Merge remote-tracking branch 'origin/NR_UE_rework_RA' into integration_2025_w11 (!3150)
Rework of NR UE RA procedures Closes #848
This commit is contained in:
@@ -1380,15 +1380,22 @@ int set_default_nta_offset(frequency_range_t freq_range, uint32_t samples_per_su
|
||||
void nr_timer_start(NR_timer_t *timer)
|
||||
{
|
||||
timer->active = true;
|
||||
timer->suspended = false;
|
||||
timer->counter = 0;
|
||||
}
|
||||
|
||||
void nr_timer_stop(NR_timer_t *timer)
|
||||
{
|
||||
timer->active = false;
|
||||
timer->suspended = false;
|
||||
timer->counter = 0;
|
||||
}
|
||||
|
||||
void nr_timer_suspension(NR_timer_t *timer)
|
||||
{
|
||||
timer->suspended = !timer->suspended;
|
||||
}
|
||||
|
||||
bool nr_timer_is_active(const NR_timer_t *timer)
|
||||
{
|
||||
return timer->active;
|
||||
@@ -1399,7 +1406,7 @@ bool nr_timer_tick(NR_timer_t *timer)
|
||||
bool expired = false;
|
||||
if (timer->active) {
|
||||
timer->counter += timer->step;
|
||||
if (timer->target == UINT_MAX) // infinite target, never expires
|
||||
if (timer->target == UINT_MAX || timer->suspended) // infinite target, never expires
|
||||
return false;
|
||||
expired = nr_timer_expired(timer);
|
||||
if (expired)
|
||||
@@ -1410,7 +1417,7 @@ bool nr_timer_tick(NR_timer_t *timer)
|
||||
|
||||
bool nr_timer_expired(const NR_timer_t *timer)
|
||||
{
|
||||
if (timer->target == UINT_MAX) // infinite target, never expires
|
||||
if (timer->target == UINT_MAX || timer->suspended) // infinite target, never expires
|
||||
return false;
|
||||
return timer->counter >= timer->target;
|
||||
}
|
||||
|
||||
@@ -156,6 +156,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
bool active;
|
||||
bool suspended;
|
||||
uint32_t counter;
|
||||
uint32_t target;
|
||||
uint32_t step;
|
||||
@@ -171,6 +172,12 @@ void nr_timer_start(NR_timer_t *timer);
|
||||
* @param timer Timer to stopped
|
||||
*/
|
||||
void nr_timer_stop(NR_timer_t *timer);
|
||||
/**
|
||||
* @brief To suspend/resume a timer
|
||||
* @param timer Timer to be stopped/suspended
|
||||
*/
|
||||
void nr_timer_suspension(NR_timer_t *timer);
|
||||
|
||||
/**
|
||||
* @brief If active, it increases timer counter by an amout of units equal to step. It stops timer if expired
|
||||
* @param timer Timer to be handled
|
||||
|
||||
+4
-1
@@ -519,7 +519,7 @@ void processSlotTX(void *arg)
|
||||
bool sl_tx_action = false;
|
||||
|
||||
if (UE->if_inst)
|
||||
UE->if_inst->slot_indication(UE->Mod_id);
|
||||
UE->if_inst->slot_indication(UE->Mod_id, true);
|
||||
|
||||
if (proc->tx_slot_type == NR_UPLINK_SLOT || proc->tx_slot_type == NR_MIXED_SLOT) {
|
||||
if (UE->sl_mode == 2 && proc->tx_slot_type == NR_SIDELINK_SLOT) {
|
||||
@@ -650,6 +650,9 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE,
|
||||
}
|
||||
}
|
||||
|
||||
if (UE->if_inst)
|
||||
UE->if_inst->slot_indication(UE->Mod_id, false);
|
||||
|
||||
bool dl_slot = false;
|
||||
if (proc->rx_slot_type == NR_DOWNLINK_SLOT || proc->rx_slot_type == NR_MIXED_SLOT) {
|
||||
dl_slot = true;
|
||||
|
||||
@@ -465,6 +465,10 @@ int main(int argc, char **argv)
|
||||
get_channel_model_mode(uniqCfg);
|
||||
}
|
||||
|
||||
// Delay to allow the convergence of the IIR filter on PRACH noise measurements at gNB side
|
||||
if (IS_SOFTMODEM_RFSIM && !get_softmodem_params()->phy_test)
|
||||
sleep(3);
|
||||
|
||||
if (!get_softmodem_params()->nsa && get_softmodem_params()->emulate_l1)
|
||||
start_oai_nrue_threads();
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ void nr_mac_rrc_sync_ind(const module_id_t module_id,
|
||||
|
||||
void nr_mac_rrc_msg3_ind(const module_id_t mod_id, int rnti, int gnb_id) {}
|
||||
|
||||
void nr_mac_rrc_ra_ind(const module_id_t mod_id, int frame, bool success) {}
|
||||
void nr_mac_rrc_ra_ind(const module_id_t mod_id, bool success) {}
|
||||
|
||||
void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id) {}
|
||||
|
||||
|
||||
@@ -136,13 +136,11 @@ int main(int argc, char **argv){
|
||||
c16_t **txdata;
|
||||
int N_RB_UL = 106, delay = 0, NCS_config = 13, rootSequenceIndex = 1, threequarter_fs = 0, mu = 1, fd_occasion = 0, loglvl = OAILOG_INFO, numRA = 0, prachStartSymbol = 0;
|
||||
uint8_t snr1set = 0, ue_speed1set = 0, transmission_mode = 1, n_tx = 1, n_rx = 1, awgn_flag = 0, msg1_frequencystart = 0, num_prach_fd_occasions = 1, prach_format=0;
|
||||
uint8_t config_index = 98, prach_sequence_length = 1, restrictedSetConfig = 0, N_dur, N_t_slot, start_symbol;
|
||||
uint16_t Nid_cell = 0, preamble_tx = 0, preamble_delay, format, format0, format1;
|
||||
uint8_t config_index = 98, prach_sequence_length = 1, restrictedSetConfig = 0;
|
||||
uint16_t Nid_cell = 0, preamble_tx = 0, preamble_delay, format0, format1;
|
||||
uint32_t tx_lev = 10000, prach_errors = 0; //,tx_lev_dB;
|
||||
uint64_t SSB_positions = 0x01;
|
||||
uint16_t RA_sfn_index;
|
||||
uint8_t N_RA_slot;
|
||||
uint8_t config_period;
|
||||
int prachOccasion = 0;
|
||||
double DS_TDL = .03;
|
||||
|
||||
@@ -482,25 +480,24 @@ int main(int argc, char **argv){
|
||||
gNB->gNB_config.prach_config.num_prach_fd_occasions.value = num_prach_fd_occasions;
|
||||
gNB->gNB_config.prach_config.num_prach_fd_occasions_list = (nfapi_nr_num_prach_fd_occasions_t *) malloc(num_prach_fd_occasions*sizeof(nfapi_nr_num_prach_fd_occasions_t));
|
||||
|
||||
gNB->proc.slot_rx = slot;
|
||||
gNB->proc.slot_rx = slot;
|
||||
frequency_range_t freq_range = absoluteFrequencyPointA > 2016666 ? FR2 : FR1;
|
||||
nr_prach_info_t prach_info = get_nr_prach_occasion_info_from_index(config_index, freq_range, frame_parms->frame_type);
|
||||
int ret = get_nr_prach_sched_from_info(prach_info,
|
||||
config_index,
|
||||
frame,
|
||||
slot,
|
||||
mu,
|
||||
freq_range,
|
||||
&RA_sfn_index,
|
||||
frame_parms->frame_type);
|
||||
|
||||
int ret = get_nr_prach_info_from_index(config_index,
|
||||
(int)frame,
|
||||
(int)slot,
|
||||
absoluteFrequencyPointA,
|
||||
mu,
|
||||
frame_parms->frame_type,
|
||||
&format,
|
||||
&start_symbol,
|
||||
&N_t_slot,
|
||||
&N_dur,
|
||||
&RA_sfn_index,
|
||||
&N_RA_slot,
|
||||
&config_period);
|
||||
|
||||
if (ret == 0) {printf("No prach in %d.%d, mu %d, config_index %d\n",frame,slot,mu,config_index); exit(-1);}
|
||||
format0 = format&0xff; // first column of format from table
|
||||
format1 = (format>>8)&0xff; // second column of format from table
|
||||
if (ret == 0) {
|
||||
printf("No prach in %d.%d, mu %d, config_index %d\n", frame, slot, mu, config_index);
|
||||
exit(-1);
|
||||
}
|
||||
format0 = prach_info.format & 0xff; // first column of format from table
|
||||
format1 = (prach_info.format >> 8) & 0xff; // second column of format from table
|
||||
|
||||
if (format1 != 0xff) {
|
||||
switch(format0) {
|
||||
|
||||
@@ -72,13 +72,13 @@
|
||||
// Messages between RRC and MAC layers
|
||||
|
||||
typedef struct NRRrcMacRaInd_s {
|
||||
uint32_t frame;
|
||||
bool RA_succeeded;
|
||||
} NRRrcMacRaInd;
|
||||
|
||||
typedef struct NRRrcMacMsg3Ind_s {
|
||||
uint16_t rnti;
|
||||
int gnb_id;
|
||||
bool prepare_payload;
|
||||
} NRRrcMacMsg3Ind;
|
||||
|
||||
typedef struct NRRrcMacInacInd_s {
|
||||
|
||||
@@ -461,36 +461,6 @@ typedef struct {
|
||||
#define NR_MAX_NUM_LCGID 8
|
||||
#define MAX_RLC_SDU_SUBHEADER_SIZE 3
|
||||
|
||||
//===========
|
||||
// PRACH defs
|
||||
//===========
|
||||
|
||||
// ===============================================
|
||||
// SSB to RO mapping public defines and structures
|
||||
// ===============================================
|
||||
#define MAX_SSB_PER_RO (16) // Maximum number of SSBs that can be mapped to a single RO
|
||||
#define MAX_TDM (7) // Maximum nb of PRACH occasions TDMed in a slot
|
||||
#define MAX_FDM (8) // Maximum nb of PRACH occasions FDMed in a slot
|
||||
|
||||
// PRACH occasion details
|
||||
typedef struct prach_occasion_info {
|
||||
uint8_t start_symbol; // 0 - 13 (14 symbols in a slot)
|
||||
uint8_t fdm; // 0-7 (possible values of msg1-FDM: 1, 2, 4 or 8)
|
||||
uint8_t slot; // 0 - 159 (maximum number of slots in a 10ms frame - @ 240kHz)
|
||||
uint8_t frame; // 0 - 15 (maximum number of frames in a 160ms association pattern)
|
||||
uint8_t mapped_ssb_idx[MAX_SSB_PER_RO]; // List of mapped SSBs
|
||||
uint8_t nb_mapped_ssb;
|
||||
uint16_t format; // RO preamble format
|
||||
} prach_occasion_info_t;
|
||||
|
||||
// PRACH occasion slot details
|
||||
// A PRACH occasion slot is a series of PRACH occasions in time (symbols) and frequency
|
||||
typedef struct prach_occasion_slot {
|
||||
prach_occasion_info_t *prach_occasion; // Starting symbol of each PRACH occasions in a slot
|
||||
uint8_t nb_of_prach_occasion_in_time;
|
||||
uint8_t nb_of_prach_occasion_in_freq;
|
||||
} prach_occasion_slot_t;
|
||||
|
||||
//=========
|
||||
// DCI defs
|
||||
//=========
|
||||
|
||||
@@ -571,34 +571,33 @@ NR_tda_info_t get_dl_tda_info(const NR_UE_DL_BWP_t *dl_BWP,
|
||||
return tda_info;
|
||||
}
|
||||
|
||||
uint16_t get_NCS(uint8_t index, uint16_t format0, uint8_t restricted_set_config) {
|
||||
|
||||
LOG_D(MAC,"get_NCS: indx %d,format0 %d, restriced_set_config %d\n",
|
||||
index,format0,restricted_set_config);
|
||||
uint16_t get_NCS(uint8_t index, uint16_t format0, uint8_t restricted_set_config)
|
||||
{
|
||||
LOG_D(NR_MAC, "get_NCS: indx %d,format0 %d, restriced_set_config %d\n", index, format0, restricted_set_config);
|
||||
|
||||
if (format0 < 3) {
|
||||
switch(restricted_set_config){
|
||||
switch (restricted_set_config) {
|
||||
case 0:
|
||||
return(NCS_unrestricted_delta_f_RA_125[index]);
|
||||
case 1:
|
||||
return(NCS_restricted_TypeA_delta_f_RA_125[index]);
|
||||
case 2:
|
||||
return(NCS_restricted_TypeB_delta_f_RA_125[index]);
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid restricted set config value %d",restricted_set_config);
|
||||
default:
|
||||
AssertFatal(false, "Invalid restricted set config value %d", restricted_set_config);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (format0 == 3) {
|
||||
switch(restricted_set_config){
|
||||
switch (restricted_set_config) {
|
||||
case 0:
|
||||
return(NCS_unrestricted_delta_f_RA_5[index]);
|
||||
case 1:
|
||||
return(NCS_restricted_TypeA_delta_f_RA_5[index]);
|
||||
case 2:
|
||||
return(NCS_restricted_TypeB_delta_f_RA_5[index]);
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid restricted set config value %d",restricted_set_config);
|
||||
default:
|
||||
AssertFatal(false, "Invalid restricted set config value %d", restricted_set_config);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1418,11 +1417,9 @@ static const int64_t table_6_3_3_2_4_prachConfig_Index[256][10] = {
|
||||
{0xa3, 0xb3, 1, 0, -1, 733007751850, 2, 1, 2, 6} // (subframe number :1,3,5,7,…,37,39)
|
||||
};
|
||||
|
||||
int get_format0(uint8_t index,
|
||||
uint8_t unpaired,
|
||||
frequency_range_t frequency_range){
|
||||
|
||||
uint16_t format=0;
|
||||
int get_format0(uint8_t index, uint8_t unpaired, frequency_range_t frequency_range)
|
||||
{
|
||||
int format = 0;
|
||||
if (unpaired) {
|
||||
if (frequency_range==FR1)
|
||||
format = table_6_3_3_2_3_prachConfig_Index[index][0];
|
||||
@@ -1438,23 +1435,6 @@ int get_format0(uint8_t index,
|
||||
return format;
|
||||
}
|
||||
|
||||
const int64_t *get_prach_config_info(frequency_range_t freq_range, uint8_t index, uint8_t unpaired)
|
||||
{
|
||||
const int64_t *prach_config_info_p;
|
||||
|
||||
if (freq_range == FR2) { //FR2
|
||||
prach_config_info_p = table_6_3_3_2_4_prachConfig_Index[index];
|
||||
}
|
||||
else { // FR1
|
||||
if (unpaired)
|
||||
prach_config_info_p = table_6_3_3_2_3_prachConfig_Index[index];
|
||||
else
|
||||
prach_config_info_p = table_6_3_3_2_2_prachConfig_Index[index];
|
||||
} // FR2 / FR1
|
||||
|
||||
return prach_config_info_p;
|
||||
}
|
||||
|
||||
void find_aggregation_candidates(uint8_t *aggregation_level,
|
||||
uint8_t *nr_of_candidates,
|
||||
const NR_SearchSpace_t *ss,
|
||||
@@ -1567,97 +1547,83 @@ void set_monitoring_periodicity_offset(NR_SearchSpace_t *ss,
|
||||
}
|
||||
|
||||
|
||||
int get_nr_prach_occasion_info_from_index(uint8_t index,
|
||||
uint32_t pointa,
|
||||
uint8_t mu,
|
||||
uint8_t unpaired,
|
||||
uint16_t *format,
|
||||
uint8_t *start_symbol,
|
||||
uint8_t *N_t_slot,
|
||||
uint8_t *N_dur,
|
||||
uint8_t *N_RA_slot,
|
||||
uint16_t *N_RA_sfn,
|
||||
uint8_t *max_association_period)
|
||||
nr_prach_info_t get_nr_prach_occasion_info_from_index(uint8_t index, frequency_range_t freq_range, uint8_t unpaired)
|
||||
{
|
||||
int x;
|
||||
uint64_t s_map;
|
||||
uint8_t format2 = 0xff;
|
||||
if (pointa > 2016666) { //FR2
|
||||
x = table_6_3_3_2_4_prachConfig_Index[index][2];
|
||||
s_map = table_6_3_3_2_4_prachConfig_Index[index][5];
|
||||
*N_RA_sfn += count_bits64(s_map);
|
||||
*N_RA_slot = table_6_3_3_2_4_prachConfig_Index[index][7]; // Number of RACH slots within a subframe
|
||||
*max_association_period = 160/(x * 10);
|
||||
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
|
||||
*start_symbol = table_6_3_3_2_4_prachConfig_Index[index][6];//multiple prach occasions in diff slot
|
||||
*N_t_slot = table_6_3_3_2_4_prachConfig_Index[index][8];
|
||||
*N_dur = table_6_3_3_2_4_prachConfig_Index[index][9];
|
||||
if (table_6_3_3_2_4_prachConfig_Index[index][1] != -1)
|
||||
format2 = (uint8_t) table_6_3_3_2_4_prachConfig_Index[index][1];
|
||||
|
||||
*format = ((uint8_t) table_6_3_3_2_4_prachConfig_Index[index][0]) | (format2<<8);
|
||||
LOG_D(MAC,"Getting Total PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_sfn = %u\n",
|
||||
index,
|
||||
pointa,
|
||||
mu,
|
||||
unpaired,
|
||||
*start_symbol,
|
||||
*N_t_slot,
|
||||
*N_dur,
|
||||
*N_RA_sfn);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
if (unpaired) {
|
||||
x = table_6_3_3_2_3_prachConfig_Index[index][2];
|
||||
s_map = table_6_3_3_2_3_prachConfig_Index[index][4];
|
||||
*N_RA_sfn += count_bits64(s_map);
|
||||
*N_RA_slot = table_6_3_3_2_3_prachConfig_Index[index][6]; // Number of RACH slots within a subframe
|
||||
*max_association_period = 160/(x * 10);
|
||||
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
|
||||
*start_symbol = table_6_3_3_2_3_prachConfig_Index[index][5];
|
||||
*N_t_slot = table_6_3_3_2_3_prachConfig_Index[index][7];
|
||||
*N_dur = table_6_3_3_2_3_prachConfig_Index[index][8];
|
||||
if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1)
|
||||
format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[index][1];
|
||||
*format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2<<8);
|
||||
LOG_D(NR_MAC,"Getting Total PRACH info from index %d (col %lu ) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_sfn = %u\n",
|
||||
index, table_6_3_3_2_3_prachConfig_Index[index][6],
|
||||
pointa,
|
||||
mu,
|
||||
unpaired,
|
||||
*start_symbol,
|
||||
*N_t_slot,
|
||||
*N_dur,
|
||||
*N_RA_sfn);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else { // FDD
|
||||
x = table_6_3_3_2_2_prachConfig_Index[index][2];
|
||||
s_map = table_6_3_3_2_2_prachConfig_Index[index][4];
|
||||
*N_RA_sfn += count_bits64(s_map);
|
||||
*N_RA_slot = table_6_3_3_2_2_prachConfig_Index[index][6];
|
||||
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
|
||||
*start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5];
|
||||
*N_t_slot = table_6_3_3_2_2_prachConfig_Index[index][7];
|
||||
*N_dur = table_6_3_3_2_2_prachConfig_Index[index][8];
|
||||
if (table_6_3_3_2_2_prachConfig_Index[index][1] != -1)
|
||||
format2 = (uint8_t) table_6_3_3_2_2_prachConfig_Index[index][1];
|
||||
*format = ((uint8_t) table_6_3_3_2_2_prachConfig_Index[index][0]) | (format2<<8);
|
||||
LOG_D(MAC,"Getting Total PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n",
|
||||
index,
|
||||
pointa,
|
||||
mu,
|
||||
unpaired,
|
||||
*start_symbol,
|
||||
*N_t_slot,
|
||||
*N_dur);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
nr_prach_info_t info;
|
||||
if (freq_range == FR2) {
|
||||
info.x = table_6_3_3_2_4_prachConfig_Index[index][2];
|
||||
info.y = table_6_3_3_2_4_prachConfig_Index[index][3];
|
||||
info.y2 = table_6_3_3_2_4_prachConfig_Index[index][4];
|
||||
info.s_map = table_6_3_3_2_4_prachConfig_Index[index][5];
|
||||
info.N_RA_sfn += count_bits64(info.s_map);
|
||||
info.N_RA_slot = table_6_3_3_2_4_prachConfig_Index[index][7];
|
||||
info.max_association_period = 160 / (info.x * 10);
|
||||
info.start_symbol = table_6_3_3_2_4_prachConfig_Index[index][6];
|
||||
info.N_t_slot = table_6_3_3_2_4_prachConfig_Index[index][8];
|
||||
info.N_dur = table_6_3_3_2_4_prachConfig_Index[index][9];
|
||||
if (table_6_3_3_2_4_prachConfig_Index[index][1] != -1)
|
||||
format2 = (uint8_t)table_6_3_3_2_4_prachConfig_Index[index][1];
|
||||
info.format = ((uint8_t)table_6_3_3_2_4_prachConfig_Index[index][0]) | (format2 << 8);
|
||||
LOG_D(NR_MAC,
|
||||
"PRACH info from index %d frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_sfn = %u\n",
|
||||
index,
|
||||
unpaired,
|
||||
info.start_symbol,
|
||||
info.N_t_slot,
|
||||
info.N_dur,
|
||||
info.N_RA_sfn);
|
||||
return info;
|
||||
}
|
||||
|
||||
if (unpaired) { // FR1 TDD
|
||||
info.x = table_6_3_3_2_3_prachConfig_Index[index][2];
|
||||
info.y = table_6_3_3_2_3_prachConfig_Index[index][3];
|
||||
info.y2 = -1;
|
||||
info.s_map = table_6_3_3_2_3_prachConfig_Index[index][4];
|
||||
info.N_RA_sfn += count_bits64(info.s_map);
|
||||
info.N_RA_slot = table_6_3_3_2_3_prachConfig_Index[index][6];
|
||||
info.max_association_period = 160 / (info.x * 10);
|
||||
info.start_symbol = table_6_3_3_2_3_prachConfig_Index[index][5];
|
||||
info.N_t_slot = table_6_3_3_2_3_prachConfig_Index[index][7];
|
||||
info.N_dur = table_6_3_3_2_3_prachConfig_Index[index][8];
|
||||
if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1)
|
||||
format2 = (uint8_t)table_6_3_3_2_3_prachConfig_Index[index][1];
|
||||
info.format = ((uint8_t)table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2 << 8);
|
||||
LOG_D(NR_MAC,
|
||||
"PRACH info from index %d (col %lu) frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_sfn = %u\n",
|
||||
index,
|
||||
table_6_3_3_2_3_prachConfig_Index[index][6],
|
||||
unpaired,
|
||||
info.start_symbol,
|
||||
info.N_t_slot,
|
||||
info.N_dur,
|
||||
info.N_RA_sfn);
|
||||
return info;
|
||||
}
|
||||
|
||||
// FR1 FDD
|
||||
info.x = table_6_3_3_2_2_prachConfig_Index[index][2];
|
||||
info.y = table_6_3_3_2_2_prachConfig_Index[index][3];
|
||||
info.y2 = -1;
|
||||
info.s_map = table_6_3_3_2_2_prachConfig_Index[index][4];
|
||||
info.N_RA_sfn += count_bits64(info.s_map);
|
||||
info.N_RA_slot = table_6_3_3_2_2_prachConfig_Index[index][6];
|
||||
info.max_association_period = 160 / (info.x * 10);
|
||||
info.start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5];
|
||||
info.N_t_slot = table_6_3_3_2_2_prachConfig_Index[index][7];
|
||||
info.N_dur = table_6_3_3_2_2_prachConfig_Index[index][8];
|
||||
if (table_6_3_3_2_2_prachConfig_Index[index][1] != -1)
|
||||
format2 = (uint8_t)table_6_3_3_2_2_prachConfig_Index[index][1];
|
||||
info.format = ((uint8_t)table_6_3_3_2_2_prachConfig_Index[index][0]) | (format2 << 8);
|
||||
LOG_D(NR_MAC,
|
||||
"PRACH info from index %d frame_type %u start_symbol %u N_t_slot %u N_dur %u \n",
|
||||
index,
|
||||
unpaired,
|
||||
info.start_symbol,
|
||||
info.N_t_slot,
|
||||
info.N_dur);
|
||||
return info;
|
||||
}
|
||||
|
||||
uint16_t get_nr_prach_format_from_index(uint8_t index, uint32_t pointa, uint8_t unpaired)
|
||||
@@ -1682,177 +1648,83 @@ uint16_t get_nr_prach_format_from_index(uint8_t index, uint32_t pointa, uint8_t
|
||||
return format;
|
||||
}
|
||||
|
||||
int get_nr_prach_info_from_index(uint8_t index,
|
||||
int frame,
|
||||
int slot,
|
||||
uint32_t pointa,
|
||||
uint8_t mu,
|
||||
uint8_t unpaired,
|
||||
uint16_t *format,
|
||||
uint8_t *start_symbol,
|
||||
uint8_t *N_t_slot,
|
||||
uint8_t *N_dur,
|
||||
uint16_t *RA_sfn_index,
|
||||
uint8_t *N_RA_slot,
|
||||
uint8_t *config_period)
|
||||
bool get_nr_prach_sched_from_info(nr_prach_info_t info,
|
||||
int config_index,
|
||||
int frame,
|
||||
int slot,
|
||||
int mu,
|
||||
frequency_range_t freq_range,
|
||||
uint16_t *RA_sfn_index,
|
||||
uint8_t unpaired)
|
||||
{
|
||||
int x,y;
|
||||
int64_t s_map;
|
||||
uint8_t format2 = 0xff;
|
||||
|
||||
if (pointa > 2016666) { //FR2
|
||||
int y2;
|
||||
uint8_t slot_60khz;
|
||||
x = table_6_3_3_2_4_prachConfig_Index[index][2];
|
||||
y = table_6_3_3_2_4_prachConfig_Index[index][3];
|
||||
y2 = table_6_3_3_2_4_prachConfig_Index[index][4];
|
||||
if (freq_range == FR2) {
|
||||
// checking n_sfn mod x = y
|
||||
if ((frame % x) == y || (frame % x) == y2) {
|
||||
slot_60khz = slot >> (mu - 2); // in table slots are numbered wrt 60kHz
|
||||
s_map = table_6_3_3_2_4_prachConfig_Index[index][5];
|
||||
if ((s_map >> slot_60khz) & 0x01) {
|
||||
if ((frame % info.x) == info.y || (frame % info.x) == info.y2) {
|
||||
int slot_60khz = slot >> (mu - 2); // in table slots are numbered wrt 60kHz
|
||||
if ((info.s_map >> slot_60khz) & 0x01) {
|
||||
for(int i = 0; i <= slot_60khz ;i++) {
|
||||
if ((s_map >> i) & 0x01) {
|
||||
if ((info.s_map >> i) & 0x01) {
|
||||
(*RA_sfn_index)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (((s_map >> slot_60khz) & 0x01)) {
|
||||
*N_RA_slot = table_6_3_3_2_4_prachConfig_Index[index][7]; // Number of RACH slots within a subframe
|
||||
if (((info.s_map >> slot_60khz) & 0x01)) {
|
||||
if (mu == 3) {
|
||||
if ((*N_RA_slot == 1) && (slot % 2 == 0) )
|
||||
return 0; // no prach in even slots @ 120kHz for 1 prach per 60khz slot
|
||||
if ((info.N_RA_slot == 1) && (slot % 2 == 0))
|
||||
return false; // no prach in even slots @ 120kHz for 1 prach per 60khz slot
|
||||
}
|
||||
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
|
||||
*config_period = x;
|
||||
*start_symbol = table_6_3_3_2_4_prachConfig_Index[index][6];
|
||||
*N_t_slot = table_6_3_3_2_4_prachConfig_Index[index][8];
|
||||
*N_dur = table_6_3_3_2_4_prachConfig_Index[index][9];
|
||||
if (table_6_3_3_2_4_prachConfig_Index[index][1] != -1)
|
||||
format2 = (uint8_t) table_6_3_3_2_4_prachConfig_Index[index][1];
|
||||
*format = ((uint8_t) table_6_3_3_2_4_prachConfig_Index[index][0]) | (format2<<8);
|
||||
LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_slot %u RA_sfn_index %u\n",
|
||||
frame,
|
||||
slot,
|
||||
index,
|
||||
pointa,
|
||||
mu,
|
||||
unpaired,
|
||||
*start_symbol,
|
||||
*N_t_slot,
|
||||
*N_dur,
|
||||
*N_RA_slot,
|
||||
*RA_sfn_index);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0; // no prach in current slot
|
||||
return true;
|
||||
} else
|
||||
return false; // no prach in current slot
|
||||
}
|
||||
else
|
||||
return 0; // no prach in current frame
|
||||
}
|
||||
else {
|
||||
uint8_t subframe;
|
||||
if (unpaired) {
|
||||
x = table_6_3_3_2_3_prachConfig_Index[index][2];
|
||||
y = table_6_3_3_2_3_prachConfig_Index[index][3];
|
||||
if ((frame % x) == y) {
|
||||
subframe = slot >> mu;
|
||||
s_map = table_6_3_3_2_3_prachConfig_Index[index][4];
|
||||
if ((s_map >> subframe) & 0x01) {
|
||||
return false; // no prach in current frame
|
||||
} else {
|
||||
if (unpaired) { // TDD
|
||||
if ((frame % info.x) == info.y) {
|
||||
int subframe = slot >> mu;
|
||||
if ((info.s_map >> subframe) & 0x01) {
|
||||
for(int i = 0; i <= subframe ;i++) {
|
||||
if ((s_map >> i) & 0x01) {
|
||||
if ((info.s_map >> i) & 0x01) {
|
||||
(*RA_sfn_index)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((s_map >> subframe) & 0x01 ) {
|
||||
*N_RA_slot = table_6_3_3_2_3_prachConfig_Index[index][6]; // Number of RACH slots within a subframe
|
||||
if (index >= 67) {
|
||||
if ((mu == 1) && (*N_RA_slot <= 1) && (slot % 2 == 0))
|
||||
return 0; // no prach in even slots @ 30kHz for 1 prach per subframe
|
||||
if ((info.s_map >> subframe) & 0x01) {
|
||||
if (config_index >= 67) {
|
||||
if ((mu == 1) && (info.N_RA_slot <= 1) && (slot % 2 == 0))
|
||||
return false; // no prach in even slots @ 30kHz for 1 prach per subframe
|
||||
} else {
|
||||
if ((slot % 2) && (mu > 0))
|
||||
return 0; // slot does not contain start symbol of this prach time resource
|
||||
return false; // slot does not contain start symbol of this prach time resource
|
||||
}
|
||||
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL) {
|
||||
*config_period = x;
|
||||
*start_symbol = table_6_3_3_2_3_prachConfig_Index[index][5];
|
||||
*N_t_slot = table_6_3_3_2_3_prachConfig_Index[index][7];
|
||||
*N_dur = table_6_3_3_2_3_prachConfig_Index[index][8];
|
||||
if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1)
|
||||
format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[index][1];
|
||||
*format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2<<8);
|
||||
LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d (col 6 %lu) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_slot %u RA_sfn_index %u \n",
|
||||
frame,
|
||||
slot,
|
||||
index,
|
||||
table_6_3_3_2_3_prachConfig_Index[index][6],
|
||||
pointa,
|
||||
mu,
|
||||
unpaired,
|
||||
*start_symbol,
|
||||
*N_t_slot,
|
||||
*N_dur,
|
||||
*N_RA_slot,
|
||||
*RA_sfn_index);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0; // no prach in current slot
|
||||
}
|
||||
else
|
||||
return 0; // no prach in current frame
|
||||
}
|
||||
else { // FDD
|
||||
x = table_6_3_3_2_2_prachConfig_Index[index][2];
|
||||
y = table_6_3_3_2_2_prachConfig_Index[index][3];
|
||||
if ((frame % x) == y) {
|
||||
subframe = slot >> mu;
|
||||
s_map = table_6_3_3_2_2_prachConfig_Index[index][4];
|
||||
if ((s_map>>subframe) & 0x01) {
|
||||
*N_RA_slot = table_6_3_3_2_2_prachConfig_Index[index][6]; // Number of RACH slots within a subframe
|
||||
if (index >= 87) {
|
||||
if ((mu == 1) && (*N_RA_slot <= 1) && (slot % 2 == 0)) {
|
||||
return 0; // no prach in even slots @ 30kHz for 1 prach per subframe
|
||||
return true;
|
||||
} else
|
||||
return false; // no prach in current slot
|
||||
} else
|
||||
return false; // no prach in current frame
|
||||
} else { // FDD
|
||||
if ((frame % info.x) == info.y) {
|
||||
int subframe = slot >> mu;
|
||||
if ((info.s_map >> subframe) & 0x01) {
|
||||
if (config_index >= 87) {
|
||||
if ((mu == 1) && (info.N_RA_slot <= 1) && (slot % 2 == 0)) {
|
||||
return false; // no prach in even slots @ 30kHz for 1 prach per subframe
|
||||
}
|
||||
} else {
|
||||
if ((slot % 2) && (mu > 0))
|
||||
return 0; // slot does not contain start symbol of this prach time resource
|
||||
}
|
||||
for(int i = 0; i <= subframe ; i++) {
|
||||
if ((s_map >> i) & 0x01) {
|
||||
if ((info.s_map >> i) & 0x01) {
|
||||
(*RA_sfn_index)++;
|
||||
}
|
||||
}
|
||||
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
|
||||
*start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5];
|
||||
*config_period = x;
|
||||
*N_t_slot = table_6_3_3_2_2_prachConfig_Index[index][7];
|
||||
*N_dur = table_6_3_3_2_2_prachConfig_Index[index][8];
|
||||
if (table_6_3_3_2_2_prachConfig_Index[index][1] != -1)
|
||||
format2 = (uint8_t) table_6_3_3_2_2_prachConfig_Index[index][1];
|
||||
*format = ((uint8_t) table_6_3_3_2_2_prachConfig_Index[index][0]) | (format2<<8);
|
||||
LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n",
|
||||
frame,
|
||||
slot,
|
||||
index,
|
||||
pointa,
|
||||
mu,
|
||||
unpaired,
|
||||
*start_symbol,
|
||||
*N_t_slot,
|
||||
*N_dur);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0; // no prach in current slot
|
||||
}
|
||||
else
|
||||
return 0; // no prach in current frame
|
||||
return true;
|
||||
} else
|
||||
return false; // no prach in current slot
|
||||
} else
|
||||
return false; // no prach in current frame
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,20 @@ typedef enum {
|
||||
pusch_len2 = 2
|
||||
} pusch_maxLength_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t format;
|
||||
uint32_t start_symbol;
|
||||
uint32_t N_t_slot;
|
||||
uint32_t N_dur;
|
||||
uint32_t N_RA_slot;
|
||||
uint32_t N_RA_sfn;
|
||||
uint32_t max_association_period;
|
||||
int x;
|
||||
int y;
|
||||
int y2;
|
||||
uint64_t s_map;
|
||||
} nr_prach_info_t;
|
||||
|
||||
uint32_t get_Y(const NR_SearchSpace_t *ss, int slot, rnti_t rnti);
|
||||
|
||||
uint8_t get_BG(uint32_t A, uint16_t R);
|
||||
@@ -144,31 +158,16 @@ void find_aggregation_candidates(uint8_t *aggregation_level,
|
||||
|
||||
uint16_t get_nr_prach_format_from_index(uint8_t index, uint32_t pointa, uint8_t unpaired);
|
||||
|
||||
int get_nr_prach_info_from_index(uint8_t index,
|
||||
int frame,
|
||||
int slot,
|
||||
uint32_t pointa,
|
||||
uint8_t mu,
|
||||
uint8_t unpaired,
|
||||
uint16_t *format,
|
||||
uint8_t *start_symbol,
|
||||
uint8_t *N_t_slot,
|
||||
uint8_t *N_dur,
|
||||
uint16_t *RA_sfn_index,
|
||||
uint8_t *N_RA_slot,
|
||||
uint8_t *config_period);
|
||||
bool get_nr_prach_sched_from_info(nr_prach_info_t info,
|
||||
int config_index,
|
||||
int frame,
|
||||
int slot,
|
||||
int mu,
|
||||
frequency_range_t freq_range,
|
||||
uint16_t *RA_sfn_index,
|
||||
uint8_t unpaired);
|
||||
|
||||
int get_nr_prach_occasion_info_from_index(uint8_t index,
|
||||
uint32_t pointa,
|
||||
uint8_t mu,
|
||||
uint8_t unpaired,
|
||||
uint16_t *format,
|
||||
uint8_t *start_symbol,
|
||||
uint8_t *N_t_slot,
|
||||
uint8_t *N_dur,
|
||||
uint8_t *N_RA_slot,
|
||||
uint16_t *N_RA_sfn,
|
||||
uint8_t *max_association_period);
|
||||
nr_prach_info_t get_nr_prach_occasion_info_from_index(uint8_t index, frequency_range_t freq_range, uint8_t unpaired);
|
||||
|
||||
uint8_t get_pusch_mcs_table(long *mcs_Table,
|
||||
int is_tp,
|
||||
@@ -186,9 +185,7 @@ int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig, long transformPrec
|
||||
|
||||
uint8_t get_pdsch_mcs_table(long *mcs_Table, int dci_format, int rnti_type, int ss_type);
|
||||
|
||||
int get_format0(uint8_t index, uint8_t unpaired,frequency_range_t);
|
||||
|
||||
const int64_t *get_prach_config_info(frequency_range_t freq_range, uint8_t index, uint8_t unpaired);
|
||||
int get_format0(uint8_t index, uint8_t unpaired, frequency_range_t frequency_range);
|
||||
|
||||
uint16_t get_NCS(uint8_t index, uint16_t format, uint8_t restricted_set_config);
|
||||
int compute_pucch_crc_size(int O_uci);
|
||||
|
||||
@@ -44,6 +44,26 @@
|
||||
#include "oai_asn1.h"
|
||||
#include "executables/position_interface.h"
|
||||
|
||||
// Build the list of all the valid/transmitted SSBs according to the config
|
||||
static void build_ssb_list(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
// Create the list of transmitted SSBs
|
||||
memset(&mac->ssb_list, 0, sizeof(ssb_list_info_t));
|
||||
ssb_list_info_t *ssb_list = &mac->ssb_list;
|
||||
fapi_nr_config_request_t *cfg = &mac->phy_config.config_req;
|
||||
ssb_list->nb_tx_ssb = 0;
|
||||
|
||||
for (int ssb_index = 0; ssb_index < MAX_NB_SSB; ssb_index++) {
|
||||
uint32_t curr_mask = cfg->ssb_table.ssb_mask_list[ssb_index / 32].ssb_mask;
|
||||
// check if if current SSB is transmitted
|
||||
if ((curr_mask >> (31 - (ssb_index % 32))) & 0x01) {
|
||||
ssb_list->nb_ssb_per_index[ssb_index] = ssb_list->nb_tx_ssb;
|
||||
ssb_list->nb_tx_ssb++;
|
||||
} else
|
||||
ssb_list->nb_ssb_per_index[ssb_index] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void set_tdd_config_nr_ue(fapi_nr_tdd_table_t *tdd_table, const frame_structure_t *fs)
|
||||
{
|
||||
tdd_table->tdd_period_in_slots = fs->numb_slots_period;
|
||||
@@ -187,8 +207,7 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo
|
||||
else {
|
||||
// If absent, the UE applies the SCS as derived from the prach-ConfigurationIndex (for 839)
|
||||
int config_index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex;
|
||||
const int64_t *prach_config_info_p = get_prach_config_info(mac->frequency_range, config_index, frame_type);
|
||||
int format = prach_config_info_p[0];
|
||||
int format = get_format0(config_index, frame_type, mac->frequency_range);
|
||||
cfg->prach_config.prach_sub_c_spacing = get_delta_f_RA_long(format);
|
||||
}
|
||||
|
||||
@@ -411,8 +430,7 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t
|
||||
else {
|
||||
// If absent, the UE applies the SCS as derived from the prach-ConfigurationIndex (for 839)
|
||||
int config_index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex;
|
||||
const int64_t *prach_config_info_p = get_prach_config_info(mac->frequency_range, config_index, frame_type);
|
||||
int format = prach_config_info_p[0];
|
||||
int format = get_format0(config_index, frame_type, mac->frequency_range);
|
||||
cfg->prach_config.prach_sub_c_spacing = format == 3 ? 5 : 4;
|
||||
}
|
||||
|
||||
@@ -1399,7 +1417,7 @@ static void setup_srsconfig(NR_UE_UL_BWP_t *bwp, NR_SRS_Config_t *source, NR_SRS
|
||||
}
|
||||
}
|
||||
|
||||
static NR_UE_DL_BWP_t *get_dl_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup)
|
||||
NR_UE_DL_BWP_t *get_dl_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup)
|
||||
{
|
||||
NR_UE_DL_BWP_t *bwp = NULL;
|
||||
for (int i = 0; i < mac->dl_BWPs.count; i++) {
|
||||
@@ -1423,7 +1441,7 @@ static NR_UE_DL_BWP_t *get_dl_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, b
|
||||
return bwp;
|
||||
}
|
||||
|
||||
static NR_UE_UL_BWP_t *get_ul_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup)
|
||||
NR_UE_UL_BWP_t *get_ul_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup)
|
||||
{
|
||||
NR_UE_UL_BWP_t *bwp = NULL;
|
||||
for (int i = 0; i < mac->ul_BWPs.count; i++) {
|
||||
@@ -1746,14 +1764,16 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *si
|
||||
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);
|
||||
|
||||
// Build the list of all the valid/transmitted SSBs according to the config
|
||||
LOG_D(NR_MAC, "Build SSB list\n");
|
||||
build_ssb_list(mac);
|
||||
|
||||
int bwp_id = 0;
|
||||
configure_common_BWP_dl(mac, bwp_id, &scc->downlinkConfigCommon.initialDownlinkBWP);
|
||||
if (scc->uplinkConfigCommon) {
|
||||
mac->timeAlignmentTimerCommon = scc->uplinkConfigCommon->timeAlignmentTimerCommon;
|
||||
configure_common_BWP_ul(mac,
|
||||
0, // bwp-id
|
||||
&scc->uplinkConfigCommon->initialUplinkBWP);
|
||||
configure_common_BWP_ul(mac, 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
|
||||
@@ -1767,9 +1787,6 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *si
|
||||
if (mac->state == UE_RECEIVING_SIB && can_start_ra)
|
||||
mac->state = UE_PERFORMING_RA;
|
||||
|
||||
// Setup the SSB to Rach Occasions mapping according to the config
|
||||
build_ssb_to_ro_map(mac);
|
||||
|
||||
if (!get_softmodem_params()->emulate_l1)
|
||||
mac->if_module->phy_config_request(&mac->phy_config);
|
||||
ret = pthread_mutex_unlock(&mac->if_mutex);
|
||||
@@ -1818,6 +1835,10 @@ static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac,
|
||||
mac->dmrs_TypeA_Position = scc->dmrs_TypeA_Position;
|
||||
UPDATE_IE(mac->tdd_UL_DL_ConfigurationCommon, scc->tdd_UL_DL_ConfigurationCommon, NR_TDD_UL_DL_ConfigCommon_t);
|
||||
config_common_ue(mac, scc, cc_idP);
|
||||
// Build the list of all the valid/transmitted SSBs according to the config
|
||||
LOG_D(NR_MAC,"Build SSB list\n");
|
||||
build_ssb_list(mac);
|
||||
|
||||
const int bwp_id = 0;
|
||||
if (scc->downlinkConfigCommon)
|
||||
configure_common_BWP_dl(mac, bwp_id, scc->downlinkConfigCommon->initialDownlinkBWP);
|
||||
@@ -2625,11 +2646,6 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id,
|
||||
if (ue_Capability)
|
||||
handle_mac_uecap_info(mac, ue_Capability);
|
||||
|
||||
// Setup the SSB to Rach Occasions mapping according to the config
|
||||
// Only if RACH is configured for current BWP
|
||||
if (mac->current_UL_BWP->rach_ConfigCommon)
|
||||
build_ssb_to_ro_map(mac);
|
||||
|
||||
if (!mac->dl_config_request || !mac->ul_config_request)
|
||||
ue_init_config_request(mac, mac->frame_structure.numb_slots_frame);
|
||||
ret = pthread_mutex_unlock(&mac->if_mutex);
|
||||
|
||||
@@ -79,23 +79,7 @@
|
||||
/*!\brief value for indicating BSR Timer is not running */
|
||||
#define NR_MAC_UE_BSR_TIMER_NOT_RUNNING (0xFFFF)
|
||||
|
||||
// ================================================
|
||||
// SSB to RO mapping private defines and structures
|
||||
// ================================================
|
||||
|
||||
#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD (16) // Maximum association period is 16
|
||||
#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max association pattern period is 160ms and minimum PRACH configuration period is 10ms
|
||||
#define MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max nb of association periods in an association pattern period of 160ms
|
||||
#define MAX_NB_FRAME_IN_PRACH_CONF_PERIOD (16) // Max PRACH configuration period is 160ms and frame is 10ms
|
||||
#define MAX_NB_SLOT_IN_FRAME (160) // Max number of slots in a frame (@ SCS 240kHz = 160)
|
||||
#define MAX_NB_FRAME_IN_ASSOCIATION_PATTERN_PERIOD (16) // Maximum number of frames in the maximum association pattern period
|
||||
#define MAX_NB_SSB (64) // Maximum number of possible SSB indexes
|
||||
#define MAX_RO_PER_SSB (8) // Maximum number of consecutive ROs that can be mapped to an SSB according to the ssb_per_RACH config
|
||||
|
||||
// Maximum number of ROs that can be mapped to an SSB in an association pattern
|
||||
// This is to reserve enough elements in the SSBs list for each mapped ROs for a single SSB
|
||||
// An arbitrary maximum number is chosen to be safe: maximum number of slots in an association pattern * maximum number of ROs in a slot
|
||||
#define MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN (MAX_TDM*MAX_FDM*MAX_NB_SLOT_IN_FRAME*MAX_NB_FRAME_IN_ASSOCIATION_PATTERN_PERIOD)
|
||||
|
||||
// ===============
|
||||
// DCI fields defs
|
||||
@@ -169,6 +153,23 @@
|
||||
UE_STATE(UE_CONNECTED) \
|
||||
UE_STATE(UE_DETACHING)
|
||||
|
||||
// ===============================================
|
||||
// SSB to RO mapping public defines and structures
|
||||
// ===============================================
|
||||
#define MAX_SSB_PER_RO (16) // Maximum number of SSBs that can be mapped to a single RO
|
||||
#define MAX_TDM (7) // Maximum nb of PRACH occasions TDMed in a slot
|
||||
#define MAX_FDM (8) // Maximum nb of PRACH occasions FDMed in a slot
|
||||
|
||||
// PRACH occasion details
|
||||
typedef struct prach_occasion_info {
|
||||
int start_symbol; // 0 - 13 (14 symbols in a slot)
|
||||
int fdm; // 0-7 (possible values of msg1-FDM: 1, 2, 4 or 8)
|
||||
int slot;
|
||||
int format; // RO preamble format
|
||||
int frame_info[2];
|
||||
int association_period_idx;
|
||||
} prach_occasion_info_t;
|
||||
|
||||
typedef enum {
|
||||
phr_cause_prohibit_timer = 0,
|
||||
phr_cause_periodic_timer,
|
||||
@@ -272,42 +273,41 @@ static const char *const nrra_ue_text[] =
|
||||
{"UE_IDLE", "GENERATE_PREAMBLE", "WAIT_RAR", "WAIT_MSGB", "WAIT_CONTENTION_RESOLUTION", "RA_SUCCEEDED", "RA_FAILED"};
|
||||
|
||||
typedef struct {
|
||||
/// PRACH format retrieved from prach_ConfigIndex
|
||||
uint16_t prach_format;
|
||||
/// Preamble Tx Counter
|
||||
uint8_t RA_PREAMBLE_TRANSMISSION_COUNTER;
|
||||
uint8_t preamble_tx_counter;
|
||||
/// Preamble Power Ramping Counter
|
||||
uint8_t RA_PREAMBLE_POWER_RAMPING_COUNTER;
|
||||
uint8_t preamble_power_ramping_cnt;
|
||||
/// 2-step RA power offset
|
||||
int POWER_OFFSET_2STEP_RA;
|
||||
int power_offset_2step;
|
||||
/// Target received power at gNB. Baseline is range -202..-60 dBm. Depends on delta preamble, power ramping counter and step.
|
||||
int ra_PREAMBLE_RECEIVED_TARGET_POWER;
|
||||
/// PRACH index for TDD (0 ... 6) depending on TDD configuration and prachConfigIndex
|
||||
uint8_t ra_TDD_map_index;
|
||||
int ra_preamble_rx_target_power;
|
||||
/// RA Preamble Power Ramping Step in dB
|
||||
uint32_t RA_PREAMBLE_POWER_RAMPING_STEP;
|
||||
///
|
||||
uint8_t RA_PREAMBLE_BACKOFF;
|
||||
///
|
||||
uint8_t RA_SCALING_FACTOR_BI;
|
||||
/// Indicating whether it is 2-step or 4-step RA
|
||||
nr_ra_type_t RA_TYPE;
|
||||
uint32_t preamble_power_ramping_step;
|
||||
/// UE configured maximum output power
|
||||
int RA_PCMAX;
|
||||
int Pc_max;
|
||||
} NR_PRACH_RESOURCES_t;
|
||||
|
||||
typedef struct {
|
||||
float ssb_per_ro;
|
||||
int preambles_per_ssb;
|
||||
} ssb_ro_preambles_t;
|
||||
|
||||
typedef struct {
|
||||
bool active;
|
||||
uint32_t preamble_index;
|
||||
uint32_t ssb_index;
|
||||
uint32_t prach_mask;
|
||||
} NR_pdcch_order_config_t;
|
||||
|
||||
typedef struct {
|
||||
// pointer to RACH config dedicated
|
||||
NR_RACH_ConfigDedicated_t *rach_ConfigDedicated;
|
||||
/// state of RA procedure
|
||||
nrRA_UE_state_t ra_state;
|
||||
/// RA contention type
|
||||
uint8_t cfra;
|
||||
bool cfra;
|
||||
/// RA type
|
||||
nr_ra_type_t ra_type;
|
||||
/// RA rx frame offset: compensate RA rx offset introduced by OAI gNB.
|
||||
uint8_t RA_offset;
|
||||
/// MsgB SuccessRAR MAC subheader
|
||||
int8_t MsgB_R;
|
||||
int8_t MsgB_CH_ACESS_CPEXT;
|
||||
@@ -321,53 +321,51 @@ typedef struct {
|
||||
uint16_t MsgB_rnti;
|
||||
/// Temporary CRNTI
|
||||
uint16_t t_crnti;
|
||||
/// number of attempt for rach
|
||||
uint8_t RA_attempt_number;
|
||||
/// Random-access procedure flag
|
||||
bool RA_active;
|
||||
/// Random-access preamble index
|
||||
int ra_PreambleIndex;
|
||||
// When multiple SSBs per RO is configured, this indicates which one is selected in this RO -> this is used to properly compute the PRACH preamble
|
||||
uint8_t ssb_nb_in_ro;
|
||||
|
||||
/// Random-access window counter
|
||||
int16_t RA_window_cnt;
|
||||
/// Flag to monitor if matching RAPID was received in RAR
|
||||
uint8_t RA_RAPID_found;
|
||||
/// Flag to monitor if BI was received in RAR
|
||||
uint8_t RA_BI_found;
|
||||
/// Random-access backoff counter
|
||||
int16_t RA_backoff_indicator;
|
||||
/// Flag to indicate whether preambles Group A was used
|
||||
uint8_t RA_usedGroupA;
|
||||
/// RA backoff counter
|
||||
int16_t RA_backoff_cnt;
|
||||
int zeroCorrelationZoneConfig;
|
||||
int restricted_set_config;
|
||||
// selected SSB for RACH (not the SSB-Index but the cumulative index, excluding not trasmitted SSBs)
|
||||
int ra_ssb;
|
||||
/// Random-access response window timer
|
||||
NR_timer_t response_window_timer;
|
||||
int response_window_setup_time;
|
||||
/// Random-access backoff timer
|
||||
NR_timer_t RA_backoff_timer;
|
||||
int RA_backoff_limit;
|
||||
uint8_t scaling_factor_bi;
|
||||
/// Flag to indicate whether preambles Group A is selected
|
||||
bool RA_GroupA;
|
||||
/// RA max number of preamble transmissions
|
||||
int preambleTransMax;
|
||||
/// Nb of preambles per SSB
|
||||
long cb_preambles_per_ssb;
|
||||
int starting_preamble_nb;
|
||||
|
||||
/// Received TPC command (in dB) from RAR
|
||||
int8_t Msg3_TPC;
|
||||
/// Flag to indicate whether it is the first Msg3 to be transmitted
|
||||
bool first_Msg3;
|
||||
/// RA Msg3 size in bytes
|
||||
uint8_t Msg3_size;
|
||||
/// Msg3 buffer
|
||||
uint8_t *Msg3_buffer;
|
||||
|
||||
bool msg3_C_RNTI;
|
||||
|
||||
// initial Random Access Preamble power
|
||||
int preambleRxTargetPower;
|
||||
int msg3_deltaPreamble;
|
||||
int preambleReceivedTargetPower_config;
|
||||
/// Random-access Contention Resolution Timer
|
||||
NR_timer_t contention_resolution_timer;
|
||||
/// Transmitted UE Contention Resolution Identifier
|
||||
uint8_t cont_res_id[6];
|
||||
|
||||
/// BeamfailurerecoveryConfig
|
||||
NR_BeamFailureRecoveryConfig_t RA_BeamFailureRecoveryConfig;
|
||||
NR_pdcch_order_config_t pdcch_order;
|
||||
|
||||
NR_PRACH_RESOURCES_t prach_resources;
|
||||
|
||||
bool new_ssb;
|
||||
int num_fd_occasions;
|
||||
int ra_config_index;
|
||||
ssb_ro_preambles_t ssb_ro_config;
|
||||
int association_periods;
|
||||
prach_occasion_info_t sched_ro_info;
|
||||
int ro_mask_index;
|
||||
} RA_config_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -435,39 +433,8 @@ typedef struct NR_UL_TIME_ALIGNMENT {
|
||||
int slot;
|
||||
} NR_UL_TIME_ALIGNMENT_t;
|
||||
|
||||
// The PRACH Config period is a series of selected slots in one or multiple frames
|
||||
typedef struct prach_conf_period {
|
||||
prach_occasion_slot_t prach_occasion_slot_map[MAX_NB_FRAME_IN_PRACH_CONF_PERIOD][MAX_NB_SLOT_IN_FRAME];
|
||||
uint16_t nb_of_prach_occasion; // Total number of PRACH occasions in the PRACH Config period
|
||||
uint8_t nb_of_frame; // Size of the PRACH Config period in number of 10ms frames
|
||||
uint8_t nb_of_slot; // Nb of slots in each frame
|
||||
} prach_conf_period_t;
|
||||
|
||||
// The association period is a series of PRACH Config periods
|
||||
typedef struct prach_association_period {
|
||||
prach_conf_period_t *prach_conf_period_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD];
|
||||
uint8_t nb_of_prach_conf_period; // Nb of PRACH configuration periods within the association period
|
||||
uint8_t nb_of_frame; // Total number of frames included in the association period
|
||||
} prach_association_period_t;
|
||||
|
||||
// The association pattern is a series of Association periods
|
||||
typedef struct prach_association_pattern {
|
||||
prach_association_period_t prach_association_period_list[MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD];
|
||||
prach_conf_period_t prach_conf_period_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD];
|
||||
uint8_t nb_of_assoc_period; // Nb of association periods within the association pattern
|
||||
uint8_t nb_of_prach_conf_period_in_max_period; // Nb of PRACH configuration periods within the maximum association pattern period (according to the size of the configured PRACH
|
||||
uint8_t nb_of_frame; // Total number of frames included in the association pattern period (after mapping the SSBs and determining the real association pattern length)
|
||||
} prach_association_pattern_t;
|
||||
|
||||
// SSB details
|
||||
typedef struct ssb_info {
|
||||
prach_occasion_info_t *mapped_ro[MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN]; // List of mapped RACH Occasions to this SSB index
|
||||
uint32_t nb_mapped_ro; // Total number of mapped ROs to this SSB index
|
||||
} ssb_info_t;
|
||||
|
||||
// List of all the possible SSBs and their details
|
||||
typedef struct ssb_list_info {
|
||||
ssb_info_t *tx_ssb;
|
||||
int nb_tx_ssb;
|
||||
int nb_ssb_per_index[MAX_NB_SSB];
|
||||
} ssb_list_info_t;
|
||||
@@ -571,14 +538,12 @@ typedef struct NR_UE_MAC_INST_s {
|
||||
NR_UE_L2_STATE_t state;
|
||||
int servCellIndex;
|
||||
long physCellId;
|
||||
int first_sync_frame;
|
||||
bool get_sib1;
|
||||
bool get_otherSI;
|
||||
NR_MIB_t *mib;
|
||||
|
||||
si_schedInfo_t si_SchedInfo;
|
||||
ssb_list_info_t ssb_list[MAX_NUM_BWP_UE];
|
||||
prach_association_pattern_t prach_assoc_pattern[MAX_NUM_BWP_UE];
|
||||
ssb_list_info_t ssb_list;
|
||||
|
||||
NR_UE_ServingCell_Info_t sc_info;
|
||||
A_SEQUENCE_OF(NR_UE_DL_BWP_t) dl_BWPs;
|
||||
@@ -670,6 +635,7 @@ typedef struct NR_UE_MAC_INST_s {
|
||||
int f_b_f_c;
|
||||
bool pusch_power_control_initialized;
|
||||
int delta_msg2;
|
||||
bool msg3_C_RNTI;
|
||||
pthread_mutex_t if_mutex;
|
||||
ue_mac_stats_t stats;
|
||||
} NR_UE_MAC_INST_t;
|
||||
|
||||
@@ -45,8 +45,12 @@
|
||||
\param mac MAC pointer */
|
||||
void nr_ue_init_mac(NR_UE_MAC_INST_t *mac);
|
||||
|
||||
NR_UE_DL_BWP_t *get_dl_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup);
|
||||
NR_UE_UL_BWP_t *get_ul_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup);
|
||||
|
||||
void send_srb0_rrc(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data);
|
||||
void update_mac_timers(NR_UE_MAC_INST_t *mac);
|
||||
void update_mac_ul_timers(NR_UE_MAC_INST_t *mac);
|
||||
void update_mac_dl_timers(NR_UE_MAC_INST_t *mac);
|
||||
NR_LC_SCHEDULING_INFO *get_scheduling_info_from_lcid(NR_UE_MAC_INST_t *mac, NR_LogicalChannelIdentity_t lcid);
|
||||
|
||||
/**\brief apply default configuration values in nr_mac instance
|
||||
@@ -177,8 +181,6 @@ typedef struct {
|
||||
enum { b_none, b_long, b_short, b_short_trunc, b_long_trunc } type_bsr;
|
||||
} type_bsr_t;
|
||||
|
||||
int nr_write_ce_msg3_pdu(uint8_t *mac_ce, NR_UE_MAC_INST_t *mac, rnti_t crnti, uint8_t *mac_ce_end);
|
||||
|
||||
int nr_write_ce_ulsch_pdu(uint8_t *mac_ce,
|
||||
NR_UE_MAC_INST_t *mac,
|
||||
NR_SINGLE_ENTRY_PHR_MAC_CE *power_headroom,
|
||||
@@ -211,7 +213,6 @@ void set_harq_status(NR_UE_MAC_INST_t *mac,
|
||||
bool get_downlink_ack(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCCH_sched_t *pucch);
|
||||
initial_pucch_resource_t get_initial_pucch_resource(const int idx);
|
||||
void multiplex_pucch_resource(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *pucch, int num_res);
|
||||
uint32_t get_backoff_indicator(int idx);
|
||||
int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac,
|
||||
int scs,
|
||||
NR_PUCCH_Config_t *pucch_Config,
|
||||
@@ -274,6 +275,8 @@ void ul_ports_config(NR_UE_MAC_INST_t *mac,
|
||||
dci_pdu_rel15_t *dci,
|
||||
nr_dci_format_t dci_format);
|
||||
|
||||
bool init_RA(NR_UE_MAC_INST_t *mac, int frame);
|
||||
|
||||
/* Random Access */
|
||||
/* \brief This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211 tables 6.3.3.2.x
|
||||
and fills the PRACH PDU per each FD occasion.
|
||||
@@ -290,56 +293,17 @@ void configure_csi_resource_mapping(fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_c
|
||||
uint32_t bwp_size,
|
||||
uint32_t bwp_start);
|
||||
|
||||
/* \brief This function schedules the Msg3 transmission
|
||||
@param
|
||||
@param
|
||||
@param
|
||||
@returns void
|
||||
*/
|
||||
void nr_ue_msg3_scheduler(NR_UE_MAC_INST_t *mac, frame_t current_frame, slot_t current_slot, uint8_t Msg3_tda_id);
|
||||
|
||||
void nr_ue_contention_resolution(NR_UE_MAC_INST_t *mac, int cc_id, frame_t frame, int slot, NR_PRACH_RESOURCES_t *prach_resources);
|
||||
|
||||
void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *prach_resources, frame_t frame, int slot);
|
||||
|
||||
void nr_ra_contention_resolution_failed(NR_UE_MAC_INST_t *mac);
|
||||
void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame_t frame, const int slot);
|
||||
|
||||
int16_t nr_get_RA_window_2Step(const NR_MsgA_ConfigCommon_r16_t *msgA_ConfigCommon_r16);
|
||||
|
||||
int16_t nr_get_RA_window_4Step(const NR_RACH_ConfigCommon_t *rach_ConfigCommon);
|
||||
|
||||
void nr_ra_backoff_setting(RA_config_t *ra);
|
||||
void nr_get_RA_window(NR_UE_MAC_INST_t *mac);
|
||||
|
||||
/* \brief Function called by PHY to retrieve information to be transmitted using the RA procedure.
|
||||
If the UE is not in PUSCH mode for a particular eNB index, this is assumed to be an Msg3 and MAC
|
||||
attempts to retrieves the CCCH message from RRC. If the UE is in PUSCH mode for a particular eNB
|
||||
index and PUCCH format 0 (Scheduling Request) is not activated, the MAC may use this resource for
|
||||
andom-access to transmit a BSR along with the C-RNTI control element (see 5.1.4 from 38.321)
|
||||
@param mod_id Index of UE instance
|
||||
@param CC_id Component Carrier Index
|
||||
@param frame
|
||||
@param gNB_id gNB index
|
||||
@param nr_slot_tx slot for PRACH transmission
|
||||
@returns indication to generate PRACH to phy */
|
||||
void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB_id, int nr_slot_tx);
|
||||
|
||||
/* \brief Function implementing the routine for the selection of Random Access resources (5.1.2 TS 38.321).
|
||||
@param mac pointer to MAC instance
|
||||
@param CC_id Component Carrier Index
|
||||
@param gNB_index gNB index
|
||||
@param rach_ConfigDedicated
|
||||
@returns void */
|
||||
void nr_get_prach_resources(NR_UE_MAC_INST_t *mac,
|
||||
int CC_id,
|
||||
uint8_t gNB_id,
|
||||
NR_PRACH_RESOURCES_t *prach_resources,
|
||||
NR_RACH_ConfigDedicated_t * rach_ConfigDedicated);
|
||||
|
||||
void prepare_msg4_msgb_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack);
|
||||
void configure_initial_pucch(PUCCH_sched_t *pucch, int res_ind);
|
||||
void release_PUCCH_SRS(NR_UE_MAC_INST_t *mac);
|
||||
void nr_ue_reset_sync_state(NR_UE_MAC_INST_t *mac);
|
||||
void nr_ue_send_synch_request(NR_UE_MAC_INST_t *mac, module_id_t module_id, int cc_id, const fapi_nr_synch_request_t *sync_req);
|
||||
bool is_ss_monitor_occasion(const int frame, const int slot, const int slots_per_frame, const NR_SearchSpace_t *ss);
|
||||
|
||||
/**
|
||||
* @brief Get UE sync state
|
||||
@@ -348,18 +312,12 @@ void nr_ue_send_synch_request(NR_UE_MAC_INST_t *mac, module_id_t module_id, int
|
||||
*/
|
||||
NR_UE_L2_STATE_t nr_ue_get_sync_state(module_id_t mod_id);
|
||||
|
||||
void init_RA(NR_UE_MAC_INST_t *mac,
|
||||
NR_PRACH_RESOURCES_t *prach_resources,
|
||||
NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon,
|
||||
NR_RACH_ConfigGeneric_t *rach_ConfigGeneric,
|
||||
NR_RACH_ConfigDedicated_t *rach_ConfigDedicated);
|
||||
|
||||
int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac);
|
||||
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_rar_not_successful(NR_UE_MAC_INST_t *mac);
|
||||
void ra_resource_selection(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 trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac, dci_pdu_rel15_t *pdcch_order);
|
||||
void nr_get_Msg3_MsgA_PUSCH_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,
|
||||
@@ -370,9 +328,7 @@ int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *p
|
||||
int start_DLBWP,
|
||||
dci_field_t frequency_domain_assignment);
|
||||
|
||||
void build_ssb_to_ro_map(NR_UE_MAC_INST_t *mac);
|
||||
|
||||
void ue_init_config_request(NR_UE_MAC_INST_t *mac, int slots_per_frame);
|
||||
void ue_init_config_request(NR_UE_MAC_INST_t *mac, int scs);
|
||||
|
||||
fapi_nr_dl_config_request_t *get_dl_config_request(NR_UE_MAC_INST_t *mac, int slot);
|
||||
|
||||
|
||||
@@ -412,30 +412,6 @@ static const uint8_t table_7_3_2_3_3_4_twoCodeword[6][14] = {
|
||||
{2,1,1,1,1,0,0,1,1,1,1,0,0,2},
|
||||
};
|
||||
|
||||
// table 7.2-1 TS 38.321
|
||||
static const uint32_t table_7_2_1[16] = {
|
||||
5, // row index 0
|
||||
10, // row index 1
|
||||
20, // row index 2
|
||||
30, // row index 3
|
||||
40, // row index 4
|
||||
60, // row index 5
|
||||
80, // row index 6
|
||||
120, // row index 7
|
||||
160, // row index 8
|
||||
240, // row index 9
|
||||
320, // row index 10
|
||||
480, // row index 11
|
||||
960, // row index 12
|
||||
1920, // row index 13
|
||||
};
|
||||
|
||||
uint32_t get_backoff_indicator(int idx)
|
||||
{
|
||||
AssertFatal(idx < 16, "Backoff indicator index %d exeeding table size\n", idx);
|
||||
return table_7_2_1[idx];
|
||||
}
|
||||
|
||||
static inline uint16_t packBits(const uint8_t *toPack, const int nb)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
@@ -69,6 +69,7 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
|
||||
mac->p_Max = INT_MIN;
|
||||
mac->p_Max_alt = INT_MIN;
|
||||
mac->n_ta_offset = -1;
|
||||
mac->msg3_C_RNTI = false;
|
||||
mac->ntn_ta.ntn_params_changed = false;
|
||||
reset_mac_inst(mac);
|
||||
|
||||
@@ -77,8 +78,7 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
|
||||
|
||||
memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements));
|
||||
memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment));
|
||||
memset(mac->ssb_list, 0, sizeof(mac->ssb_list));
|
||||
memset(mac->prach_assoc_pattern, 0, sizeof(mac->prach_assoc_pattern));
|
||||
memset(&mac->ssb_list, 0, sizeof(mac->ssb_list));
|
||||
|
||||
for (int i = 0; i < NR_MAX_SR_ID; i++)
|
||||
memset(&mac->scheduling_info.sr_info[i], 0, sizeof(mac->scheduling_info.sr_info[i]));
|
||||
@@ -115,7 +115,6 @@ void nr_ue_send_synch_request(NR_UE_MAC_INST_t *mac, module_id_t module_id, int
|
||||
void nr_ue_reset_sync_state(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
// reset synchornization status
|
||||
mac->first_sync_frame = -1;
|
||||
mac->state = UE_NOT_SYNC;
|
||||
mac->ra.ra_state = nrRA_UE_IDLE;
|
||||
}
|
||||
@@ -181,9 +180,11 @@ 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);
|
||||
nr_timer_stop(&nr_mac->ra.response_window_timer);
|
||||
nr_timer_stop(&nr_mac->ra.RA_backoff_timer);
|
||||
nr_timer_stop(&nr_mac->ra.contention_resolution_timer);
|
||||
for (int i = 0; i < NR_MAX_SR_ID; i++)
|
||||
nr_timer_stop(&nr_mac->scheduling_info.sr_info[i].prohibitTimer);
|
||||
|
||||
@@ -195,8 +196,10 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
|
||||
nr_mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value
|
||||
|
||||
// stop any ongoing RACH procedure
|
||||
if (nr_mac->ra.ra_state < nrRA_SUCCEEDED)
|
||||
if (nr_mac->ra.RA_active) {
|
||||
nr_mac->ra.ra_state = nrRA_UE_IDLE;
|
||||
nr_mac->ra.RA_active = false;
|
||||
}
|
||||
|
||||
// discard explicitly signalled contention-free Random Access Resources
|
||||
// TODO not sure what needs to be done here
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -442,8 +442,8 @@ bool search_space_monitoring_ocasion_other_si(NR_UE_MAC_INST_t *mac,
|
||||
get_monitoring_period_offset(ss, &period, &offset);
|
||||
for (int i = 0; i < duration; i++) {
|
||||
if (((frame * slots_per_frame + slot - offset - i) % period) == 0) {
|
||||
int N = mac->ssb_list[bwp_id].nb_tx_ssb;
|
||||
int K = mac->ssb_list->nb_ssb_per_index[mac->mib_ssb];
|
||||
int N = mac->ssb_list.nb_tx_ssb;
|
||||
int K = mac->ssb_list.nb_ssb_per_index[mac->mib_ssb];
|
||||
|
||||
// numbering current frame and slot in terms of monitoring occasions in window
|
||||
int rel_slot = abs_slot - mac->si_SchedInfo.si_window_start;
|
||||
@@ -560,12 +560,13 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl
|
||||
config_dci_pdu(mac, dl_config, TYPE_SI_RNTI_, slot, ss);
|
||||
}
|
||||
}
|
||||
if (mac->state == UE_PERFORMING_RA && mac->ra.ra_state >= nrRA_WAIT_RAR) {
|
||||
RA_config_t *ra = &mac->ra;
|
||||
if (mac->state == UE_PERFORMING_RA && ra->ra_state >= nrRA_WAIT_RAR) {
|
||||
// if RA is ongoing use RA search space
|
||||
if (is_ss_monitor_occasion(frame, slot, slots_per_frame, pdcch_config->ra_SS)) {
|
||||
nr_rnti_type_t rnti_type = 0;
|
||||
if (mac->ra.ra_type == RA_4_STEP) {
|
||||
rnti_type = mac->ra.ra_state == nrRA_WAIT_RAR ? TYPE_RA_RNTI_ : TYPE_TC_RNTI_;
|
||||
if (ra->ra_type == RA_4_STEP) {
|
||||
rnti_type = ra->ra_state == nrRA_WAIT_RAR ? TYPE_RA_RNTI_ : TYPE_TC_RNTI_;
|
||||
} else {
|
||||
rnti_type = TYPE_MSGB_RNTI_;
|
||||
}
|
||||
|
||||
@@ -372,8 +372,8 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac,
|
||||
if (mac->pucch_power_control_initialized == false) {
|
||||
// Initialize power control state
|
||||
// Assuming only sending on PCell
|
||||
NR_PRACH_RESOURCES_t* prach_resources = &mac->ra.prach_resources;
|
||||
float DELTA_P_rampup_requested = (prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER - 1) * prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP;
|
||||
NR_PRACH_RESOURCES_t *prach_res = &mac->ra.prach_resources;
|
||||
float DELTA_P_rampup_requested = (prach_res->preamble_power_ramping_cnt - 1) * prach_res->preamble_power_ramping_step;
|
||||
float DELTA_P_rampup = P_CMAX - (P_O_PUCCH + pathloss + delta_F_PUCCH + DELTA_TF + sum_delta_pucch);
|
||||
DELTA_P_rampup = max(min(0, DELTA_P_rampup), DELTA_P_rampup_requested);
|
||||
mac->G_b_f_c = DELTA_P_rampup + sum_delta_pucch;
|
||||
@@ -492,9 +492,7 @@ int get_pusch_tx_power_ue(NR_UE_MAC_INST_t *mac,
|
||||
if (current_UL_BWP->msg3_DeltaPreamble) {
|
||||
DELTA_PREAMBLE_MSG3 = *current_UL_BWP->msg3_DeltaPreamble;
|
||||
}
|
||||
NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = current_UL_BWP->rach_ConfigCommon;
|
||||
long preambleReceivedTargetPower = nr_rach_ConfigCommon->rach_ConfigGeneric.preambleReceivedTargetPower;
|
||||
int P_O_PRE = preambleReceivedTargetPower;
|
||||
int P_O_PRE = mac->ra.prach_resources.ra_preamble_rx_target_power;
|
||||
P_O_NOMINAL_PUSCH = P_O_PRE + DELTA_PREAMBLE_MSG3;
|
||||
|
||||
if (has_pusch_power_control_config && pusch_Config->pusch_PowerControl->msg3_Alpha) {
|
||||
@@ -572,8 +570,8 @@ int get_pusch_tx_power_ue(NR_UE_MAC_INST_t *mac,
|
||||
f_b_f_c = delta_pusch;
|
||||
} else {
|
||||
if (!mac->pusch_power_control_initialized && is_rar_tx_retx) {
|
||||
NR_PRACH_RESOURCES_t* prach_resources = &mac->ra.prach_resources;
|
||||
float DELTA_P_rampup_requested = (prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER - 1) * prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP;
|
||||
NR_PRACH_RESOURCES_t *prach_res = &mac->ra.prach_resources;
|
||||
float DELTA_P_rampup_requested = (prach_res->preamble_power_ramping_cnt - 1) * prach_res->preamble_power_ramping_step;
|
||||
float DELTA_P_rampup = P_CMAX - (P_O_PUSCH + M_pusch_component + alpha * pathloss + DELTA_TF + delta_pusch);
|
||||
DELTA_P_rampup = min(DELTA_P_rampup_requested, max(0, DELTA_P_rampup));
|
||||
mac->f_b_f_c = DELTA_P_rampup + delta_pusch;
|
||||
@@ -654,9 +652,8 @@ int get_srs_tx_power_ue(NR_UE_MAC_INST_t *mac,
|
||||
|
||||
if (!is_tpc_accumulation_provided && (!is_configured_for_pusch_on_current_bwp || separate_pc_adjustment_state)) {
|
||||
if (!current_UL_BWP->srs_power_control_initialized) {
|
||||
NR_PRACH_RESOURCES_t *prach_resources = &mac->ra.prach_resources;
|
||||
float DELTA_P_rampup_requested =
|
||||
(prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER - 1) * prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP;
|
||||
NR_PRACH_RESOURCES_t *prach = &mac->ra.prach_resources;
|
||||
float DELTA_P_rampup_requested = (prach->preamble_power_ramping_cnt - 1) * prach->preamble_power_ramping_step;
|
||||
float DELTA_P_rampup = P_CMAX - (P_0_SRS + m_srs_component + alpha * pathloss);
|
||||
DELTA_P_rampup = min(DELTA_P_rampup_requested, max(0, DELTA_P_rampup));
|
||||
current_UL_BWP->srs_power_control_initialized = true;
|
||||
|
||||
@@ -59,6 +59,25 @@
|
||||
// #define DEBUG_MIB
|
||||
// #define ENABLE_MAC_PAYLOAD_DEBUG 1
|
||||
// #define DEBUG_RAR
|
||||
|
||||
// table 7.2-1 TS 38.321
|
||||
const uint16_t table_7_2_1[16] = {
|
||||
5, // row index 0
|
||||
10, // row index 1
|
||||
20, // row index 2
|
||||
30, // row index 3
|
||||
40, // row index 4
|
||||
60, // row index 5
|
||||
80, // row index 6
|
||||
120, // row index 7
|
||||
160, // row index 8
|
||||
240, // row index 9
|
||||
320, // row index 10
|
||||
480, // row index 11
|
||||
960, // row index 12
|
||||
1920, // row index 13
|
||||
};
|
||||
|
||||
/* TS 36.213 Table 9.2.3-3: Mapping of values for one HARQ-ACK bit to sequences */
|
||||
static const int sequence_cyclic_shift_1_harq_ack_bit[2]
|
||||
/* HARQ-ACK Value 0 1 */
|
||||
@@ -219,9 +238,6 @@ void nr_ue_decode_mib(NR_UE_MAC_INST_t *mac, int cc_id)
|
||||
mac->ssb_subcarrier_offset = ssb_subcarrier_offset;
|
||||
mac->dmrs_TypeA_Position = mac->mib->dmrs_TypeA_Position;
|
||||
|
||||
if (mac->first_sync_frame == -1)
|
||||
mac->first_sync_frame = frame;
|
||||
|
||||
if (get_softmodem_params()->phy_test)
|
||||
mac->state = UE_CONNECTED;
|
||||
else if (mac->state == UE_NOT_SYNC) {
|
||||
@@ -701,7 +717,7 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
|
||||
dlsch_pdu->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon + 2;
|
||||
} else {
|
||||
dlsch_pdu->SubcarrierSpacing = current_DL_BWP->scs;
|
||||
if (mac->ra.RA_window_cnt >= 0 && rnti_type == TYPE_RA_RNTI_) {
|
||||
if (nr_timer_is_active(&mac->ra.response_window_timer) && rnti_type == TYPE_RA_RNTI_) {
|
||||
dl_conf_req->pdu_type = FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH;
|
||||
} else {
|
||||
dl_conf_req->pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH;
|
||||
@@ -2929,7 +2945,7 @@ void nr_ue_send_sdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, in
|
||||
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);
|
||||
trigger_MAC_UE_RA(mac, NULL);
|
||||
break;
|
||||
}
|
||||
nr_ue_process_mac_pdu(mac, dl_info, pdu_id);
|
||||
@@ -2991,7 +3007,11 @@ static void extract_10_si_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dc
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->system_info_indicator, 1);
|
||||
}
|
||||
|
||||
static void extract_10_c_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dci_pdu, int pos, const int N_RB)
|
||||
static bool extract_10_c_rnti(NR_UE_MAC_INST_t *mac,
|
||||
dci_pdu_rel15_t *dci_pdu_rel15,
|
||||
const uint8_t *dci_pdu,
|
||||
int pos,
|
||||
const int N_RB)
|
||||
{
|
||||
LOG_D(NR_MAC_DCI, "Received dci 1_0 C rnti\n");
|
||||
|
||||
@@ -3014,29 +3034,31 @@ static void extract_10_c_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dci
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->ss_pbch_index, 6);
|
||||
// prach_mask_index 4 bits
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->prach_mask_index, 4);
|
||||
trigger_MAC_UE_RA(mac, dci_pdu_rel15);
|
||||
return true;
|
||||
} // end if
|
||||
else {
|
||||
// Time domain assignment 4bit
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->time_domain_assignment.val, 4);
|
||||
// VRB to PRB mapping 1bit
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->vrb_to_prb_mapping.val, 1);
|
||||
// MCS 5bit //bit over 32, so dci_pdu ++
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->mcs, 5);
|
||||
// New data indicator 1bit
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->ndi, 1);
|
||||
// Redundancy version 2bit
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->rv, 2);
|
||||
// HARQ process number 4/5 bit
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->harq_pid.val, dci_pdu_rel15->harq_pid.nbits);
|
||||
// Downlink assignment index 2bit
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->dai[0].val, 2);
|
||||
// TPC command for scheduled PUCCH 2bit
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->tpc, 2);
|
||||
// PUCCH resource indicator 3bit
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->pucch_resource_indicator, 3);
|
||||
// PDSCH-to-HARQ_feedback timing indicator 3bit
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val, 3);
|
||||
} // end else
|
||||
|
||||
// Time domain assignment 4bit
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->time_domain_assignment.val, 4);
|
||||
// VRB to PRB mapping 1bit
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->vrb_to_prb_mapping.val, 1);
|
||||
// MCS 5bit //bit over 32, so dci_pdu ++
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->mcs, 5);
|
||||
// New data indicator 1bit
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->ndi, 1);
|
||||
// Redundancy version 2bit
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->rv, 2);
|
||||
// HARQ process number 4/5 bit
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->harq_pid.val, dci_pdu_rel15->harq_pid.nbits);
|
||||
// Downlink assignment index 2bit
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->dai[0].val, 2);
|
||||
// TPC command for scheduled PUCCH 2bit
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->tpc, 2);
|
||||
// PUCCH resource indicator 3bit
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->pucch_resource_indicator, 3);
|
||||
// PDSCH-to-HARQ_feedback timing indicator 3bit
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val, 3);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void extract_00_c_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dci_pdu, int pos)
|
||||
@@ -3297,7 +3319,9 @@ static nr_dci_format_t nr_extract_dci_00_10(NR_UE_MAC_INST_t *mac,
|
||||
int n_RB = get_nrb_for_dci(mac, format, ss_type);
|
||||
if (n_RB == 0)
|
||||
return NR_DCI_NONE;
|
||||
extract_10_c_rnti(dci_pdu_rel15, dci_pdu, pos, n_RB);
|
||||
bool pdcch_order = extract_10_c_rnti(mac, dci_pdu_rel15, dci_pdu, pos, n_RB);
|
||||
if (pdcch_order)
|
||||
return NR_DCI_NONE;
|
||||
}
|
||||
else {
|
||||
format = NR_UL_DCI_FORMAT_0_0;
|
||||
@@ -3406,11 +3430,11 @@ static bool check_ra_contention_resolution(const uint8_t *pdu, const uint8_t *co
|
||||
}
|
||||
|
||||
static int nr_ue_validate_successrar(uint8_t *pduP,
|
||||
int32_t pdu_len,
|
||||
NR_UE_MAC_INST_t *mac,
|
||||
uint8_t gNB_index,
|
||||
frame_t frameP,
|
||||
int slot)
|
||||
int32_t pdu_len,
|
||||
NR_UE_MAC_INST_t *mac,
|
||||
uint8_t gNB_index,
|
||||
frame_t frameP,
|
||||
int slot)
|
||||
{
|
||||
// TS 38.321 - Figure 6.1.5a-1: BI MAC subheader
|
||||
// TS 38.321 - Figure 6.1.5a-3: SuccessRAR MAC subheader
|
||||
@@ -3418,6 +3442,7 @@ static int nr_ue_validate_successrar(uint8_t *pduP,
|
||||
uint8_t E = 1;
|
||||
uint8_t cont_res_id[6];
|
||||
RA_config_t *ra = &mac->ra;
|
||||
ra->RA_backoff_limit = 0;
|
||||
|
||||
while (n < pdu_len && E) {
|
||||
E = (pduP[n] >> 7) & 0x1;
|
||||
@@ -3425,7 +3450,9 @@ static int nr_ue_validate_successrar(uint8_t *pduP,
|
||||
if (SUCESS_RAR_header_T1 == 0) { // T2 exist
|
||||
int SUCESS_RAR_header_T2 = (pduP[n] >> 5) & 0x1;
|
||||
if (SUCESS_RAR_header_T2 == 0) { // BI
|
||||
ra->RA_backoff_indicator = pduP[n] & 0x0F;
|
||||
int bi_ms = table_7_2_1[(pduP[n] & 0x0F)] * ra->scaling_factor_bi;
|
||||
int slots_per_ms = mac->frame_structure.numb_slots_frame / 10;
|
||||
ra->RA_backoff_limit = bi_ms * slots_per_ms;
|
||||
n++;
|
||||
} else { // S
|
||||
n++;
|
||||
@@ -3468,11 +3495,10 @@ static int nr_ue_validate_successrar(uint8_t *pduP,
|
||||
bool ra_success = check_ra_contention_resolution(cont_res_id, ra->cont_res_id);
|
||||
|
||||
if (ra->RA_active && ra_success) {
|
||||
nr_timer_stop(&ra->response_window_timer);
|
||||
nr_ra_succeeded(mac, gNB_index, frameP, slot);
|
||||
} else if (!ra_success) {
|
||||
// nr_ra_failed(mac, CC_id, &ra->prach_resources, frameP, slot);
|
||||
ra->ra_state = nrRA_UE_IDLE;
|
||||
ra->RA_active = 0;
|
||||
nr_ra_backoff_setting(ra);
|
||||
}
|
||||
}
|
||||
} else { // RAPID
|
||||
@@ -3675,7 +3701,8 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i
|
||||
mac_len = 6;
|
||||
|
||||
if (ra->ra_state == nrRA_WAIT_CONTENTION_RESOLUTION) {
|
||||
LOG_I(MAC, "[UE %d]Frame %d Contention resolution identity: 0x%02x%02x%02x%02x%02x%02x Terminating RA procedure\n",
|
||||
LOG_D(NR_MAC,
|
||||
"[UE %d]Frame %d Contention resolution identity: 0x%02x%02x%02x%02x%02x%02x Terminating RA procedure\n",
|
||||
mac->ue_id,
|
||||
frameP,
|
||||
pduP[1],
|
||||
@@ -3685,15 +3712,15 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i
|
||||
pduP[5],
|
||||
pduP[6]);
|
||||
|
||||
nr_timer_stop(&ra->contention_resolution_timer);
|
||||
bool ra_success = check_ra_contention_resolution(&pduP[1], ra->cont_res_id);
|
||||
|
||||
if (ra->RA_active && ra_success) {
|
||||
nr_ra_succeeded(mac, gNB_index, frameP, slot);
|
||||
} else if (!ra_success) {
|
||||
// TODO: Handle failure of RA procedure @ MAC layer
|
||||
// nr_ra_failed(module_idP, CC_id, prach_resources, frameP, slot); // prach_resources is a PHY structure
|
||||
ra->ra_state = nrRA_UE_IDLE;
|
||||
ra->RA_active = false;
|
||||
// consider this Contention Resolution not successful and discard the successfully decoded MAC PDU
|
||||
nr_ra_contention_resolution_failed(mac);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -3731,21 +3758,6 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i
|
||||
}
|
||||
}
|
||||
|
||||
int nr_write_ce_msg3_pdu(uint8_t *mac_ce, NR_UE_MAC_INST_t *mac, rnti_t crnti, uint8_t *mac_ce_end)
|
||||
{
|
||||
uint8_t *pdu = mac_ce;
|
||||
if (IS_SA_MODE(get_softmodem_params()) && mac->ra.ra_state != nrRA_SUCCEEDED) {
|
||||
LOG_D(NR_MAC, "Generating C-RNTI MAC CE with C-RNTI %x\n", crnti);
|
||||
*(NR_MAC_SUBHEADER_FIXED *)mac_ce = (NR_MAC_SUBHEADER_FIXED){.R = 0, .LCID = UL_SCH_LCID_C_RNTI};
|
||||
mac_ce += sizeof(NR_MAC_SUBHEADER_FIXED);
|
||||
// C-RNTI MAC CE (2 octets)
|
||||
memcpy(mac_ce, &crnti, sizeof(crnti));
|
||||
// update pointer and length
|
||||
mac_ce += sizeof(crnti);
|
||||
}
|
||||
return mac_ce - pdu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function: generating MAC CEs (MAC CE and subheader) for the ULSCH PDU
|
||||
* Parameters:
|
||||
@@ -3848,6 +3860,117 @@ int nr_write_ce_ulsch_pdu(uint8_t *mac_ce,
|
||||
return mac_ce - pdu;
|
||||
}
|
||||
|
||||
static void handle_rar_reception(NR_UE_MAC_INST_t *mac, NR_MAC_RAR *rar, frame_t frame, int slot)
|
||||
{
|
||||
RAR_grant_t rar_grant;
|
||||
RA_config_t *ra = &mac->ra;
|
||||
#ifdef DEBUG_RAR
|
||||
// CSI
|
||||
unsigned char csi_req = (unsigned char)(rar->UL_GRANT_4 & 0x01);
|
||||
#endif
|
||||
|
||||
// TPC
|
||||
unsigned char tpc_command = (unsigned char)((rar->UL_GRANT_4 >> 1) & 0x07);
|
||||
ra->Msg3_TPC = (tpc_command << 1) - 6;
|
||||
|
||||
// MCS
|
||||
rar_grant.mcs = (unsigned char)(rar->UL_GRANT_4 >> 4);
|
||||
// time alloc
|
||||
rar_grant.Msg3_t_alloc = (unsigned char)(rar->UL_GRANT_3 & 0x0f);
|
||||
// frequency alloc
|
||||
rar_grant.Msg3_f_alloc = (uint16_t)((rar->UL_GRANT_3 >> 4) | (rar->UL_GRANT_2 << 4) | ((rar->UL_GRANT_1 & 0x03) << 12));
|
||||
// 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");
|
||||
// resume RAR response window timer if MSG2 decoding failed
|
||||
nr_timer_suspension(&mac->ra.response_window_timer);
|
||||
return;
|
||||
}
|
||||
frame_t frame_tx = 0;
|
||||
int slot_tx = 0;
|
||||
const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, mac->current_UL_BWP->scs);
|
||||
int ret = nr_ue_pusch_scheduler(mac, 1, 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);
|
||||
LOG_I(NR_MAC, "rarh->RAPID = 0x%x (%i)\n", rarh->RAPID, rarh->RAPID);
|
||||
|
||||
LOG_I(NR_MAC, "rar->R = 0x%x\n", rar->R);
|
||||
LOG_I(NR_MAC, "rar->TA1 = 0x%x\n", rar->TA1);
|
||||
|
||||
LOG_I(NR_MAC, "rar->TA2 = 0x%x\n", rar->TA2);
|
||||
LOG_I(NR_MAC, "rar->UL_GRANT_1 = 0x%x\n", rar->UL_GRANT_1);
|
||||
|
||||
LOG_I(NR_MAC, "rar->UL_GRANT_2 = 0x%x\n", rar->UL_GRANT_2);
|
||||
LOG_I(NR_MAC, "rar->UL_GRANT_3 = 0x%x\n", rar->UL_GRANT_3);
|
||||
LOG_I(NR_MAC, "rar->UL_GRANT_4 = 0x%x\n", rar->UL_GRANT_4);
|
||||
|
||||
LOG_I(NR_MAC, "rar->TCRNTI_1 = 0x%x\n", rar->TCRNTI_1);
|
||||
LOG_I(NR_MAC, "rar->TCRNTI_2 = 0x%x\n", rar->TCRNTI_2);
|
||||
|
||||
LOG_I(NR_MAC,
|
||||
"[%d.%d]: [UE %d] Received RAR with t_alloc %d f_alloc %d ta_command %d mcs %d freq_hopping %d tpc_command %d\n",
|
||||
frame,
|
||||
slot,
|
||||
mac->ue_id,
|
||||
rar_grant.Msg3_t_alloc,
|
||||
rar_grant.Msg3_f_alloc,
|
||||
ta_command,
|
||||
rar_grant.mcs,
|
||||
rar_grant.freq_hopping,
|
||||
tpc_command);
|
||||
#endif
|
||||
|
||||
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
|
||||
if (!ra->cfra) {
|
||||
ra->t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8);
|
||||
rnti = ra->t_crnti;
|
||||
if (!mac->msg3_C_RNTI)
|
||||
nr_mac_rrc_msg3_ind(mac->ue_id, rnti, false);
|
||||
}
|
||||
fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH);
|
||||
if (!pdu)
|
||||
return;
|
||||
// Config Msg3 PDU
|
||||
int ret = nr_config_pusch_pdu(mac,
|
||||
&tda_info,
|
||||
&pdu->pusch_config_pdu,
|
||||
NULL,
|
||||
NULL,
|
||||
&rar_grant,
|
||||
rnti,
|
||||
NR_SearchSpace__searchSpaceType_PR_common,
|
||||
NR_DCI_NONE);
|
||||
if (ret != 0)
|
||||
remove_ul_config_last_item(pdu);
|
||||
release_ul_config(pdu, false);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////
|
||||
// Random Access Response PDU //
|
||||
// TS 38.213 ch 8.2 //
|
||||
@@ -3892,13 +4015,10 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d
|
||||
}
|
||||
|
||||
RA_config_t *ra = &mac->ra;
|
||||
ra->t_crnti = 0;
|
||||
uint8_t n_subPDUs = 0; // number of RAR payloads
|
||||
uint8_t n_subheaders = 0; // number of MAC RAR subheaders
|
||||
uint8_t *dlsch_buffer = dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.pdu;
|
||||
uint8_t is_Msg3 = 1;
|
||||
frame_t frame_tx = 0;
|
||||
int slot_tx = 0;
|
||||
int ret = 0;
|
||||
NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) dlsch_buffer; // RAR subheader pointer
|
||||
NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 1); // RAR subPDU pointer
|
||||
uint8_t preamble_index = ra->ra_PreambleIndex;
|
||||
@@ -3907,7 +4027,8 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d
|
||||
T(T_NRUE_MAC_DL_RAR_PDU_WITH_DATA, T_INT(rnti), T_INT(frame), T_INT(slot),
|
||||
T_BUFFER(dlsch_buffer, dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.pdu_length));
|
||||
|
||||
LOG_D(NR_MAC, "[%d.%d]: [UE %d][RAPROC] invoking MAC for received RAR (current preamble %d)\n", frame, slot, mac->ue_id, preamble_index);
|
||||
ra->RA_backoff_limit = 0;
|
||||
LOG_D(NR_MAC, "[%d.%d]: [UE %d][RAPROC] MAC received RAR (current preamble %d)\n", frame, slot, mac->ue_id, preamble_index);
|
||||
|
||||
while (1) {
|
||||
n_subheaders++;
|
||||
@@ -3915,10 +4036,11 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d
|
||||
n_subPDUs++;
|
||||
LOG_I(NR_MAC, "[UE %d][RAPROC][RA-RNTI %04x] Got RAPID RAR subPDU\n", mac->ue_id, rnti);
|
||||
} else {
|
||||
ra->RA_backoff_indicator = get_backoff_indicator(((NR_RA_HEADER_BI *)rarh)->BI);
|
||||
ra->RA_BI_found = 1;
|
||||
LOG_I(NR_MAC, "[UE %d][RAPROC][RA-RNTI %04x] Got BI RAR subPDU %d ms\n", mac->ue_id, ra->RA_backoff_indicator, rnti);
|
||||
if ( ((NR_RA_HEADER_BI *)rarh)->E == 1) {
|
||||
int bi_ms = table_7_2_1[((NR_RA_HEADER_BI *)rarh)->BI] * ra->scaling_factor_bi;
|
||||
int slots_per_ms = mac->frame_structure.numb_slots_frame / 10;
|
||||
ra->RA_backoff_limit = bi_ms * slots_per_ms;
|
||||
LOG_I(NR_MAC, "[UE %d][RAPROC][RA-RNTI %04x] Got BI RAR subPDU %d ms\n", mac->ue_id, rnti, bi_ms);
|
||||
if (((NR_RA_HEADER_BI *)rarh)->E == 1) {
|
||||
rarh += sizeof(NR_RA_HEADER_BI);
|
||||
continue;
|
||||
} else {
|
||||
@@ -3926,9 +4048,15 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d
|
||||
}
|
||||
}
|
||||
if (rarh->RAPID == preamble_index) {
|
||||
// The MAC entity may stop ra-ResponseWindow (and hence monitoring for Random Access Response(s)) after
|
||||
// successful reception of a Random Access Response containing Random Access Preamble identifiers
|
||||
// that matches the transmitted PREAMBLE_INDEX.
|
||||
nr_timer_stop(&ra->response_window_timer);
|
||||
LOG_A(NR_MAC, "[UE %d][RAPROC][%d.%d] Found RAR with the intended RAPID %d\n", mac->ue_id, frame, slot, rarh->RAPID);
|
||||
rar = (NR_MAC_RAR *) (dlsch_buffer + n_subheaders + (n_subPDUs - 1) * sizeof(NR_MAC_RAR));
|
||||
ra->RA_RAPID_found = 1;
|
||||
handle_rar_reception(mac, rar, frame, slot);
|
||||
if (ra->cfra)
|
||||
nr_ra_succeeded(mac, dl_info->gNB_index, frame, slot);
|
||||
if (get_softmodem_params()->emulate_l1) {
|
||||
/* When we are emulating L1 with multiple UEs, the rx_indication will have
|
||||
multiple RAR PDUs. The code would previously handle each of these PDUs,
|
||||
@@ -3953,6 +4081,8 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d
|
||||
slot,
|
||||
rarh->RAPID,
|
||||
preamble_index);
|
||||
// resume RAR response window timer if MSG2 decoding failed
|
||||
nr_timer_suspension(&mac->ra.response_window_timer);
|
||||
break;
|
||||
} else {
|
||||
rarh += sizeof(NR_MAC_RAR) + 1;
|
||||
@@ -3978,142 +4108,6 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d
|
||||
rarh->RAPID,
|
||||
preamble_index);
|
||||
#endif
|
||||
|
||||
if (ra->RA_RAPID_found) {
|
||||
RAR_grant_t rar_grant;
|
||||
|
||||
#ifdef DEBUG_RAR
|
||||
// CSI
|
||||
unsigned char csi_req = (unsigned char) (rar->UL_GRANT_4 & 0x01);
|
||||
#endif
|
||||
|
||||
// TPC
|
||||
unsigned char tpc_command = (unsigned char) ((rar->UL_GRANT_4 >> 1) & 0x07);
|
||||
switch (tpc_command){
|
||||
case 0:
|
||||
ra->Msg3_TPC = -6;
|
||||
break;
|
||||
case 1:
|
||||
ra->Msg3_TPC = -4;
|
||||
break;
|
||||
case 2:
|
||||
ra->Msg3_TPC = -2;
|
||||
break;
|
||||
case 3:
|
||||
ra->Msg3_TPC = 0;
|
||||
break;
|
||||
case 4:
|
||||
ra->Msg3_TPC = 2;
|
||||
break;
|
||||
case 5:
|
||||
ra->Msg3_TPC = 4;
|
||||
break;
|
||||
case 6:
|
||||
ra->Msg3_TPC = 6;
|
||||
break;
|
||||
case 7:
|
||||
ra->Msg3_TPC = 8;
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_PHY, "RAR impossible msg3 TPC\n");
|
||||
}
|
||||
// MCS
|
||||
rar_grant.mcs = (unsigned char) (rar->UL_GRANT_4 >> 4);
|
||||
// time alloc
|
||||
rar_grant.Msg3_t_alloc = (unsigned char) (rar->UL_GRANT_3 & 0x0f);
|
||||
// frequency alloc
|
||||
rar_grant.Msg3_f_alloc = (uint16_t) ((rar->UL_GRANT_3 >> 4) | (rar->UL_GRANT_2 << 4) | ((rar->UL_GRANT_1 & 0x03) << 12));
|
||||
// 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_K_OFFSET(&mac->ntn_ta, 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);
|
||||
LOG_I(NR_MAC, "rarh->RAPID = 0x%x (%i)\n", rarh->RAPID, rarh->RAPID);
|
||||
|
||||
LOG_I(NR_MAC, "rar->R = 0x%x\n", rar->R);
|
||||
LOG_I(NR_MAC, "rar->TA1 = 0x%x\n", rar->TA1);
|
||||
|
||||
LOG_I(NR_MAC, "rar->TA2 = 0x%x\n", rar->TA2);
|
||||
LOG_I(NR_MAC, "rar->UL_GRANT_1 = 0x%x\n", rar->UL_GRANT_1);
|
||||
|
||||
LOG_I(NR_MAC, "rar->UL_GRANT_2 = 0x%x\n", rar->UL_GRANT_2);
|
||||
LOG_I(NR_MAC, "rar->UL_GRANT_3 = 0x%x\n", rar->UL_GRANT_3);
|
||||
LOG_I(NR_MAC, "rar->UL_GRANT_4 = 0x%x\n", rar->UL_GRANT_4);
|
||||
|
||||
LOG_I(NR_MAC, "rar->TCRNTI_1 = 0x%x\n", rar->TCRNTI_1);
|
||||
LOG_I(NR_MAC, "rar->TCRNTI_2 = 0x%x\n", rar->TCRNTI_2);
|
||||
|
||||
LOG_I(NR_MAC, "[%d.%d]: [UE %d] Received RAR with t_alloc %d f_alloc %d ta_command %d mcs %d freq_hopping %d tpc_command %d\n",
|
||||
frame,
|
||||
slot,
|
||||
mac->ue_id,
|
||||
rar_grant.Msg3_t_alloc,
|
||||
rar_grant.Msg3_f_alloc,
|
||||
ta_command,
|
||||
rar_grant.mcs,
|
||||
rar_grant.freq_hopping,
|
||||
tpc_command);
|
||||
#endif
|
||||
|
||||
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
|
||||
if (!ra->cfra) {
|
||||
ra->t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8);
|
||||
rnti = ra->t_crnti;
|
||||
if (!ra->msg3_C_RNTI)
|
||||
nr_mac_rrc_msg3_ind(mac->ue_id, rnti, dl_info->gNB_index);
|
||||
}
|
||||
fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH);
|
||||
if (!pdu)
|
||||
return;
|
||||
// Config Msg3 PDU
|
||||
int ret = nr_config_pusch_pdu(mac,
|
||||
&tda_info,
|
||||
&pdu->pusch_config_pdu,
|
||||
NULL,
|
||||
NULL,
|
||||
&rar_grant,
|
||||
rnti,
|
||||
NR_SearchSpace__searchSpaceType_PR_common,
|
||||
NR_DCI_NONE);
|
||||
if (ret != 0)
|
||||
remove_ul_config_last_item(pdu);
|
||||
release_ul_config(pdu, false);
|
||||
}
|
||||
|
||||
} 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -182,17 +182,26 @@ void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac)
|
||||
// TODO not sure what to do here
|
||||
}
|
||||
|
||||
void update_mac_timers(NR_UE_MAC_INST_t *mac)
|
||||
void update_mac_dl_timers(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
bool ra_window_expired = nr_timer_tick(&mac->ra.response_window_timer);
|
||||
if (ra_window_expired) // consider the Random Access Response reception not successful
|
||||
nr_rar_not_successful(mac);
|
||||
bool alignment_timer_expired = nr_timer_tick(&mac->time_alignment_timer);
|
||||
if (alignment_timer_expired)
|
||||
handle_time_alignment_timer_expired(mac);
|
||||
}
|
||||
|
||||
void update_mac_ul_timers(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
if (mac->data_inactivity_timer) {
|
||||
bool inactivity_timer_expired = nr_timer_tick(mac->data_inactivity_timer);
|
||||
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);
|
||||
bool contention_resolution_expired = nr_timer_tick(&mac->ra.contention_resolution_timer);
|
||||
if (contention_resolution_expired)
|
||||
nr_ra_contention_resolution_failed(mac);
|
||||
for (int j = 0; j < NR_MAX_SR_ID; j++)
|
||||
nr_timer_tick(&mac->scheduling_info.sr_info[j].prohibitTimer);
|
||||
nr_timer_tick(&mac->scheduling_info.sr_DelayTimer);
|
||||
@@ -236,6 +245,24 @@ void update_mac_timers(NR_UE_MAC_INST_t *mac)
|
||||
phr_info->phr_reporting |= (1 << phr_cause_periodic_timer);
|
||||
}
|
||||
}
|
||||
bool ra_backoff_expired = nr_timer_tick(&mac->ra.RA_backoff_timer);
|
||||
if (ra_backoff_expired) {
|
||||
// perform the Random Access Resource selection procedure after the backoff time
|
||||
mac->ra.ra_state = nrRA_GENERATE_PREAMBLE;
|
||||
ra_resource_selection(mac);
|
||||
} else {
|
||||
if (nr_timer_is_active(&mac->ra.RA_backoff_timer)) {
|
||||
// if the criteria (as defined in clause 5.1.2) to select contention-free Random Access Resources
|
||||
// is met during the backoff time
|
||||
// TODO verify what does this mean
|
||||
if (mac->ra.cfra) {
|
||||
// perform the Random Access Resource selection procedure
|
||||
nr_timer_stop(&mac->ra.RA_backoff_timer);
|
||||
mac->ra.ra_state = nrRA_GENERATE_PREAMBLE;
|
||||
ra_resource_selection(mac);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void remove_ul_config_last_item(fapi_nr_ul_config_request_pdu_t *pdu)
|
||||
@@ -1144,7 +1171,7 @@ 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);
|
||||
trigger_MAC_UE_RA(mac, NULL);
|
||||
// release PUCCH for all Serving Cells;
|
||||
// release SRS for all Serving Cells;
|
||||
release_PUCCH_SRS(mac);
|
||||
@@ -1206,7 +1233,9 @@ static void nr_update_sr(NR_UE_MAC_INST_t *mac, bool BSRsent)
|
||||
|
||||
NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
|
||||
NR_PUCCH_Config_t *pucch_Config = current_UL_BWP ? current_UL_BWP->pucch_Config : NULL;
|
||||
if (!pucch_Config || !pucch_Config->schedulingRequestResourceToAddModList)
|
||||
if (!pucch_Config
|
||||
|| !pucch_Config->schedulingRequestResourceToAddModList
|
||||
|| pucch_Config->schedulingRequestResourceToAddModList->list.count == 0)
|
||||
return; // cannot schedule SR if there is no schedulingRequestResource configured
|
||||
|
||||
if (lc_info->sr_id < 0 || lc_info->sr_id >= NR_MAX_SR_ID)
|
||||
@@ -1304,11 +1333,16 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info)
|
||||
uint32_t gNB_index = ul_info->gNB_index;
|
||||
|
||||
RA_config_t *ra = &mac->ra;
|
||||
if (mac->state == UE_PERFORMING_RA) {
|
||||
nr_ue_get_rach(mac, cc_id, frame_tx, gNB_index, slot_tx);
|
||||
nr_ue_prach_scheduler(mac, frame_tx, slot_tx);
|
||||
|
||||
if (mac->state == UE_PERFORMING_RA && ra->ra_state == nrRA_UE_IDLE) {
|
||||
init_RA(mac, frame_tx);
|
||||
// perform the Random Access Resource selection procedure (see clause 5.1.2 and .2a)
|
||||
ra_resource_selection(mac);
|
||||
}
|
||||
|
||||
if (mac->state == UE_PERFORMING_RA && ra->ra_state == nrRA_GENERATE_PREAMBLE)
|
||||
nr_ue_prach_scheduler(mac, frame_tx, slot_tx);
|
||||
|
||||
bool BSRsent = false;
|
||||
if (mac->state == UE_CONNECTED) {
|
||||
nr_ue_periodic_srs_scheduling(mac, frame_tx, slot_tx);
|
||||
@@ -1352,7 +1386,7 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info)
|
||||
&& (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);
|
||||
trigger_MAC_UE_RA(mac, NULL);
|
||||
return;
|
||||
}
|
||||
// Getting IP traffic to be transmitted
|
||||
@@ -1561,547 +1595,6 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac,
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config
|
||||
static void build_ro_list(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
int x,y; // PRACH Configuration Index table variables used to compute the valid frame numbers
|
||||
int y2; // PRACH Configuration Index table additional variable used to compute the valid frame numbers
|
||||
uint8_t slot_shift_for_map;
|
||||
uint8_t map_shift;
|
||||
bool even_slot_invalid;
|
||||
int64_t s_map;
|
||||
uint8_t prach_conf_start_symbol; // Starting symbol of the PRACH occasions in the PRACH slot
|
||||
uint8_t N_t_slot; // Number of PRACH occasions in a 14-symbols PRACH slot
|
||||
uint8_t N_dur; // Duration of a PRACH occasion (nb of symbols)
|
||||
uint16_t format = 0xffff;
|
||||
uint8_t format2 = 0xff;
|
||||
int nb_fdm;
|
||||
|
||||
uint8_t config_index;
|
||||
int msg1_FDM;
|
||||
|
||||
uint8_t nb_of_frames_per_prach_conf_period;
|
||||
|
||||
NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon;
|
||||
NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric;
|
||||
|
||||
config_index = rach_ConfigGeneric->prach_ConfigurationIndex;
|
||||
msg1_FDM = rach_ConfigGeneric->msg1_FDM;
|
||||
|
||||
switch (msg1_FDM){
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
nb_fdm = 1 << msg1_FDM;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1 == 0, "Unknown msg1_FDM from rach_ConfigGeneric %d\n", msg1_FDM);
|
||||
}
|
||||
|
||||
// Create the PRACH occasions map
|
||||
// WIP: For now assume no rejected PRACH occasions because of conflict with SSB or TDD_UL_DL_ConfigurationCommon schedule
|
||||
|
||||
int unpaired = mac->phy_config.config_req.cell_config.frame_duplex_type;
|
||||
|
||||
const int64_t *prach_config_info_p = get_prach_config_info(mac->frequency_range, config_index, unpaired);
|
||||
const int ul_mu = mac->current_UL_BWP->scs;
|
||||
const int mu = nr_get_prach_or_ul_mu(mac->current_UL_BWP->msgA_ConfigCommon_r16, setup, ul_mu);
|
||||
|
||||
// Identify the proper PRACH Configuration Index table according to the operating frequency
|
||||
LOG_D(NR_MAC,"mu = %u, PRACH config index = %u, unpaired = %u\n", mu, config_index, unpaired);
|
||||
|
||||
if (mac->frequency_range == FR2) { //FR2
|
||||
|
||||
x = prach_config_info_p[2];
|
||||
y = prach_config_info_p[3];
|
||||
y2 = prach_config_info_p[4];
|
||||
|
||||
s_map = prach_config_info_p[5];
|
||||
|
||||
prach_conf_start_symbol = prach_config_info_p[6];
|
||||
N_t_slot = prach_config_info_p[8];
|
||||
N_dur = prach_config_info_p[9];
|
||||
if (prach_config_info_p[1] != -1)
|
||||
format2 = (uint8_t) prach_config_info_p[1];
|
||||
format = ((uint8_t) prach_config_info_p[0]) | (format2<<8);
|
||||
|
||||
slot_shift_for_map = mu-2;
|
||||
if ( (mu == 3) && (prach_config_info_p[7] == 1) )
|
||||
even_slot_invalid = true;
|
||||
else
|
||||
even_slot_invalid = false;
|
||||
}
|
||||
else { // FR1
|
||||
x = prach_config_info_p[2];
|
||||
y = prach_config_info_p[3];
|
||||
y2 = y;
|
||||
|
||||
s_map = prach_config_info_p[4];
|
||||
|
||||
prach_conf_start_symbol = prach_config_info_p[5];
|
||||
N_t_slot = prach_config_info_p[7];
|
||||
N_dur = prach_config_info_p[8];
|
||||
LOG_D(NR_MAC,"N_t_slot %d, N_dur %d\n",N_t_slot,N_dur);
|
||||
if (prach_config_info_p[1] != -1)
|
||||
format2 = (uint8_t) prach_config_info_p[1];
|
||||
format = ((uint8_t) prach_config_info_p[0]) | (format2<<8);
|
||||
|
||||
slot_shift_for_map = mu;
|
||||
if ( (mu == 1) && (prach_config_info_p[6] == 1) && ((format & 0xff) > 3) )
|
||||
// no prach in even slots @ 30kHz for 1 prach per subframe
|
||||
even_slot_invalid = true;
|
||||
else
|
||||
even_slot_invalid = false;
|
||||
} // FR2 / FR1
|
||||
|
||||
const int bwp_id = mac->current_UL_BWP->bwp_id;
|
||||
prach_association_pattern_t *prach_assoc_pattern = &mac->prach_assoc_pattern[bwp_id];
|
||||
prach_assoc_pattern->nb_of_prach_conf_period_in_max_period = MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD / x;
|
||||
nb_of_frames_per_prach_conf_period = x;
|
||||
int slots_per_frame = mac->frame_structure.numb_slots_frame;
|
||||
LOG_D(NR_MAC,"nb_of_prach_conf_period_in_max_period %d\n", prach_assoc_pattern->nb_of_prach_conf_period_in_max_period);
|
||||
|
||||
// Fill in the PRACH occasions table for every slot in every frame in every PRACH configuration periods in the maximum association pattern period
|
||||
// ----------------------------------------------------------------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------------------------------------------------------------
|
||||
// For every PRACH configuration periods
|
||||
// -------------------------------------
|
||||
for (int period_idx = 0; period_idx < prach_assoc_pattern->nb_of_prach_conf_period_in_max_period; period_idx++) {
|
||||
prach_conf_period_t *prach_conf_period_list = &prach_assoc_pattern->prach_conf_period_list[period_idx];
|
||||
prach_conf_period_list->nb_of_prach_occasion = 0;
|
||||
prach_conf_period_list->nb_of_frame = nb_of_frames_per_prach_conf_period;
|
||||
prach_conf_period_list->nb_of_slot = slots_per_frame;
|
||||
|
||||
LOG_D(NR_MAC,"PRACH Conf Period Idx %d\n", period_idx);
|
||||
|
||||
// For every frames in a PRACH configuration period
|
||||
// ------------------------------------------------
|
||||
for (int frame_idx = 0; frame_idx < nb_of_frames_per_prach_conf_period; frame_idx++) {
|
||||
int frame_rach = (period_idx * nb_of_frames_per_prach_conf_period) + frame_idx;
|
||||
|
||||
LOG_D(NR_MAC,"PRACH Conf Period Frame Idx %d - Frame %d\n", frame_idx, frame_rach);
|
||||
// Is it a valid frame for this PRACH configuration index? (n_sfn mod x = y)
|
||||
if ((frame_rach % x) == y || (frame_rach % x) == y2) {
|
||||
|
||||
// For every slot in a frame
|
||||
// -------------------------
|
||||
for (int slot = 0; slot < slots_per_frame; slot++) {
|
||||
// Is it a valid slot?
|
||||
map_shift = slot >> slot_shift_for_map; // in PRACH configuration index table slots are numbered wrt 60kHz
|
||||
if ((s_map>>map_shift) & 0x01) {
|
||||
// Valid slot
|
||||
|
||||
// Additionally, for 30kHz/120kHz, we must check for the n_RA_Slot param also
|
||||
if (even_slot_invalid && (slot%2 == 0))
|
||||
continue; // no prach in even slots @ 30kHz/120kHz for 1 prach per 60khz slot/subframe
|
||||
|
||||
// We're good: valid frame and valid slot
|
||||
// Compute all the PRACH occasions in the slot
|
||||
|
||||
prach_occasion_slot_t *slot_map = &prach_conf_period_list->prach_occasion_slot_map[frame_idx][slot];
|
||||
slot_map->nb_of_prach_occasion_in_time = N_t_slot;
|
||||
slot_map->nb_of_prach_occasion_in_freq = nb_fdm;
|
||||
slot_map->prach_occasion = malloc(N_t_slot * nb_fdm * sizeof(*slot_map->prach_occasion));
|
||||
AssertFatal(slot_map->prach_occasion, "no memory available\n");
|
||||
for (int n_prach_occ_in_time = 0; n_prach_occ_in_time < N_t_slot; n_prach_occ_in_time++) {
|
||||
uint8_t start_symbol = prach_conf_start_symbol + n_prach_occ_in_time * N_dur;
|
||||
LOG_D(NR_MAC,"PRACH Occ in time %d\n", n_prach_occ_in_time);
|
||||
|
||||
for (int n_prach_occ_in_freq = 0; n_prach_occ_in_freq < nb_fdm; n_prach_occ_in_freq++) {
|
||||
slot_map->prach_occasion[n_prach_occ_in_time * nb_fdm + n_prach_occ_in_freq] =
|
||||
(prach_occasion_info_t){.start_symbol = start_symbol,
|
||||
.fdm = n_prach_occ_in_freq,
|
||||
.frame = frame_idx,
|
||||
.slot = slot,
|
||||
.format = format};
|
||||
prach_assoc_pattern->prach_conf_period_list[period_idx].nb_of_prach_occasion++;
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"Adding a PRACH occasion: frame %u, slot-symbol %d-%d, occ_in_time-occ_in-freq %d-%d, nb ROs in conf period %d, for this slot: RO# in time %d, RO# in freq %d\n",
|
||||
frame_rach,
|
||||
slot,
|
||||
start_symbol,
|
||||
n_prach_occ_in_time,
|
||||
n_prach_occ_in_freq,
|
||||
prach_conf_period_list->nb_of_prach_occasion,
|
||||
slot_map->nb_of_prach_occasion_in_time,
|
||||
slot_map->nb_of_prach_occasion_in_freq);
|
||||
} // For every freq in the slot
|
||||
} // For every time occasions in the slot
|
||||
} // Valid slot?
|
||||
} // For every slots in a frame
|
||||
} // Valid frame?
|
||||
} // For every frames in a prach configuration period
|
||||
} // For every prach configuration periods in the maximum association pattern period (160ms)
|
||||
}
|
||||
|
||||
// Build the list of all the valid/transmitted SSBs according to the config
|
||||
static void build_ssb_list(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
// Create the list of transmitted SSBs
|
||||
const int bwp_id = mac->current_UL_BWP->bwp_id;
|
||||
ssb_list_info_t *ssb_list = &mac->ssb_list[bwp_id];
|
||||
fapi_nr_config_request_t *cfg = &mac->phy_config.config_req;
|
||||
ssb_list->nb_tx_ssb = 0;
|
||||
|
||||
for (int ssb_index = 0; ssb_index < MAX_NB_SSB; ssb_index++) {
|
||||
uint32_t curr_mask = cfg->ssb_table.ssb_mask_list[ssb_index / 32].ssb_mask;
|
||||
// check if if current SSB is transmitted
|
||||
if ((curr_mask >> (31 - (ssb_index % 32))) & 0x01) {
|
||||
ssb_list->nb_ssb_per_index[ssb_index] = ssb_list->nb_tx_ssb;
|
||||
ssb_list->nb_tx_ssb++;
|
||||
}
|
||||
else
|
||||
ssb_list->nb_ssb_per_index[ssb_index] = -1;
|
||||
}
|
||||
ssb_list->tx_ssb = calloc(ssb_list->nb_tx_ssb, sizeof(*ssb_list->tx_ssb));
|
||||
}
|
||||
|
||||
static int get_ssb_idx_from_list(ssb_list_info_t *ssb_list, int idx)
|
||||
{
|
||||
for (int ssb_index = 0; ssb_index < MAX_NB_SSB; ssb_index++) {
|
||||
if (ssb_list->nb_ssb_per_index[ssb_index] == idx)
|
||||
return ssb_index;
|
||||
}
|
||||
AssertFatal(false, "Couldn't find SSB index in SSB list\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Map the transmitted SSBs to the ROs and create the association pattern according to the config
|
||||
static void map_ssb_to_ro(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
// Map SSBs to PRACH occasions
|
||||
// WIP: Assumption: No PRACH occasion is rejected because of a conflict with SSBs or TDD_UL_DL_ConfigurationCommon schedule
|
||||
NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon;
|
||||
NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present;
|
||||
|
||||
const struct {
|
||||
// true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB
|
||||
bool multiple_ssb_per_ro;
|
||||
// Nb of SSBs per RACH or RACHs per SSB
|
||||
int ssb_rach_ratio;
|
||||
} config[] = {{false, 0}, {false, 8}, {false, 4}, {false, 2}, {true, 1}, {true, 2}, {true, 4}, {true, 8}, {true, 16}};
|
||||
AssertFatal(ssb_perRACH_config <= NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen,
|
||||
"Unsupported ssb_perRACH_config %d\n",
|
||||
ssb_perRACH_config);
|
||||
const bool multiple_ssb_per_ro = config[ssb_perRACH_config].multiple_ssb_per_ro;
|
||||
const int ssb_rach_ratio = config[ssb_perRACH_config].ssb_rach_ratio;
|
||||
|
||||
LOG_D(NR_MAC,"SSB rach ratio %d, Multiple SSB per RO %d\n", ssb_rach_ratio, multiple_ssb_per_ro);
|
||||
|
||||
const int bwp_id = mac->current_UL_BWP->bwp_id;
|
||||
ssb_list_info_t *ssb_list = &mac->ssb_list[bwp_id];
|
||||
|
||||
// Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period
|
||||
// WIP: Assumption for now is that all the PRACH configuration periods within a maximum association pattern period have the same
|
||||
// number of PRACH occasions
|
||||
// (No PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule)
|
||||
// There is only one possible association period which can contain up to 16 PRACH configuration periods
|
||||
LOG_D(NR_MAC,"Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period\n");
|
||||
const int required_nb_of_prach_occasion =
|
||||
multiple_ssb_per_ro ? ((ssb_list->nb_tx_ssb - 1) + ssb_rach_ratio) / ssb_rach_ratio : ssb_list->nb_tx_ssb * ssb_rach_ratio;
|
||||
|
||||
prach_association_pattern_t *prach_assoc_pattern = &mac->prach_assoc_pattern[bwp_id];
|
||||
const prach_conf_period_t *prach_conf_period = &prach_assoc_pattern->prach_conf_period_list[0];
|
||||
AssertFatal(prach_conf_period->nb_of_prach_occasion > 0,
|
||||
"prach_conf_period->nb_of_prach_occasion shouldn't be 0 (nb_tx_ssb %d, ssb_rach_ratio %d)\n",
|
||||
ssb_list->nb_tx_ssb,
|
||||
ssb_rach_ratio);
|
||||
prach_association_period_t *prach_association_period = &prach_assoc_pattern->prach_association_period_list[0];
|
||||
const int required_nb_of_prach_conf_period =
|
||||
((required_nb_of_prach_occasion - 1) + prach_conf_period->nb_of_prach_occasion) / prach_conf_period->nb_of_prach_occasion;
|
||||
|
||||
if (required_nb_of_prach_conf_period == 1) {
|
||||
prach_association_period->nb_of_prach_conf_period = 1;
|
||||
}
|
||||
else if (required_nb_of_prach_conf_period == 2) {
|
||||
prach_association_period->nb_of_prach_conf_period = 2;
|
||||
}
|
||||
else if (required_nb_of_prach_conf_period <= 4) {
|
||||
prach_association_period->nb_of_prach_conf_period = 4;
|
||||
}
|
||||
else if (required_nb_of_prach_conf_period <= 8) {
|
||||
prach_association_period->nb_of_prach_conf_period = 8;
|
||||
}
|
||||
else if (required_nb_of_prach_conf_period <= 16) {
|
||||
prach_association_period->nb_of_prach_conf_period = 16;
|
||||
}
|
||||
else {
|
||||
AssertFatal(1 == 0, "Invalid number of PRACH config periods within an association period %d\n", required_nb_of_prach_conf_period);
|
||||
}
|
||||
|
||||
prach_assoc_pattern->nb_of_assoc_period = 1; // WIP: only one possible association period
|
||||
prach_association_period->nb_of_frame = prach_association_period->nb_of_prach_conf_period * prach_conf_period->nb_of_frame;
|
||||
prach_assoc_pattern->nb_of_frame = prach_association_period->nb_of_frame;
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"Assoc period %d, Nb of frames in assoc period %d\n",
|
||||
prach_association_period->nb_of_prach_conf_period,
|
||||
prach_association_period->nb_of_frame);
|
||||
|
||||
// Set the starting PRACH Configuration period index in the association_pattern map for this particular association period
|
||||
int prach_configuration_period_idx =
|
||||
0; // WIP: only one possible association period so the starting PRACH configuration period is automatically 0
|
||||
|
||||
// Map all the association periods within the association pattern period
|
||||
LOG_D(NR_MAC,"Proceed to the SSB to RO mapping\n");
|
||||
// Check if we need to map multiple SSBs per RO or multiple ROs per SSB
|
||||
|
||||
if (multiple_ssb_per_ro) {
|
||||
const prach_association_period_t *end =
|
||||
prach_assoc_pattern->prach_association_period_list + prach_assoc_pattern->nb_of_assoc_period;
|
||||
for (prach_association_period_t *prach_period = prach_assoc_pattern->prach_association_period_list; prach_period < end;
|
||||
prach_period++) {
|
||||
// Set the starting PRACH Configuration period index in the association_pattern map for this particular association period
|
||||
// WIP: only one possible association period so the starting PRACH configuration period is automatically 0
|
||||
// WIP: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO
|
||||
// this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule
|
||||
int idx = 0;
|
||||
bool done = false;
|
||||
for (int i = 0; i < prach_period->nb_of_prach_conf_period && !done; i++, prach_configuration_period_idx++) {
|
||||
prach_period->prach_conf_period_list[i] = &prach_assoc_pattern->prach_conf_period_list[prach_configuration_period_idx];
|
||||
prach_conf_period_t *prach_conf = prach_period->prach_conf_period_list[i];
|
||||
// Build the association period with its association PRACH Configuration indexes
|
||||
// Go through all the ROs within the PRACH config period
|
||||
for (int frame = 0; frame < prach_conf->nb_of_frame && !done; frame++) {
|
||||
for (int slot = 0; slot < prach_conf->nb_of_slot && !done; slot++) {
|
||||
prach_occasion_slot_t *slot_map = &prach_conf->prach_occasion_slot_map[frame][slot];
|
||||
for (int ro_in_time = 0; ro_in_time < slot_map->nb_of_prach_occasion_in_time && !done; ro_in_time++) {
|
||||
for (int ro_in_freq = 0; ro_in_freq < slot_map->nb_of_prach_occasion_in_freq && !done; ro_in_freq++) {
|
||||
prach_occasion_info_t *ro_p =
|
||||
slot_map->prach_occasion + ro_in_time * slot_map->nb_of_prach_occasion_in_freq + ro_in_freq;
|
||||
// Go through the list of transmitted SSBs and map the required amount of SSBs to this RO
|
||||
// WIP: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO
|
||||
// this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule
|
||||
for (; idx < ssb_list->nb_tx_ssb; idx++) {
|
||||
ssb_info_t *tx_ssb = ssb_list->tx_ssb + idx;
|
||||
// Map only the transmitted ssb_idx
|
||||
int ssb_idx = get_ssb_idx_from_list(ssb_list, idx);
|
||||
ro_p->mapped_ssb_idx[ro_p->nb_mapped_ssb] = ssb_idx;
|
||||
ro_p->nb_mapped_ssb++;
|
||||
AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > tx_ssb->nb_mapped_ro + 1,
|
||||
"Too many mapped ROs (%d) to a single SSB\n",
|
||||
tx_ssb->nb_mapped_ro);
|
||||
tx_ssb->mapped_ro[tx_ssb->nb_mapped_ro] = ro_p;
|
||||
tx_ssb->nb_mapped_ro++;
|
||||
LOG_D(NR_MAC,
|
||||
"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n"
|
||||
"Nb mapped ROs for this ssb idx: in the association period only %u\n",
|
||||
ssb_idx,
|
||||
ro_p->slot,
|
||||
ro_p->start_symbol,
|
||||
slot,
|
||||
ro_in_time,
|
||||
ro_in_freq,
|
||||
slot_map->nb_of_prach_occasion_in_freq,
|
||||
tx_ssb->nb_mapped_ro);
|
||||
// If all the required SSBs are mapped to this RO, exit the loop of SSBs
|
||||
if (ro_p->nb_mapped_ssb == ssb_rach_ratio) {
|
||||
idx++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
done = MAX_NB_SSB == idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int frame = 0;
|
||||
int slot = 0;
|
||||
int ro_in_time = 0;
|
||||
int ro_in_freq = 0;
|
||||
prach_association_period_t *end = prach_assoc_pattern->prach_association_period_list + prach_assoc_pattern->nb_of_assoc_period;
|
||||
for (prach_association_period_t *prach_period = prach_assoc_pattern->prach_association_period_list; prach_period < end;
|
||||
prach_period++) {
|
||||
// Go through the list of transmitted SSBs
|
||||
for (int idx = 0; idx < ssb_list->nb_tx_ssb; idx++) {
|
||||
ssb_info_t *tx_ssb = ssb_list->tx_ssb + idx;
|
||||
uint8_t nb_mapped_ro_in_association_period = 0; // Reset the nb of mapped ROs for the new SSB index
|
||||
bool done = false;
|
||||
// Map all the required ROs to this SSB
|
||||
// Go through the list of PRACH config periods within this association period
|
||||
for (int i = 0; i < prach_period->nb_of_prach_conf_period && !done; i++, prach_configuration_period_idx++) {
|
||||
// Build the association period with its association PRACH Configuration indexes
|
||||
prach_period->prach_conf_period_list[i] = &prach_assoc_pattern->prach_conf_period_list[prach_configuration_period_idx];
|
||||
prach_conf_period_t *prach_conf = prach_period->prach_conf_period_list[i];
|
||||
for (; frame < prach_conf->nb_of_frame; frame++) {
|
||||
for (; slot < prach_conf->nb_of_slot; slot++) {
|
||||
prach_occasion_slot_t *slot_map = &prach_conf->prach_occasion_slot_map[frame][slot];
|
||||
for (; ro_in_time < slot_map->nb_of_prach_occasion_in_time; ro_in_time++) {
|
||||
for (; ro_in_freq < slot_map->nb_of_prach_occasion_in_freq; ro_in_freq++) {
|
||||
prach_occasion_info_t *ro_p =
|
||||
slot_map->prach_occasion + ro_in_time * slot_map->nb_of_prach_occasion_in_freq + ro_in_freq;
|
||||
int ssb_idx = get_ssb_idx_from_list(ssb_list, idx);
|
||||
ro_p->mapped_ssb_idx[0] = ssb_idx;
|
||||
ro_p->nb_mapped_ssb = 1;
|
||||
AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > tx_ssb->nb_mapped_ro + 1,
|
||||
"Too many mapped ROs (%d) to a single SSB\n",
|
||||
tx_ssb->nb_mapped_ro);
|
||||
tx_ssb->mapped_ro[tx_ssb->nb_mapped_ro] = ro_p;
|
||||
tx_ssb->nb_mapped_ro++;
|
||||
nb_mapped_ro_in_association_period++;
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"Mapped ssb_idx %u to RO slot-symbol %u-%u-%u, %u-%u-%u-%u/%u\n"
|
||||
"Nb mapped ROs for this ssb idx: in the association period only %u / total %u\n",
|
||||
ssb_idx,
|
||||
ro_p->frame,
|
||||
ro_p->slot,
|
||||
ro_p->start_symbol,
|
||||
frame,
|
||||
slot,
|
||||
ro_in_time,
|
||||
ro_in_freq,
|
||||
slot_map->nb_of_prach_occasion_in_freq,
|
||||
tx_ssb->nb_mapped_ro,
|
||||
nb_mapped_ro_in_association_period);
|
||||
|
||||
// Exit the loop if this SSB has been mapped to all the required ROs
|
||||
// WIP: Assuming that ssb_rach_ratio equals the maximum nb of times a given ssb_idx is mapped within an
|
||||
// association period:
|
||||
// this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule
|
||||
if (nb_mapped_ro_in_association_period == ssb_rach_ratio) {
|
||||
ro_in_freq++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (nb_mapped_ro_in_association_period == ssb_rach_ratio)
|
||||
break;
|
||||
else
|
||||
ro_in_freq = 0;
|
||||
}
|
||||
if (nb_mapped_ro_in_association_period == ssb_rach_ratio)
|
||||
break;
|
||||
else
|
||||
ro_in_time = 0;
|
||||
}
|
||||
if (nb_mapped_ro_in_association_period == ssb_rach_ratio)
|
||||
break;
|
||||
else
|
||||
slot = 0;
|
||||
}
|
||||
if (nb_mapped_ro_in_association_period == ssb_rach_ratio)
|
||||
break;
|
||||
else
|
||||
frame = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a RACH occasion if any matches the SSB idx, the frame and the slot
|
||||
static int get_nr_prach_info_from_ssb_index(prach_association_pattern_t *prach_assoc_pattern,
|
||||
int ssb_idx,
|
||||
int frame,
|
||||
int slot,
|
||||
ssb_list_info_t *ssb_list,
|
||||
prach_occasion_info_t **prach_occasion_info_pp)
|
||||
{
|
||||
prach_occasion_slot_t *prach_occasion_slot_p = NULL;
|
||||
|
||||
*prach_occasion_info_pp = NULL;
|
||||
|
||||
// Search for a matching RO slot in the SSB_to_RO map
|
||||
// A valid RO slot will match:
|
||||
// - ssb_idx mapped to one of the ROs in that RO slot
|
||||
// - exact slot number
|
||||
// - frame offset
|
||||
int idx_list = ssb_list->nb_ssb_per_index[ssb_idx];
|
||||
ssb_info_t *ssb_info_p = &ssb_list->tx_ssb[idx_list];
|
||||
LOG_D(NR_MAC, "checking for prach : ssb_info_p->nb_mapped_ro %d\n", ssb_info_p->nb_mapped_ro);
|
||||
for (int n_mapped_ro = 0; n_mapped_ro < ssb_info_p->nb_mapped_ro; n_mapped_ro++) {
|
||||
LOG_D(NR_MAC,
|
||||
"%d.%d: mapped_ro[%d]->frame.slot %d.%d, prach_assoc_pattern->nb_of_frame %d\n",
|
||||
frame,
|
||||
slot,
|
||||
n_mapped_ro,
|
||||
ssb_info_p->mapped_ro[n_mapped_ro]->frame,
|
||||
ssb_info_p->mapped_ro[n_mapped_ro]->slot,
|
||||
prach_assoc_pattern->nb_of_frame);
|
||||
if ((slot == ssb_info_p->mapped_ro[n_mapped_ro]->slot) && prach_assoc_pattern->prach_conf_period_list[0].nb_of_frame != 0 &&
|
||||
(ssb_info_p->mapped_ro[n_mapped_ro]->frame == (frame % prach_assoc_pattern->nb_of_frame))) {
|
||||
uint8_t prach_config_period_nb = ssb_info_p->mapped_ro[n_mapped_ro]->frame / prach_assoc_pattern->prach_conf_period_list[0].nb_of_frame;
|
||||
uint8_t frame_nb_in_prach_config_period = ssb_info_p->mapped_ro[n_mapped_ro]->frame % prach_assoc_pattern->prach_conf_period_list[0].nb_of_frame;
|
||||
prach_occasion_slot_p = &prach_assoc_pattern->prach_conf_period_list[prach_config_period_nb].prach_occasion_slot_map[frame_nb_in_prach_config_period][slot];
|
||||
}
|
||||
}
|
||||
|
||||
// If there is a matching RO slot in the SSB_to_RO map
|
||||
if (NULL != prach_occasion_slot_p) {
|
||||
// A random RO mapped to the SSB index should be selected in the slot
|
||||
|
||||
// First count the number of times the SSB index is found in that RO
|
||||
uint8_t nb_mapped_ssb = 0;
|
||||
|
||||
for (int ro_in_time = 0; ro_in_time < prach_occasion_slot_p->nb_of_prach_occasion_in_time; ro_in_time++) {
|
||||
for (int ro_in_freq = 0; ro_in_freq < prach_occasion_slot_p->nb_of_prach_occasion_in_freq; ro_in_freq++) {
|
||||
prach_occasion_info_t *ro_p =
|
||||
prach_occasion_slot_p->prach_occasion + ro_in_time * prach_occasion_slot_p->nb_of_prach_occasion_in_freq + ro_in_freq;
|
||||
for (uint8_t ssb_nb = 0; ssb_nb < ro_p->nb_mapped_ssb; ssb_nb++) {
|
||||
if (ro_p->mapped_ssb_idx[ssb_nb] == ssb_idx) {
|
||||
nb_mapped_ssb++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Choose a random SSB nb
|
||||
uint8_t random_ssb_nb = 0;
|
||||
|
||||
random_ssb_nb = ((taus()) % nb_mapped_ssb);
|
||||
|
||||
// Select the RO according to the chosen random SSB nb
|
||||
nb_mapped_ssb=0;
|
||||
for (int ro_in_time=0; ro_in_time < prach_occasion_slot_p->nb_of_prach_occasion_in_time; ro_in_time++) {
|
||||
for (int ro_in_freq=0; ro_in_freq < prach_occasion_slot_p->nb_of_prach_occasion_in_freq; ro_in_freq++) {
|
||||
prach_occasion_info_t *ro_p =
|
||||
prach_occasion_slot_p->prach_occasion + ro_in_time * prach_occasion_slot_p->nb_of_prach_occasion_in_freq + ro_in_freq;
|
||||
for (uint8_t ssb_nb = 0; ssb_nb < ro_p->nb_mapped_ssb; ssb_nb++) {
|
||||
if (ro_p->mapped_ssb_idx[ssb_nb] == ssb_idx) {
|
||||
if (nb_mapped_ssb == random_ssb_nb) {
|
||||
*prach_occasion_info_pp = ro_p;
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
nb_mapped_ssb++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Build the SSB to RO mapping upon RRC configuration update
|
||||
void build_ssb_to_ro_map(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
// Clear all the lists and maps
|
||||
const int bwp_id = mac->current_UL_BWP->bwp_id;
|
||||
free_rach_structures(mac, bwp_id);
|
||||
memset(&mac->ssb_list[bwp_id], 0, sizeof(ssb_list_info_t));
|
||||
memset(&mac->prach_assoc_pattern[bwp_id], 0, sizeof(prach_association_pattern_t));
|
||||
|
||||
// Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config
|
||||
LOG_D(NR_MAC,"Build RO list\n");
|
||||
build_ro_list(mac);
|
||||
|
||||
// Build the list of all the valid/transmitted SSBs according to the config
|
||||
LOG_D(NR_MAC,"Build SSB list\n");
|
||||
build_ssb_list(mac);
|
||||
|
||||
// Map the transmitted SSBs to the ROs and create the association pattern according to the config
|
||||
LOG_D(NR_MAC,"Map SSB to RO\n");
|
||||
map_ssb_to_ro(mac);
|
||||
LOG_D(NR_MAC,"Map SSB to RO done\n");
|
||||
}
|
||||
|
||||
static bool schedule_uci_on_pusch(NR_UE_MAC_INST_t *mac,
|
||||
frame_t frame_tx,
|
||||
int slot_tx,
|
||||
@@ -2581,6 +2074,23 @@ void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot)
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_prach_frame(frame_t frame, prach_occasion_info_t *prach_occasion_info, int association_periods)
|
||||
{
|
||||
int config_period = prach_occasion_info->frame_info[0];
|
||||
int frame_period = config_period * association_periods;
|
||||
int frame_in_period = frame % frame_period;
|
||||
if (association_periods > 1) {
|
||||
int current_assoc_period = frame_in_period / config_period;
|
||||
if (current_assoc_period != prach_occasion_info->association_period_idx)
|
||||
return false;
|
||||
frame_in_period %= config_period;
|
||||
}
|
||||
if (frame_in_period == prach_occasion_info->frame_info[1]) // SFN % x == y (see Tables in Table 6.3.3.2 of 38.211)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x
|
||||
// PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3.
|
||||
// - todo:
|
||||
@@ -2588,56 +2098,33 @@ void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot)
|
||||
static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP)
|
||||
{
|
||||
RA_config_t *ra = &mac->ra;
|
||||
ra->RA_offset = 2; // to compensate the rx frame offset at the gNB
|
||||
if (ra->ra_state != nrRA_GENERATE_PREAMBLE)
|
||||
|
||||
// Get any valid PRACH occasion in the current slot for the selected SSB index
|
||||
prach_occasion_info_t *prach_occasion_info = &ra->sched_ro_info;
|
||||
|
||||
if (!is_prach_frame(frameP, prach_occasion_info, ra->association_periods))
|
||||
return;
|
||||
|
||||
fapi_nr_config_request_t *cfg = &mac->phy_config.config_req;
|
||||
fapi_nr_prach_config_t *prach_config = &cfg->prach_config;
|
||||
|
||||
NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon;
|
||||
NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric;
|
||||
const int bwp_id = mac->current_UL_BWP->bwp_id;
|
||||
|
||||
if (is_ul_slot(slotP, &mac->frame_structure)) {
|
||||
// WIP Need to get the proper selected ssb_idx
|
||||
// Initial beam selection functionality is not available yet
|
||||
uint8_t selected_gnb_ssb_idx = mac->mib_ssb;
|
||||
|
||||
// Get any valid PRACH occasion in the current slot for the selected SSB index
|
||||
prach_occasion_info_t *prach_occasion_info_p;
|
||||
int is_nr_prach_slot = get_nr_prach_info_from_ssb_index(&mac->prach_assoc_pattern[bwp_id],
|
||||
selected_gnb_ssb_idx,
|
||||
(int)frameP,
|
||||
(int)slotP,
|
||||
&mac->ssb_list[bwp_id],
|
||||
&prach_occasion_info_p);
|
||||
|
||||
if (is_nr_prach_slot) {
|
||||
AssertFatal(NULL != prach_occasion_info_p,"PRACH Occasion Info not returned in a valid NR Prach Slot\n");
|
||||
|
||||
nr_get_RA_window(mac);
|
||||
|
||||
uint16_t format = prach_occasion_info_p->format;
|
||||
uint16_t format0 = format & 0xff; // single PRACH format
|
||||
uint16_t format1 = (format >> 8) & 0xff; // dual PRACH format
|
||||
|
||||
if (slotP == prach_occasion_info->slot) {
|
||||
fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frameP, slotP, FAPI_NR_UL_CONFIG_TYPE_PRACH);
|
||||
if (!pdu) {
|
||||
LOG_E(NR_MAC, "Error in PRACH allocation\n");
|
||||
return;
|
||||
}
|
||||
uint16_t ncs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, setup->restrictedSetConfig);
|
||||
|
||||
int format = prach_occasion_info->format;
|
||||
fapi_nr_prach_config_t *prach_config = &mac->phy_config.config_req.prach_config;
|
||||
pdu->prach_config_pdu = (fapi_nr_ul_config_prach_pdu){
|
||||
.phys_cell_id = mac->physCellId,
|
||||
.num_prach_ocas = 1,
|
||||
.prach_slot = prach_occasion_info_p->slot,
|
||||
.prach_start_symbol = prach_occasion_info_p->start_symbol,
|
||||
.num_ra = prach_occasion_info_p->fdm,
|
||||
.num_cs = ncs,
|
||||
.root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].prach_root_sequence_index,
|
||||
.prach_slot = prach_occasion_info->slot,
|
||||
.prach_start_symbol = prach_occasion_info->start_symbol,
|
||||
.num_ra = prach_occasion_info->fdm,
|
||||
.num_cs = get_NCS(ra->zeroCorrelationZoneConfig, format, ra->restricted_set_config),
|
||||
.root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info->fdm].prach_root_sequence_index,
|
||||
.restricted_set = prach_config->restricted_set_config,
|
||||
.freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].k1};
|
||||
.freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info->fdm].k1};
|
||||
|
||||
LOG_I(NR_MAC,
|
||||
"PRACH scheduler: Selected RO Frame %u, Slot %u, Symbol %u, Fdm %u\n",
|
||||
@@ -2646,82 +2133,46 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t
|
||||
pdu->prach_config_pdu.prach_start_symbol,
|
||||
pdu->prach_config_pdu.num_ra);
|
||||
|
||||
// Search which SSB is mapped in the RO (among all the SSBs mapped to this RO)
|
||||
for (int ssb_nb_in_ro=0; ssb_nb_in_ro<prach_occasion_info_p->nb_mapped_ssb; ssb_nb_in_ro++) {
|
||||
if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb_in_ro] == selected_gnb_ssb_idx) {
|
||||
ra->ssb_nb_in_ro = ssb_nb_in_ro;
|
||||
switch (format) { // single PRACH format
|
||||
case 0:
|
||||
pdu->prach_config_pdu.prach_format = 0;
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
pdu->prach_config_pdu.prach_format = 1;
|
||||
break;
|
||||
case 2:
|
||||
pdu->prach_config_pdu.prach_format = 2;
|
||||
break;
|
||||
case 3:
|
||||
pdu->prach_config_pdu.prach_format = 3;
|
||||
break;
|
||||
case 0xa1:
|
||||
pdu->prach_config_pdu.prach_format = 4;
|
||||
break;
|
||||
case 0xa2:
|
||||
pdu->prach_config_pdu.prach_format = 5;
|
||||
break;
|
||||
case 0xa3:
|
||||
pdu->prach_config_pdu.prach_format = 6;
|
||||
break;
|
||||
case 0xb1:
|
||||
pdu->prach_config_pdu.prach_format = 7;
|
||||
break;
|
||||
case 0xb4:
|
||||
pdu->prach_config_pdu.prach_format = 8;
|
||||
break;
|
||||
case 0xc0:
|
||||
pdu->prach_config_pdu.prach_format = 9;
|
||||
break;
|
||||
case 0xc2:
|
||||
pdu->prach_config_pdu.prach_format = 10;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(false, "Invalid PRACH format");
|
||||
}
|
||||
AssertFatal(ra->ssb_nb_in_ro<prach_occasion_info_p->nb_mapped_ssb, "%u not found in the mapped SSBs to the PRACH occasion", selected_gnb_ssb_idx);
|
||||
|
||||
if (format1 != 0xff) {
|
||||
switch (format0) { // dual PRACH format
|
||||
case 0xa1:
|
||||
pdu->prach_config_pdu.prach_format = 11;
|
||||
break;
|
||||
case 0xa2:
|
||||
pdu->prach_config_pdu.prach_format = 12;
|
||||
break;
|
||||
case 0xa3:
|
||||
pdu->prach_config_pdu.prach_format = 13;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1 == 0, "Only formats A1/B1 A2/B2 A3/B3 are valid for dual format");
|
||||
}
|
||||
} else {
|
||||
switch (format0) { // single PRACH format
|
||||
case 0:
|
||||
pdu->prach_config_pdu.prach_format = 0;
|
||||
break;
|
||||
case 1:
|
||||
pdu->prach_config_pdu.prach_format = 1;
|
||||
break;
|
||||
case 2:
|
||||
pdu->prach_config_pdu.prach_format = 2;
|
||||
break;
|
||||
case 3:
|
||||
pdu->prach_config_pdu.prach_format = 3;
|
||||
break;
|
||||
case 0xa1:
|
||||
pdu->prach_config_pdu.prach_format = 4;
|
||||
break;
|
||||
case 0xa2:
|
||||
pdu->prach_config_pdu.prach_format = 5;
|
||||
break;
|
||||
case 0xa3:
|
||||
pdu->prach_config_pdu.prach_format = 6;
|
||||
break;
|
||||
case 0xb1:
|
||||
pdu->prach_config_pdu.prach_format = 7;
|
||||
break;
|
||||
case 0xb4:
|
||||
pdu->prach_config_pdu.prach_format = 8;
|
||||
break;
|
||||
case 0xc0:
|
||||
pdu->prach_config_pdu.prach_format = 9;
|
||||
break;
|
||||
case 0xc2:
|
||||
pdu->prach_config_pdu.prach_format = 10;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1 == 0, "Invalid PRACH format");
|
||||
}
|
||||
} // if format1
|
||||
|
||||
nr_get_prach_resources(mac, 0, 0, &ra->prach_resources, ra->rach_ConfigDedicated);
|
||||
pdu->prach_config_pdu.ra_PreambleIndex = ra->ra_PreambleIndex;
|
||||
pdu->prach_config_pdu.prach_tx_power = get_prach_tx_power(mac);
|
||||
unsigned int slot_RA;
|
||||
// 3GPP TS 38.321 Section 5.1.3 says t_id for RA-RNTI depends on mu as specified in clause 5.3.2 in TS 38.211
|
||||
// so mu = 0 for prach format < 4.
|
||||
if (pdu->prach_config_pdu.prach_format < 4) {
|
||||
unsigned int slots_per_sf = (1 << mac->current_UL_BWP->scs);
|
||||
slot_RA = pdu->prach_config_pdu.prach_slot / slots_per_sf;
|
||||
} else {
|
||||
slot_RA = pdu->prach_config_pdu.prach_slot;
|
||||
}
|
||||
mac->ra.ra_rnti = nr_get_ra_rnti(pdu->prach_config_pdu.prach_start_symbol, slot_RA, pdu->prach_config_pdu.num_ra, 0);
|
||||
release_ul_config(pdu, false);
|
||||
nr_scheduled_response_t scheduled_response = {.ul_config = mac->ul_config_request + slotP,
|
||||
.mac = mac,
|
||||
@@ -2733,12 +2184,31 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t
|
||||
T(T_UE_PHY_INITIATE_RA_PROCEDURE, T_INT(frameP), T_INT(pdu->prach_config_pdu.prach_slot),
|
||||
T_INT(pdu->prach_config_pdu.ra_PreambleIndex), T_INT(pdu->prach_config_pdu.prach_tx_power));
|
||||
|
||||
const int n_slots_frame = mac->frame_structure.numb_slots_frame;
|
||||
if (ra->ra_type == RA_4_STEP) {
|
||||
nr_Msg1_transmitted(mac);
|
||||
ra->ra_state = nrRA_WAIT_RAR;
|
||||
// we start to monitor DCI for RAR in the first valid occasion after transmitting RACH
|
||||
// the response window timer should be started at that time
|
||||
// but for processing reasons it is better to start it here and to add the slot difference
|
||||
// that also takes into account the rx to tx slot offset
|
||||
int next_slot = (slotP + 1) % n_slots_frame;
|
||||
int next_frame = (frameP + (next_slot < slotP)) % MAX_FRAME_NUMBER;
|
||||
int add_slots = 1;
|
||||
NR_BWP_PDCCH_t *pdcch_config = &mac->config_BWP_PDCCH[mac->current_DL_BWP->bwp_id];
|
||||
while (!is_dl_slot(next_slot, &mac->frame_structure)
|
||||
|| !is_ss_monitor_occasion(next_frame, next_slot, n_slots_frame, pdcch_config->ra_SS)) {
|
||||
int temp_slot = (next_slot + 1) % n_slots_frame;
|
||||
next_frame = (next_frame + (temp_slot < next_slot)) % MAX_FRAME_NUMBER;
|
||||
next_slot = temp_slot;
|
||||
add_slots++;
|
||||
}
|
||||
nr_timer_setup(&ra->response_window_timer,
|
||||
ra->response_window_setup_time + add_slots + GET_DURATION_RX_TO_TX(&mac->ntn_ta),
|
||||
1);
|
||||
nr_timer_start(&ra->response_window_timer);
|
||||
} else if (ra->ra_type == RA_2_STEP) {
|
||||
NR_MsgA_PUSCH_Resource_r16_t *msgA_PUSCH_Resource =
|
||||
mac->current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16;
|
||||
const int n_slots_frame = mac->frame_structure.numb_slots_frame;
|
||||
slot_t msgA_pusch_slot = (slotP + msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16) % n_slots_frame;
|
||||
frame_t msgA_pusch_frame =
|
||||
(frameP + ((slotP + msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16) / n_slots_frame)) % 1024;
|
||||
@@ -2767,9 +2237,6 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t
|
||||
remove_ul_config_last_item(pdu);
|
||||
release_ul_config(pdu, false);
|
||||
|
||||
// Compute MsgB RNTI
|
||||
ra->MsgB_rnti =
|
||||
nr_get_MsgB_rnti(prach_occasion_info_p->start_symbol, slot_RA, prach_occasion_info_p->fdm, 0);
|
||||
LOG_D(NR_MAC, "ra->ra_state %s\n", nrra_ue_text[ra->ra_state]);
|
||||
ra->ra_state = nrRA_WAIT_MSGB;
|
||||
ra->t_crnti = 0;
|
||||
@@ -2778,8 +2245,6 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t
|
||||
} else {
|
||||
AssertFatal(false, "RA type %d not implemented!\n", ra->ra_type);
|
||||
}
|
||||
|
||||
// rnti = ra->t_crnti;
|
||||
} // is_nr_prach_slot
|
||||
} // if is_nr_UL_slot
|
||||
}
|
||||
|
||||
@@ -192,8 +192,6 @@ TEST(pusch_power_control, pusch_power_control_msg3)
|
||||
current_UL_BWP.BWPSize = 106;
|
||||
current_UL_BWP.channel_bandwidth = 40;
|
||||
mac.current_UL_BWP = ¤t_UL_BWP;
|
||||
NR_RACH_ConfigCommon_t nr_rach_ConfigCommon = {0};
|
||||
current_UL_BWP.rach_ConfigCommon = &nr_rach_ConfigCommon;
|
||||
mac.nr_band = 78;
|
||||
NR_PUSCH_Config_t pusch_Config = {0};
|
||||
current_UL_BWP.pusch_Config = &pusch_Config;
|
||||
@@ -229,8 +227,8 @@ TEST(pusch_power_control, pusch_power_control_msg3)
|
||||
num_rb,
|
||||
start_prb);
|
||||
|
||||
long preambleReceivedTargetPower = -96;
|
||||
nr_rach_ConfigCommon.rach_ConfigGeneric.preambleReceivedTargetPower = preambleReceivedTargetPower;
|
||||
int preambleReceivedTargetPower = -96;
|
||||
mac.ra.prach_resources.ra_preamble_rx_target_power = preambleReceivedTargetPower;
|
||||
|
||||
int power = get_pusch_tx_power_ue(&mac,
|
||||
num_rb,
|
||||
@@ -247,7 +245,7 @@ TEST(pusch_power_control, pusch_power_control_msg3)
|
||||
false);
|
||||
EXPECT_EQ(power, -84);
|
||||
EXPECT_LT(power, P_CMAX);
|
||||
nr_rach_ConfigCommon.rach_ConfigGeneric.preambleReceivedTargetPower -= 2;
|
||||
mac.ra.prach_resources.ra_preamble_rx_target_power -= 2;
|
||||
|
||||
int reduced_power = get_pusch_tx_power_ue(&mac,
|
||||
num_rb,
|
||||
@@ -372,8 +370,6 @@ TEST(pusch_power_control, pusch_power_control_state_initialization)
|
||||
current_UL_BWP.BWPSize = 106;
|
||||
current_UL_BWP.channel_bandwidth = 40;
|
||||
mac.current_UL_BWP = ¤t_UL_BWP;
|
||||
NR_RACH_ConfigCommon_t nr_rach_ConfigCommon = {0};
|
||||
current_UL_BWP.rach_ConfigCommon = &nr_rach_ConfigCommon;
|
||||
mac.nr_band = 78;
|
||||
NR_PUSCH_Config_t pusch_Config = {0};
|
||||
current_UL_BWP.pusch_Config = &pusch_Config;
|
||||
@@ -393,8 +389,8 @@ TEST(pusch_power_control, pusch_power_control_state_initialization)
|
||||
uint32_t sum_bits_in_codeblocks = 56;
|
||||
int delta_pusch = 0;
|
||||
bool is_rar_tx_retx = true;
|
||||
long preambleReceivedTargetPower = -96;
|
||||
nr_rach_ConfigCommon.rach_ConfigGeneric.preambleReceivedTargetPower = preambleReceivedTargetPower;
|
||||
int preambleReceivedTargetPower = -96;
|
||||
mac.ra.prach_resources.ra_preamble_rx_target_power = preambleReceivedTargetPower;
|
||||
|
||||
get_pusch_tx_power_ue(&mac,
|
||||
num_rb,
|
||||
|
||||
@@ -29,20 +29,11 @@ softmodem_params_t *get_softmodem_params(void)
|
||||
{
|
||||
return &softmodem_params;
|
||||
}
|
||||
void nr_mac_rrc_ra_ind(const module_id_t mod_id, int frame, bool success)
|
||||
void nr_mac_rrc_ra_ind(const module_id_t mod_id, bool success)
|
||||
{
|
||||
}
|
||||
int nr_write_ce_ulsch_pdu(uint8_t *mac_ce,
|
||||
NR_UE_MAC_INST_t *mac,
|
||||
NR_SINGLE_ENTRY_PHR_MAC_CE *power_headroom,
|
||||
const type_bsr_t *bsr,
|
||||
uint8_t *mac_ce_end)
|
||||
void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, bool prepare_payload)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int nr_write_ce_msg3_pdu(uint8_t *mac_ce, NR_UE_MAC_INST_t *mac, rnti_t crnti, uint8_t *mac_ce_end)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
tbs_size_t mac_rlc_data_req(const module_id_t module_idP,
|
||||
const rnti_t rntiP,
|
||||
@@ -77,6 +68,14 @@ int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac,
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
NR_UE_DL_BWP_t *get_dl_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
NR_UE_UL_BWP_t *get_ul_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#include <cstdio>
|
||||
#include "common/utils/LOG/log.h"
|
||||
@@ -84,22 +83,32 @@ int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac,
|
||||
TEST(test_init_ra, four_step_cbra)
|
||||
{
|
||||
NR_UE_MAC_INST_t mac = {0};
|
||||
NR_PRACH_RESOURCES_t prach_resources = {0};
|
||||
RA_config_t *ra = &mac.ra;
|
||||
NR_RACH_ConfigCommon_t nr_rach_ConfigCommon = {0};
|
||||
NR_RACH_ConfigGeneric_t rach_ConfigGeneric = {0};
|
||||
NR_RACH_ConfigDedicated_t *rach_ConfigDedicated = nullptr;
|
||||
NR_RACH_ConfigDedicated_t rach_ConfigDedicated = {0};
|
||||
NR_UE_UL_BWP_t current_bwp;
|
||||
NR_UE_DL_BWP_t dl_bwp;
|
||||
mac.current_UL_BWP = ¤t_bwp;
|
||||
mac.current_DL_BWP = &dl_bwp;
|
||||
mac.mib_ssb = 0;
|
||||
long scs = 1;
|
||||
current_bwp.scs = scs;
|
||||
current_bwp.bwp_id = 0;
|
||||
dl_bwp.bwp_id = 0;
|
||||
current_bwp.channel_bandwidth = 40;
|
||||
nr_rach_ConfigCommon.msg1_SubcarrierSpacing = &scs;
|
||||
nr_rach_ConfigCommon.rach_ConfigGeneric = rach_ConfigGeneric;
|
||||
current_bwp.rach_ConfigCommon = &nr_rach_ConfigCommon;
|
||||
ra->rach_ConfigDedicated = &rach_ConfigDedicated;
|
||||
mac.p_Max = 23;
|
||||
mac.nr_band = 78;
|
||||
mac.frame_structure.frame_type = TDD;
|
||||
mac.frame_structure.numb_slots_frame = 20;
|
||||
mac.frequency_range = FR1;
|
||||
int frame = 151;
|
||||
|
||||
init_RA(&mac, &prach_resources, &nr_rach_ConfigCommon, &rach_ConfigGeneric, rach_ConfigDedicated);
|
||||
init_RA(&mac, frame);
|
||||
|
||||
EXPECT_EQ(mac.ra.ra_type, RA_4_STEP);
|
||||
EXPECT_EQ(mac.state, UE_PERFORMING_RA);
|
||||
@@ -110,25 +119,35 @@ TEST(test_init_ra, four_step_cbra)
|
||||
TEST(test_init_ra, four_step_cfra)
|
||||
{
|
||||
NR_UE_MAC_INST_t mac = {0};
|
||||
NR_PRACH_RESOURCES_t prach_resources = {0};
|
||||
RA_config_t *ra = &mac.ra;
|
||||
NR_RACH_ConfigCommon_t nr_rach_ConfigCommon = {0};
|
||||
NR_RACH_ConfigGeneric_t rach_ConfigGeneric = {0};
|
||||
NR_UE_UL_BWP_t current_bwp;
|
||||
NR_UE_DL_BWP_t dl_bwp;
|
||||
mac.current_UL_BWP = ¤t_bwp;
|
||||
mac.current_DL_BWP = &dl_bwp;
|
||||
mac.mib_ssb = 0;
|
||||
long scs = 1;
|
||||
current_bwp.scs = scs;
|
||||
current_bwp.bwp_id = 0;
|
||||
dl_bwp.bwp_id = 0;
|
||||
current_bwp.channel_bandwidth = 40;
|
||||
nr_rach_ConfigCommon.msg1_SubcarrierSpacing = &scs;
|
||||
nr_rach_ConfigCommon.rach_ConfigGeneric = rach_ConfigGeneric;
|
||||
current_bwp.rach_ConfigCommon = &nr_rach_ConfigCommon;
|
||||
mac.p_Max = 23;
|
||||
mac.nr_band = 78;
|
||||
mac.frame_structure.frame_type = TDD;
|
||||
mac.frame_structure.numb_slots_frame = 20;
|
||||
mac.frequency_range = FR1;
|
||||
int frame = 151;
|
||||
|
||||
NR_RACH_ConfigDedicated_t rach_ConfigDedicated = {0};
|
||||
struct NR_CFRA cfra;
|
||||
NR_CFRA_t cfra;
|
||||
rach_ConfigDedicated.cfra = &cfra;
|
||||
ra->rach_ConfigDedicated = &rach_ConfigDedicated;
|
||||
|
||||
init_RA(&mac, &prach_resources, &nr_rach_ConfigCommon, &rach_ConfigGeneric, &rach_ConfigDedicated);
|
||||
init_RA(&mac, frame);
|
||||
|
||||
EXPECT_EQ(mac.ra.ra_type, RA_4_STEP);
|
||||
EXPECT_EQ(mac.state, UE_PERFORMING_RA);
|
||||
|
||||
@@ -521,8 +521,7 @@ static void config_common(gNB_MAC_INST *nrmac,
|
||||
// If absent, use SCS as derived from the prach-ConfigurationIndex (for 839)
|
||||
int config_index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex;
|
||||
int frame_type = get_frame_type(band, frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing);
|
||||
const int64_t *prach_config_info_p = get_prach_config_info(frequency_range, config_index, frame_type);
|
||||
int format = prach_config_info_p[0];
|
||||
int format = get_nr_prach_format_from_index(config_index, UL_pointA, frame_type) & 0xff;
|
||||
cfg->prach_config.prach_sub_c_spacing.value = get_delta_f_RA_long(format);
|
||||
}
|
||||
|
||||
|
||||
@@ -83,9 +83,8 @@ static int16_t ssb_index_from_prach(module_id_t module_idP,
|
||||
|
||||
float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value];
|
||||
uint16_t start_symbol_index = 0;
|
||||
uint8_t N_dur=0,N_t_slot=0,start_symbol = 0, temp_start_symbol = 0, N_RA_slot=0;
|
||||
uint16_t format,RA_sfn_index = -1;
|
||||
uint8_t config_period = 1;
|
||||
uint8_t temp_start_symbol = 0;
|
||||
uint16_t RA_sfn_index = -1;
|
||||
uint16_t prach_occasion_id = -1;
|
||||
uint8_t num_active_ssb = cc->num_active_ssb;
|
||||
NR_MsgA_ConfigCommon_r16_t *msgacc = NULL;
|
||||
@@ -93,42 +92,32 @@ static int16_t ssb_index_from_prach(module_id_t module_idP,
|
||||
msgacc = scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup;
|
||||
const int ul_mu = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
const int mu = nr_get_prach_or_ul_mu(msgacc, rach_ConfigCommon, ul_mu);
|
||||
frequency_range_t freq_range = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA > 2016666 ? FR2 : FR1;
|
||||
get_nr_prach_sched_from_info(cc->prach_info, config_index, frameP, slotP, mu, freq_range, &RA_sfn_index, cc->frame_type);
|
||||
|
||||
get_nr_prach_info_from_index(config_index,
|
||||
(int)frameP,
|
||||
(int)slotP,
|
||||
scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA,
|
||||
mu,
|
||||
cc->frame_type,
|
||||
&format,
|
||||
&start_symbol,
|
||||
&N_t_slot,
|
||||
&N_dur,
|
||||
&RA_sfn_index,
|
||||
&N_RA_slot,
|
||||
&config_period);
|
||||
uint8_t index = 0, slot_index = 0;
|
||||
for (slot_index = 0; slot_index < N_RA_slot; slot_index++) {
|
||||
if (N_RA_slot <= 1) { //1 PRACH slot in a subframe
|
||||
for (slot_index = 0; slot_index < cc->prach_info.N_RA_slot; slot_index++) {
|
||||
if (cc->prach_info.N_RA_slot <= 1) { // 1 PRACH slot in a subframe
|
||||
if((mu == 1) || (mu == 3))
|
||||
slot_index = 1; //For scs = 30khz and 120khz
|
||||
slot_index = 1; // For scs = 30khz and 120khz
|
||||
}
|
||||
for (int i = 0; i < N_t_slot; i++) {
|
||||
temp_start_symbol = (start_symbol + i * N_dur + 14 * slot_index) % 14;
|
||||
for (int i = 0; i < cc->prach_info.N_t_slot; i++) {
|
||||
temp_start_symbol = (cc->prach_info.start_symbol + i * cc->prach_info.N_dur + 14 * slot_index) % 14;
|
||||
if(symbol == temp_start_symbol) {
|
||||
start_symbol_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (N_RA_slot <= 1) { //1 PRACH slot in a subframe
|
||||
if (cc->prach_info.N_RA_slot <= 1) { // 1 PRACH slot in a subframe
|
||||
if((mu == 1) || (mu == 3))
|
||||
slot_index = 0; //For scs = 30khz and 120khz
|
||||
slot_index = 0; // For scs = 30khz and 120khz
|
||||
}
|
||||
|
||||
int config_period = cc->prach_info.x;
|
||||
// prach_occasion_id = subframe_index * N_t_slot * N_RA_slot * fdm + N_RA_slot_index * N_t_slot * fdm + freq_index + fdm * start_symbol_index;
|
||||
prach_occasion_id = (((frameP % (cc->max_association_period * config_period)) / config_period) * cc->total_prach_occasions_per_config_period) +
|
||||
(RA_sfn_index + slot_index) * N_t_slot * fdm + start_symbol_index * fdm + freq_index;
|
||||
prach_occasion_id =
|
||||
(((frameP % (cc->max_association_period * config_period)) / config_period) * cc->total_prach_occasions_per_config_period)
|
||||
+ (RA_sfn_index + slot_index) * cc->prach_info.N_t_slot * fdm + start_symbol_index * fdm + freq_index;
|
||||
|
||||
//one SSB have more than one continuous RO
|
||||
if(num_ssb_per_RO <= 1)
|
||||
@@ -159,14 +148,12 @@ void find_SSB_and_RO_available(gNB_MAC_INST *nrmac)
|
||||
nfapi_nr_config_request_scf_t *cfg = &nrmac->config[0];
|
||||
NR_RACH_ConfigCommon_t *rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
|
||||
uint8_t config_index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex;
|
||||
uint8_t N_dur=0,N_t_slot=0,start_symbol=0,N_RA_slot = 0;
|
||||
uint16_t format,N_RA_sfn = 0,unused_RA_occasion,repetition = 0;
|
||||
uint16_t unused_RA_occasion, repetition = 0;
|
||||
uint8_t num_active_ssb = 0;
|
||||
uint8_t max_association_period = 1;
|
||||
|
||||
struct NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB *ssb_perRACH_OccasionAndCB_PreamblesPerSSB = rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB;
|
||||
|
||||
switch (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present){
|
||||
switch (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present) {
|
||||
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth:
|
||||
cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1);
|
||||
break;
|
||||
@@ -194,31 +181,16 @@ void find_SSB_and_RO_available(gNB_MAC_INST *nrmac)
|
||||
default:
|
||||
AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present);
|
||||
break;
|
||||
}
|
||||
|
||||
NR_MsgA_ConfigCommon_r16_t *msgacc = NULL;
|
||||
if (scc->uplinkConfigCommon->initialUplinkBWP->ext1 && scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16)
|
||||
msgacc = scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup;
|
||||
const int ul_mu = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
const int mu = nr_get_prach_or_ul_mu(msgacc, rach_ConfigCommon, ul_mu);
|
||||
}
|
||||
|
||||
// prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4
|
||||
get_nr_prach_occasion_info_from_index(config_index,
|
||||
scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA,
|
||||
mu,
|
||||
cc->frame_type,
|
||||
&format,
|
||||
&start_symbol,
|
||||
&N_t_slot,
|
||||
&N_dur,
|
||||
&N_RA_slot,
|
||||
&N_RA_sfn,
|
||||
&max_association_period);
|
||||
frequency_range_t freq_range = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA > 2016666 ? FR2 : FR1;
|
||||
nr_prach_info_t prach_info = get_nr_prach_occasion_info_from_index(config_index, freq_range, cc->frame_type);
|
||||
|
||||
float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value];
|
||||
uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value;
|
||||
uint64_t L_ssb = (((uint64_t) cfg->ssb_table.ssb_mask_list[0].ssb_mask.value) << 32) | cfg->ssb_table.ssb_mask_list[1].ssb_mask.value;
|
||||
uint32_t total_RA_occasions = N_RA_sfn * N_t_slot * N_RA_slot * fdm;
|
||||
uint32_t total_RA_occasions = prach_info.N_RA_sfn * prach_info.N_t_slot * prach_info.N_RA_slot * fdm;
|
||||
|
||||
for(int i = 0; i < 64; i++) {
|
||||
if ((L_ssb >> (63 - i)) & 0x01) { // only if the bit of L_ssb at current ssb index is 1
|
||||
@@ -228,7 +200,7 @@ void find_SSB_and_RO_available(gNB_MAC_INST *nrmac)
|
||||
}
|
||||
|
||||
cc->total_prach_occasions_per_config_period = total_RA_occasions;
|
||||
for(int i = 1; (1 << (i-1)) <= max_association_period; i++) {
|
||||
for (int i = 1; (1 << (i - 1)) <= prach_info.max_association_period; i++) {
|
||||
cc->max_association_period = (1 << (i - 1));
|
||||
total_RA_occasions = total_RA_occasions * cc->max_association_period;
|
||||
if(total_RA_occasions >= (int) (num_active_ssb / num_ssb_per_RO)) {
|
||||
@@ -240,14 +212,16 @@ void find_SSB_and_RO_available(gNB_MAC_INST *nrmac)
|
||||
unused_RA_occasion = total_RA_occasions - (int)((num_active_ssb * repetition) / num_ssb_per_RO);
|
||||
cc->total_prach_occasions = total_RA_occasions - unused_RA_occasion;
|
||||
cc->num_active_ssb = num_active_ssb;
|
||||
cc->prach_info = prach_info;
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"Total available RO %d, num of active SSB %d: unused RO = %d association_period %u N_RA_sfn %u total_prach_occasions_per_config_period %u\n",
|
||||
"Total available RO %d, num of active SSB %d: unused RO = %d association_period %u N_RA_sfn %u "
|
||||
"total_prach_occasions_per_config_period %u\n",
|
||||
cc->total_prach_occasions,
|
||||
cc->num_active_ssb,
|
||||
unused_RA_occasion,
|
||||
cc->max_association_period,
|
||||
N_RA_sfn,
|
||||
prach_info.N_RA_sfn,
|
||||
cc->total_prach_occasions_per_config_period);
|
||||
}
|
||||
|
||||
@@ -396,10 +370,6 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
if (is_ul_slot(slotP, &RC.nrmac[module_idP]->frame_structure)) {
|
||||
const NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &rach_ConfigCommon->rach_ConfigGeneric;
|
||||
uint8_t config_index = rach_ConfigGeneric->prach_ConfigurationIndex;
|
||||
uint8_t N_dur, N_t_slot, start_symbol = 0, N_RA_slot;
|
||||
uint16_t RA_sfn_index = -1;
|
||||
uint8_t config_period = 1;
|
||||
uint16_t format;
|
||||
int slot_index = 0;
|
||||
uint16_t prach_occasion_id = -1;
|
||||
|
||||
@@ -409,29 +379,18 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
const int ul_mu = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
const int mu = nr_get_prach_or_ul_mu(msgacc, rach_ConfigCommon, ul_mu);
|
||||
// prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4
|
||||
if (get_nr_prach_info_from_index(config_index,
|
||||
(int)frameP,
|
||||
(int)slotP,
|
||||
scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA,
|
||||
mu,
|
||||
cc->frame_type,
|
||||
&format,
|
||||
&start_symbol,
|
||||
&N_t_slot,
|
||||
&N_dur,
|
||||
&RA_sfn_index,
|
||||
&N_RA_slot,
|
||||
&config_period)) {
|
||||
uint16_t RA_sfn_index = -1;
|
||||
frequency_range_t freq_range = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA > 2016666 ? FR2 : FR1;
|
||||
if (get_nr_prach_sched_from_info(cc->prach_info, config_index, frameP, slotP, mu, freq_range, &RA_sfn_index, cc->frame_type)) {
|
||||
uint16_t format0 = cc->prach_info.format & 0xff; // first column of format from table
|
||||
uint16_t format1 = (cc->prach_info.format >> 8) & 0xff; // second column of format from table
|
||||
|
||||
uint16_t format0 = format & 0xff; // first column of format from table
|
||||
uint16_t format1 = (format >> 8) & 0xff; // second column of format from table
|
||||
|
||||
if (N_RA_slot > 1) { //more than 1 PRACH slot in a subframe
|
||||
if (cc->prach_info.N_RA_slot > 1) { // more than 1 PRACH slot in a subframe
|
||||
if (slotP % 2 == 1)
|
||||
slot_index = 1;
|
||||
else
|
||||
slot_index = 0;
|
||||
} else if (N_RA_slot <= 1) { //1 PRACH slot in a subframe
|
||||
} else if (cc->prach_info.N_RA_slot <= 1) { // 1 PRACH slot in a subframe
|
||||
slot_index = 0;
|
||||
}
|
||||
|
||||
@@ -439,9 +398,11 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
UL_tti_req->Slot = slotP;
|
||||
UL_tti_req->rach_present = 1;
|
||||
NR_beam_alloc_t beam = {0};
|
||||
uint32_t N_t_slot = cc->prach_info.N_t_slot;
|
||||
uint32_t start_symb = cc->prach_info.start_symbol;
|
||||
for (int fdm_index = 0; fdm_index < fdm; fdm_index++) { // one structure per frequency domain occasion
|
||||
for (int td_index = 0; td_index < N_t_slot; td_index++) {
|
||||
|
||||
uint32_t config_period = cc->prach_info.x;
|
||||
prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period) * cc->total_prach_occasions_per_config_period) +
|
||||
(RA_sfn_index + slot_index) * N_t_slot * fdm + td_index * fdm + fdm_index;
|
||||
|
||||
@@ -482,7 +443,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
// filling the prach fapi structure
|
||||
prach_pdu->phys_cell_id = *scc->physCellId;
|
||||
prach_pdu->num_prach_ocas = N_t_slot;
|
||||
prach_pdu->prach_start_symbol = start_symbol;
|
||||
prach_pdu->prach_start_symbol = start_symb;
|
||||
prach_pdu->num_ra = fdm_index;
|
||||
prach_pdu->num_cs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig,
|
||||
format0,
|
||||
@@ -499,7 +460,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
slotP,
|
||||
prach_occasion_id,
|
||||
prach_pdu->num_ra,
|
||||
prach_pdu->prach_start_symbol,
|
||||
start_symb,
|
||||
slot_index,
|
||||
RA_sfn_index);
|
||||
// SCF PRACH PDU format field does not consider A1/B1 etc. possibilities
|
||||
@@ -579,6 +540,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
const int16_t n_ra_rb = get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, mu_pusch);
|
||||
// mark PRBs as occupied for current and future slots if prach extends beyond current slot
|
||||
int total_prach_slots;
|
||||
uint32_t N_dur = cc->prach_info.N_dur;
|
||||
if (format0 < 4) {
|
||||
N_dur = 14; // number of PRACH symbols in PRACH slot
|
||||
total_prach_slots = get_long_prach_dur(format0, mu_pusch);
|
||||
@@ -595,7 +557,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
gNB->vrb_map_UL_size,
|
||||
slots_frame,
|
||||
bwp_start + rach_ConfigGeneric->msg1_FrequencyStart,
|
||||
start_symbol,
|
||||
start_symb,
|
||||
N_t_slot * N_dur,
|
||||
cc);
|
||||
}
|
||||
@@ -1411,6 +1373,8 @@ static bool msg2_in_response_window(int rach_frame,
|
||||
int current_slot)
|
||||
{
|
||||
int window_slots = get_response_window(rrc_ra_ResponseWindow);
|
||||
if (window_slots > n_slots_frame)
|
||||
LOG_E(NR_MAC, "RA-ResponseWindow need to be configured to a value lower than or equal to 10 ms\n");
|
||||
int abs_rach = n_slots_frame * rach_frame + rach_slot;
|
||||
int abs_now = n_slots_frame * current_frame + current_slot;
|
||||
int diff = (n_slots_frame * 1024 + abs_now - abs_rach) % (n_slots_frame * 1024);
|
||||
|
||||
@@ -302,6 +302,7 @@ typedef struct {
|
||||
int cb_preambles_per_ssb;
|
||||
/// Max prach length in slots
|
||||
int prach_len;
|
||||
nr_prach_info_t prach_info;
|
||||
} NR_COMMON_channels_t;
|
||||
|
||||
// SP ZP CSI-RS Resource Set Activation/Deactivation MAC CE
|
||||
|
||||
@@ -390,8 +390,7 @@ static bool is_my_dci(NR_UE_MAC_INST_t *mac, nfapi_nr_dl_dci_pdu_t *received_pdu
|
||||
already. Only once the RA procedure succeeds is the CRNTI value updated
|
||||
to the TC_RNTI. */
|
||||
if (get_softmodem_params()->nsa) {
|
||||
if (received_pdu->RNTI != mac->crnti &&
|
||||
(received_pdu->RNTI != mac->ra.ra_rnti || mac->ra.RA_RAPID_found))
|
||||
if (received_pdu->RNTI != mac->crnti && (received_pdu->RNTI != mac->ra.ra_rnti))
|
||||
return false;
|
||||
}
|
||||
if (IS_SA_MODE(get_softmodem_params())) {
|
||||
@@ -1122,9 +1121,14 @@ static nr_dci_format_t handle_dci(NR_UE_MAC_INST_t *mac,
|
||||
// if notification of a reception of a PDCCH transmission of the SpCell is received from lower layers
|
||||
// if the C-RNTI MAC CE was included in Msg3
|
||||
// consider this Contention Resolution successful
|
||||
if (mac->ra.msg3_C_RNTI && mac->ra.ra_state == nrRA_WAIT_CONTENTION_RESOLUTION)
|
||||
if (mac->msg3_C_RNTI && mac->ra.ra_state == nrRA_WAIT_CONTENTION_RESOLUTION)
|
||||
nr_ra_succeeded(mac, gNB_index, frame, slot);
|
||||
|
||||
// suspend RAR response window timer
|
||||
// (in RFsim running multiple slot in parallel it might expire while decoding MSG2)
|
||||
if (mac->ra.ra_state == nrRA_WAIT_RAR)
|
||||
nr_timer_suspension(&mac->ra.response_window_timer);
|
||||
|
||||
return nr_ue_process_dci_indication_pdu(mac, frame, slot, dci);
|
||||
}
|
||||
|
||||
@@ -1292,11 +1296,14 @@ static uint32_t nr_ue_dl_processing(NR_UE_MAC_INST_t *mac, nr_downlink_indicatio
|
||||
ret_mask |= (handle_dlsch(mac, dl_info, i)) << FAPI_NR_RX_PDU_TYPE_DLSCH;
|
||||
break;
|
||||
case FAPI_NR_RX_PDU_TYPE_RAR:
|
||||
ret_mask |= (handle_dlsch(mac, dl_info, i)) << FAPI_NR_RX_PDU_TYPE_RAR;
|
||||
if (!dl_info->rx_ind->rx_indication_body[i].pdsch_pdu.ack_nack)
|
||||
if (!dl_info->rx_ind->rx_indication_body[i].pdsch_pdu.ack_nack) {
|
||||
LOG_W(PHY, "Received a RAR-Msg2 but LDPC decode failed\n");
|
||||
else
|
||||
// resume RAR response window timer if MSG2 decoding failed
|
||||
nr_timer_suspension(&mac->ra.response_window_timer);
|
||||
} else {
|
||||
LOG_I(PHY, "RAR-Msg2 decoded\n");
|
||||
}
|
||||
ret_mask |= (handle_dlsch(mac, dl_info, i)) << FAPI_NR_RX_PDU_TYPE_RAR;
|
||||
break;
|
||||
case FAPI_NR_CSIRS_IND:
|
||||
ret_mask |= (handle_csirs_measurements(mac,
|
||||
@@ -1330,12 +1337,15 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info)
|
||||
return ret2;
|
||||
}
|
||||
|
||||
void nr_ue_slot_indication(uint8_t mod_id)
|
||||
void nr_ue_slot_indication(uint8_t mod_id, bool is_tx)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
int ret = pthread_mutex_lock(&mac->if_mutex);
|
||||
AssertFatal(!ret, "mutex failed %d\n", ret);
|
||||
update_mac_timers(mac);
|
||||
if (is_tx)
|
||||
update_mac_ul_timers(mac);
|
||||
else
|
||||
update_mac_dl_timers(mac);
|
||||
ret = pthread_mutex_unlock(&mac->if_mutex);
|
||||
AssertFatal(!ret, "mutex failed %d\n", ret);
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ typedef int (nr_ue_dl_indication_f)(nr_downlink_indication_t *dl_info);
|
||||
*/
|
||||
typedef int (nr_ue_ul_indication_f)(nr_uplink_indication_t *ul_info);
|
||||
|
||||
typedef void (nr_ue_slot_indication_f)(uint8_t mod_id);
|
||||
typedef void (nr_ue_slot_indication_f)(uint8_t mod_id, bool is_tx);
|
||||
|
||||
/*
|
||||
* Generic type of an application-defined callback to return various
|
||||
|
||||
@@ -3819,11 +3819,7 @@ NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t u
|
||||
uplink->ra_Prioritization = NULL;
|
||||
uplink->cfra = calloc(1, sizeof(struct NR_CFRA));
|
||||
uplink->cfra->ext1 = NULL;
|
||||
uplink->cfra->occasions = calloc(1, sizeof(struct NR_CFRA__occasions));
|
||||
memcpy(&uplink->cfra->occasions->rach_ConfigGeneric,
|
||||
&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric,
|
||||
sizeof(NR_RACH_ConfigGeneric_t));
|
||||
asn1cCallocOne(uplink->cfra->occasions->ssb_perRACH_Occasion, NR_CFRA__occasions__ssb_perRACH_Occasion_one);
|
||||
uplink->cfra->occasions = NULL;
|
||||
uplink->cfra->resources.present = NR_CFRA__resources_PR_ssb;
|
||||
uplink->cfra->resources.choice.ssb = calloc(1, sizeof(struct NR_CFRA__resources__ssb));
|
||||
uplink->cfra->resources.choice.ssb->ra_ssb_OccasionMaskIndex = 0;
|
||||
|
||||
@@ -159,11 +159,11 @@ void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id)
|
||||
itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(mod_id), message_p);
|
||||
}
|
||||
|
||||
void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, int gnb_id)
|
||||
void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, bool prepare_payload)
|
||||
{
|
||||
MessageDef *message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_MSG3_IND);
|
||||
NR_RRC_MAC_MSG3_IND (message_p).rnti = rnti;
|
||||
NR_RRC_MAC_MSG3_IND (message_p).gnb_id = gnb_id;
|
||||
NR_RRC_MAC_MSG3_IND (message_p).prepare_payload = prepare_payload;
|
||||
itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(mod_id), message_p);
|
||||
}
|
||||
|
||||
@@ -177,10 +177,9 @@ void nr_ue_rrc_timer_trigger(int instance, int frame, int gnb_id)
|
||||
itti_send_msg_to_task(TASK_RRC_NRUE, instance, message_p);
|
||||
}
|
||||
|
||||
void nr_mac_rrc_ra_ind(const module_id_t mod_id, int frame, bool success)
|
||||
void nr_mac_rrc_ra_ind(const module_id_t mod_id, bool success)
|
||||
{
|
||||
MessageDef *message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_RA_IND);
|
||||
NR_RRC_MAC_RA_IND (message_p).frame = frame;
|
||||
NR_RRC_MAC_RA_IND (message_p).RA_succeeded = success;
|
||||
itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(mod_id), message_p);
|
||||
}
|
||||
|
||||
@@ -37,9 +37,9 @@ void nr_mac_rrc_data_ind_ue(const module_id_t module_id,
|
||||
const uint8_t* pduP,
|
||||
const sdu_size_t pdu_len);
|
||||
void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id);
|
||||
void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, int gnb_id);
|
||||
void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, bool prepare_payload);
|
||||
void nr_ue_rrc_timer_trigger(int instance, int frame, int gnb_id);
|
||||
void nr_mac_rrc_ra_ind(const module_id_t mod_id, int frame, bool success);
|
||||
void nr_mac_rrc_ra_ind(const module_id_t mod_id, bool success);
|
||||
void nsa_sendmsg_to_lte_ue(const void *message, size_t msg_len, Rrc_Msg_Type_t msg_type);
|
||||
void process_msg_rcc_to_mac(MessageDef *msg);
|
||||
#endif
|
||||
|
||||
+43
-17
@@ -335,8 +335,6 @@ static void nr_rrc_process_sib1(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_inf
|
||||
SI_info->sib1_validity = SIB_VALID;
|
||||
if (rrc->nrRrcState == RRC_STATE_IDLE_NR) {
|
||||
rrc->ra_trigger = RRC_CONNECTION_SETUP;
|
||||
// preparing RRC setup request payload in advance
|
||||
nr_rrc_ue_prepare_RRCSetupRequest(rrc);
|
||||
}
|
||||
|
||||
NR_SIB1_v1700_IEs_t *sib1_v1700 = NULL;
|
||||
@@ -856,15 +854,6 @@ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc,
|
||||
nr_timer_stop(&timers->T311);
|
||||
rrc->ra_trigger = RRC_CONNECTION_REESTABLISHMENT;
|
||||
|
||||
// preparing MSG3 for re-establishment in advance
|
||||
uint8_t buffer[1024];
|
||||
int buf_size = do_RRCReestablishmentRequest(buffer,
|
||||
rrc->reestablishment_cause,
|
||||
rrc->phyCellID,
|
||||
rrc->rnti); // old rnti
|
||||
|
||||
nr_rlc_srb_recv_sdu(rrc->ue_id, 0, buffer, buf_size);
|
||||
|
||||
// apply the default MAC Cell Group configuration
|
||||
// (done at MAC by calling nr_ue_mac_default_configs)
|
||||
|
||||
@@ -892,6 +881,31 @@ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc,
|
||||
return;
|
||||
}
|
||||
|
||||
static void nr_rrc_ue_prepare_RRCReestablishmentRequest(NR_UE_RRC_INST_t *rrc)
|
||||
{
|
||||
uint8_t buffer[1024];
|
||||
int buf_size = do_RRCReestablishmentRequest(buffer, rrc->reestablishment_cause, rrc->phyCellID, rrc->rnti); // old rnti
|
||||
nr_rlc_srb_recv_sdu(rrc->ue_id, 0, buffer, buf_size);
|
||||
}
|
||||
|
||||
static void nr_rrc_prepare_msg3_payload(NR_UE_RRC_INST_t *rrc)
|
||||
{
|
||||
if (!IS_SA_MODE(get_softmodem_params()))
|
||||
return;
|
||||
switch (rrc->ra_trigger) {
|
||||
case RRC_CONNECTION_SETUP:
|
||||
// preparing RRC setup request payload in advance
|
||||
nr_rrc_ue_prepare_RRCSetupRequest(rrc);
|
||||
break;
|
||||
case RRC_CONNECTION_REESTABLISHMENT:
|
||||
// preparing MSG3 for re-establishment in advance
|
||||
nr_rrc_ue_prepare_RRCReestablishmentRequest(rrc);
|
||||
break;
|
||||
default:
|
||||
AssertFatal(false, "RA trigger not implemented\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void nr_rrc_handle_msg3_indication(NR_UE_RRC_INST_t *rrc, rnti_t rnti)
|
||||
{
|
||||
NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants;
|
||||
@@ -1975,6 +1989,16 @@ void nr_rrc_handle_ra_indication(NR_UE_RRC_INST_t *rrc, bool ra_succeeded)
|
||||
nr_timer_stop(&timers->T304);
|
||||
// TODO handle the rest of procedures as described in 5.3.5.3 for when
|
||||
// reconfigurationWithSync is included in spCellConfig
|
||||
} else if (!ra_succeeded) {
|
||||
// upon random access problem indication from MCG MAC
|
||||
// while neither T300, T301, T304, T311 nor T319 are running
|
||||
// consider radio link failure to be detected
|
||||
if (!nr_timer_is_active(&timers->T300)
|
||||
&& !nr_timer_is_active(&timers->T301)
|
||||
&& !nr_timer_is_active(&timers->T304)
|
||||
&& !nr_timer_is_active(&timers->T311)
|
||||
&& !nr_timer_is_active(&timers->T319))
|
||||
handle_rlf_detection(rrc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2035,16 +2059,18 @@ void *rrc_nrue(void *notUsed)
|
||||
break;
|
||||
|
||||
case NR_RRC_MAC_MSG3_IND:
|
||||
nr_rrc_handle_msg3_indication(rrc, NR_RRC_MAC_MSG3_IND(msg_p).rnti);
|
||||
if (NR_RRC_MAC_MSG3_IND(msg_p).prepare_payload)
|
||||
nr_rrc_prepare_msg3_payload(rrc);
|
||||
else
|
||||
nr_rrc_handle_msg3_indication(rrc, NR_RRC_MAC_MSG3_IND(msg_p).rnti);
|
||||
break;
|
||||
|
||||
case NR_RRC_MAC_RA_IND:
|
||||
LOG_D(NR_RRC,
|
||||
"[UE %ld] Received %s: frame %d RA %s\n",
|
||||
rrc->ue_id,
|
||||
ITTI_MSG_NAME(msg_p),
|
||||
NR_RRC_MAC_RA_IND(msg_p).frame,
|
||||
NR_RRC_MAC_RA_IND(msg_p).RA_succeeded ? "successful" : "failed");
|
||||
"[UE %ld] Received %s: RA %s\n",
|
||||
rrc->ue_id,
|
||||
ITTI_MSG_NAME(msg_p),
|
||||
NR_RRC_MAC_RA_IND(msg_p).RA_succeeded ? "successful" : "failed");
|
||||
nr_rrc_handle_ra_indication(rrc, NR_RRC_MAC_RA_IND(msg_p).RA_succeeded);
|
||||
break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user