Commit c48e96e9 authored by Mario Hudon's avatar Mario Hudon

-UE RACH updates

  - Added support for FR1 in RO selection
  -RACH preamble selected according to the chosen RO
parent 597ddf75
...@@ -170,6 +170,7 @@ typedef struct { ...@@ -170,6 +170,7 @@ typedef struct {
uint8_t prach_format; uint8_t prach_format;
/// Num RA /// Num RA
uint8_t num_ra; uint8_t num_ra;
uint8_t prach_slot;
uint8_t prach_start_symbol; uint8_t prach_start_symbol;
/// 38.211 (NCS 38.211 6.3.3.1). /// 38.211 (NCS 38.211 6.3.3.1).
uint16_t num_cs; uint16_t num_cs;
...@@ -179,6 +180,8 @@ typedef struct { ...@@ -179,6 +180,8 @@ typedef struct {
uint8_t restricted_set; uint8_t restricted_set;
/// see TS 38.211 (6.3.3.2). /// see TS 38.211 (6.3.3.2).
uint16_t freq_msg1; uint16_t freq_msg1;
// 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;
// nfapi_nr_ul_beamforming_t beamforming; // nfapi_nr_ul_beamforming_t beamforming;
} fapi_nr_ul_config_prach_pdu; } fapi_nr_ul_config_prach_pdu;
......
...@@ -4526,7 +4526,7 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t ...@@ -4526,7 +4526,7 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t
ue->ulsch_Msg3_active[i] = 0; ue->ulsch_Msg3_active[i] = 0;
} }
} }
nr_prach = nr_ue_get_rach(ue->prach_resources[gNB_id], mod_id, ue->CC_id, UE_mode, frame_tx, gNB_id, nr_tti_tx); nr_prach = nr_ue_get_rach(ue->prach_resources[gNB_id], ue->prach_vars[0], mod_id, ue->CC_id, UE_mode, frame_tx, gNB_id, nr_tti_tx);
} }
} }
......
...@@ -1018,9 +1018,13 @@ void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss, ...@@ -1018,9 +1018,13 @@ void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss,
} }
// Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config // 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_ServingCellConfigCommon_t *scc) { static void build_ro_list(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired) {
int x,y; // PRACH Configuration Index table variables used to compute the valid frame numbers 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;
boolean_t even_slot_invalid;
int64_t s_map; int64_t s_map;
uint8_t prach_conf_start_symbol; // Starting symbol of the PRACH occasions in the PRACH slot 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_t_slot; // Number of PRACH occasions in a 14-symbols PRACH slot
...@@ -1035,6 +1039,10 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc) { ...@@ -1035,6 +1039,10 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc) {
uint32_t pointa; uint32_t pointa;
int msg1_FDM; int msg1_FDM;
uint8_t prach_conf_period_idx;
uint8_t nb_of_frames_per_prach_conf_period;
uint8_t prach_conf_period_frame_idx;
NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric;
...@@ -1071,102 +1079,137 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc) { ...@@ -1071,102 +1079,137 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc) {
// WIP-IDCC: RACH preambles are not mapped yet (assumptions: ssb_per_rach is <= 1, totalNumberOfRA = CB-preamblesPerSSB - see NR_MAC_UE/nr_ra_procedures.c->nr_get_prach_resources) // WIP-IDCC: RACH preambles are not mapped yet (assumptions: ssb_per_rach is <= 1, totalNumberOfRA = CB-preamblesPerSSB - see NR_MAC_UE/nr_ra_procedures.c->nr_get_prach_resources)
// Identify the proper PRACH Configuration Index table according to the operating frequency // Identify the proper PRACH Configuration Index table according to the operating frequency
LOG_D(MAC,"Pointa %d, mu = %d\n", pointa, mu); LOG_D(MAC,"Pointa %u, mu = %u, PRACH config index = %u, unpaired = %u\n", pointa, mu, config_index, unpaired);
if (pointa > 2016666) { //FR2
int y2; // PRACH Configuration Index table additional variable used to compute the valid frame numbers
uint8_t slot_60khz;
uint8_t prach_conf_period_idx; if (pointa > 2016666) { //FR2
uint8_t nb_of_frames_per_prach_conf_period;
uint8_t prach_conf_period_frame_idx;
x = table_6_3_3_2_4_prachConfig_Index[config_index][2]; x = table_6_3_3_2_4_prachConfig_Index[config_index][2];
y = table_6_3_3_2_4_prachConfig_Index[config_index][3]; y = table_6_3_3_2_4_prachConfig_Index[config_index][3];
y2 = table_6_3_3_2_4_prachConfig_Index[config_index][4]; y2 = table_6_3_3_2_4_prachConfig_Index[config_index][4];
prach_assoc_pattern.nb_of_prach_conf_period_in_max_period = MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD / x; s_map = table_6_3_3_2_4_prachConfig_Index[config_index][5];
nb_of_frames_per_prach_conf_period = x;
LOG_D(MAC,"nb_of_prach_conf_period_in_max_period %d\n", prach_assoc_pattern.nb_of_prach_conf_period_in_max_period); prach_conf_start_symbol = table_6_3_3_2_4_prachConfig_Index[config_index][6];
N_t_slot = table_6_3_3_2_4_prachConfig_Index[config_index][8];
// Fill in the PRACH occasions table for every slot in every frame in every PRACH configuration periods in the maximum association pattern period N_dur = table_6_3_3_2_4_prachConfig_Index[config_index][9];
// ---------------------------------------------------------------------------------------------------------------------------------------------- if (table_6_3_3_2_4_prachConfig_Index[config_index][1] != -1)
// ---------------------------------------------------------------------------------------------------------------------------------------------- format2 = (uint8_t) table_6_3_3_2_4_prachConfig_Index[config_index][1];
format = ((uint8_t) table_6_3_3_2_4_prachConfig_Index[config_index][0]) | (format2<<8);
// For every PRACH configuration periods
// ------------------------------------- slot_shift_for_map = mu-2;
for (prach_conf_period_idx=0; prach_conf_period_idx<prach_assoc_pattern.nb_of_prach_conf_period_in_max_period; prach_conf_period_idx++) { if ( (mu == 3) && (table_6_3_3_2_4_prachConfig_Index[config_index][7] == 1) )
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion = 0; even_slot_invalid = true;
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_frame = nb_of_frames_per_prach_conf_period; else
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_slot = nr_slots_per_frame[mu]; even_slot_invalid = false;
}
LOG_D(MAC,"PRACH Conf Period Idx %d\n", prach_conf_period_idx); else { // FR1
if (unpaired) {
// For every frames in a PRACH configuration period x = table_6_3_3_2_3_prachConfig_Index[config_index][2];
// ------------------------------------------------ y = table_6_3_3_2_3_prachConfig_Index[config_index][3];
for (prach_conf_period_frame_idx=0; prach_conf_period_frame_idx<nb_of_frames_per_prach_conf_period; prach_conf_period_frame_idx++) {
frame = (prach_conf_period_idx * nb_of_frames_per_prach_conf_period) + prach_conf_period_frame_idx; s_map = table_6_3_3_2_3_prachConfig_Index[config_index][4];
LOG_D(MAC,"PRACH Conf Period Frame Idx %d - Frame %d\n", prach_conf_period_frame_idx, frame); prach_conf_start_symbol = table_6_3_3_2_3_prachConfig_Index[config_index][5];
// Is it a valid frame for this PRACH configuration index? (n_sfn mod x = y) N_t_slot = table_6_3_3_2_3_prachConfig_Index[config_index][7];
if ( (frame%x)==y || (frame%x)==y2 ) { N_dur = table_6_3_3_2_3_prachConfig_Index[config_index][8];
if (table_6_3_3_2_3_prachConfig_Index[config_index][1] != -1)
// For every slot in a frame format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[config_index][1];
// ------------------------- format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[config_index][0]) | (format2<<8);
for (slot=0; slot<nr_slots_per_frame[mu]; slot++) { }
// Is it a valid slot? else { // FDD
slot_60khz = slot >> (mu-2); // in PRACH configuration index table slots are numbered wrt 60kHz x = table_6_3_3_2_2_prachConfig_Index[config_index][2];
s_map = table_6_3_3_2_4_prachConfig_Index[config_index][5]; y = table_6_3_3_2_2_prachConfig_Index[config_index][3];
if ( (s_map>>slot_60khz)&0x01 ) {
// Valid slot according to the 60kHz table
// Additionally, for 120kHz, we must check for the n_RA_Slot param also
if (mu == 3) {
if ( (table_6_3_3_2_4_prachConfig_Index[config_index][7] == 1) && (slot%2 == 0) )
continue; // no prach in even slots @ 120kHz for 1 prach per 60khz slot
}
// We're good: valid frame and valid slot s_map = table_6_3_3_2_2_prachConfig_Index[config_index][4];
// Compute all the PRACH occasions in the slot
prach_conf_start_symbol = table_6_3_3_2_4_prachConfig_Index[config_index][6];
N_t_slot = table_6_3_3_2_4_prachConfig_Index[config_index][8];
N_dur = table_6_3_3_2_4_prachConfig_Index[config_index][9];
if (table_6_3_3_2_4_prachConfig_Index[config_index][1] != -1)
format2 = (uint8_t) table_6_3_3_2_4_prachConfig_Index[config_index][1];
format = ((uint8_t) table_6_3_3_2_4_prachConfig_Index[config_index][0]) | (format2<<8);
uint8_t n_prach_occ_in_time;
uint8_t n_prach_occ_in_freq;
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time = N_t_slot;
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq = nb_fdm;
for (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(MAC,"PRACH Occ in time %d\n", n_prach_occ_in_time);
for (n_prach_occ_in_freq=0; n_prach_occ_in_freq<nb_fdm; n_prach_occ_in_freq++) {
prach_occasion_info_t *prach_occasion_p = &prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].prach_occasion[n_prach_occ_in_time][n_prach_occ_in_freq];
prach_occasion_p->start_symbol = start_symbol;
prach_occasion_p->fdm = n_prach_occ_in_freq;
prach_occasion_p->frame = frame;
prach_occasion_p->slot = slot;
prach_occasion_p->format = format;
printf("\nprach_conf_period_idx : %d, .nb_of_prach_occasion : %d\n",prach_conf_period_idx,prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion);
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion++;
LOG_D(MAC,"Adding a PRACH occasion: fdm %d, frame %d, 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, slot, start_symbol, n_prach_occ_in_time, n_prach_occ_in_freq, prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion,
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time,
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].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)
} // FR2?
prach_conf_start_symbol = table_6_3_3_2_2_prachConfig_Index[config_index][5];
N_t_slot = table_6_3_3_2_2_prachConfig_Index[config_index][7];
N_dur = table_6_3_3_2_2_prachConfig_Index[config_index][8];
if (table_6_3_3_2_2_prachConfig_Index[config_index][1] != -1)
format2 = (uint8_t) table_6_3_3_2_2_prachConfig_Index[config_index][1];
format = ((uint8_t) table_6_3_3_2_2_prachConfig_Index[config_index][0]) | (format2<<8);
}
y2 = y;
slot_shift_for_map = mu;
if ( (mu == 1) && (table_6_3_3_2_3_prachConfig_Index[config_index][6] <= 1) )
even_slot_invalid = true;
else
even_slot_invalid = false;
} // FR2 / FR1
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;
LOG_D(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 (prach_conf_period_idx=0; prach_conf_period_idx<prach_assoc_pattern.nb_of_prach_conf_period_in_max_period; prach_conf_period_idx++) {
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion = 0;
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_frame = nb_of_frames_per_prach_conf_period;
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_slot = nr_slots_per_frame[mu];
LOG_D(MAC,"PRACH Conf Period Idx %d\n", prach_conf_period_idx);
// For every frames in a PRACH configuration period
// ------------------------------------------------
for (prach_conf_period_frame_idx=0; prach_conf_period_frame_idx<nb_of_frames_per_prach_conf_period; prach_conf_period_frame_idx++) {
frame = (prach_conf_period_idx * nb_of_frames_per_prach_conf_period) + prach_conf_period_frame_idx;
LOG_D(MAC,"PRACH Conf Period Frame Idx %d - Frame %d\n", prach_conf_period_frame_idx, frame);
// Is it a valid frame for this PRACH configuration index? (n_sfn mod x = y)
if ( (frame%x)==y || (frame%x)==y2 ) {
// For every slot in a frame
// -------------------------
for (slot=0; slot<nr_slots_per_frame[mu]; 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
uint8_t n_prach_occ_in_time;
uint8_t n_prach_occ_in_freq;
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time = N_t_slot;
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq = nb_fdm;
for (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(MAC,"PRACH Occ in time %d\n", n_prach_occ_in_time);
for (n_prach_occ_in_freq=0; n_prach_occ_in_freq<nb_fdm; n_prach_occ_in_freq++) {
prach_occasion_info_t *prach_occasion_p = &prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].prach_occasion[n_prach_occ_in_time][n_prach_occ_in_freq];
prach_occasion_p->start_symbol = start_symbol;
prach_occasion_p->fdm = n_prach_occ_in_freq;
prach_occasion_p->frame = frame;
prach_occasion_p->slot = slot;
prach_occasion_p->format = format;
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion++;
LOG_D(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, slot, start_symbol, n_prach_occ_in_time, n_prach_occ_in_freq, prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion,
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time,
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].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 // Build the list of all the valid/transmitted SSBs according to the config
...@@ -1174,27 +1217,62 @@ static void build_ssb_list(NR_ServingCellConfigCommon_t *scc) { ...@@ -1174,27 +1217,62 @@ static void build_ssb_list(NR_ServingCellConfigCommon_t *scc) {
// Create the list of transmitted SSBs // Create the list of transmitted SSBs
// =================================== // ===================================
// WIP-IDCC: Assumption: the optional ssb_PositionsInBurst is provided BIT_STRING_t *ssb_bitmap;
BIT_STRING_t *ssb_bitmap = &scc->ssb_PositionsInBurst->choice.longBitmap;
uint64_t ssb_positionsInBurst; uint64_t ssb_positionsInBurst;
uint8_t nb_of_bytes = ssb_bitmap->size;
uint8_t ssb_idx = 0; uint8_t ssb_idx = 0;
// WIP-IDCC: Support only long SSB bitmap for now switch (scc->ssb_PositionsInBurst->present) {
if (8 == nb_of_bytes) { case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap:
ssb_positionsInBurst = BIT_STRING_to_uint64(ssb_bitmap); ssb_bitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap;
LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%llx\n", ssb_positionsInBurst); ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap);
LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst);
for (uint8_t bit_nb=63; bit_nb<=63; bit_nb--) { for (uint8_t bit_nb=3; bit_nb<=3; bit_nb--) {
// If SSB is transmitted // If SSB is transmitted
if ((ssb_positionsInBurst>>bit_nb) & 0x01) { if ((ssb_positionsInBurst>>bit_nb) & 0x01) {
ssb_list.nb_tx_ssb++; ssb_list.nb_tx_ssb++;
ssb_list.tx_ssb[ssb_idx].transmitted = true; ssb_list.tx_ssb[ssb_idx].transmitted = true;
LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx);
}
ssb_idx++;
} }
ssb_idx++; break;
} case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap:
ssb_bitmap = &scc->ssb_PositionsInBurst->choice.mediumBitmap;
ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap);
LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst);
for (uint8_t bit_nb=7; bit_nb<=7; bit_nb--) {
// If SSB is transmitted
if ((ssb_positionsInBurst>>bit_nb) & 0x01) {
ssb_list.nb_tx_ssb++;
ssb_list.tx_ssb[ssb_idx].transmitted = true;
LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx);
}
ssb_idx++;
}
break;
case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap:
ssb_bitmap = &scc->ssb_PositionsInBurst->choice.longBitmap;
ssb_positionsInBurst = BIT_STRING_to_uint64(ssb_bitmap);
LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst);
for (uint8_t bit_nb=63; bit_nb<=63; bit_nb--) {
// If SSB is transmitted
if ((ssb_positionsInBurst>>bit_nb) & 0x01) {
ssb_list.nb_tx_ssb++;
ssb_list.tx_ssb[ssb_idx].transmitted = true;
LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx);
}
ssb_idx++;
}
break;
default:
AssertFatal(false,"ssb_PositionsInBurst not present\n");
break;
} }
} }
...@@ -1214,8 +1292,6 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { ...@@ -1214,8 +1292,6 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) {
// Determine the SSB to RACH mapping ratio // Determine the SSB to RACH mapping ratio
// ======================================= // =======================================
LOG_D(MAC,"SSB per RACH config %u\n", ssb_perRACH_config);
switch (ssb_perRACH_config){ switch (ssb_perRACH_config){
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth:
multiple_ssb_per_ro = false; multiple_ssb_per_ro = false;
...@@ -1300,7 +1376,7 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { ...@@ -1300,7 +1376,7 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) {
// Proceed to the SSB to RO mapping // Proceed to the SSB to RO mapping
// ================================ // ================================
uint8_t association_period_idx; // Association period index within the association pattern uint8_t association_period_idx; // Association period index within the association pattern
uint8_t ssb_idx = MAX_NB_SSB; uint8_t ssb_idx = 0;
uint8_t prach_configuration_period_idx; // PRACH Configuration period index within the association pattern uint8_t prach_configuration_period_idx; // PRACH Configuration period index within the association pattern
prach_conf_period_t *prach_conf_period_p; prach_conf_period_t *prach_conf_period_p;
...@@ -1324,9 +1400,11 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { ...@@ -1324,9 +1400,11 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) {
// -------------------- // --------------------
// -------------------- // --------------------
// WIP-IDCC: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO
ssb_idx = 0;
// Go through the list of PRACH config periods within this association period // Go through the list of PRACH config periods within this association period
for (n_prach_conf=0; n_prach_conf<prach_assoc_pattern.prach_association_period_list[association_period_idx].nb_of_prach_conf_period; n_prach_conf++, prach_configuration_period_idx++) { for (n_prach_conf=0; n_prach_conf<prach_assoc_pattern.prach_association_period_list[association_period_idx].nb_of_prach_conf_period; n_prach_conf++, prach_configuration_period_idx++) {
// Build the association period with its association PRACH Configuration indexes // Build the association period with its association PRACH Configuration indexes
prach_conf_period_p = &prach_assoc_pattern.prach_conf_period_list[prach_configuration_period_idx]; prach_conf_period_p = &prach_assoc_pattern.prach_conf_period_list[prach_configuration_period_idx];
prach_assoc_pattern.prach_association_period_list[association_period_idx].prach_conf_period_list[n_prach_conf] = prach_conf_period_p; prach_assoc_pattern.prach_association_period_list[association_period_idx].prach_conf_period_list[n_prach_conf] = prach_conf_period_p;
...@@ -1339,8 +1417,8 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { ...@@ -1339,8 +1417,8 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) {
prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq]; prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq];
// Go through the list of transmitted SSBs and map the required amount of SSBs to this RO // Go through the list of transmitted SSBs and map the required amount of SSBs to this RO
for (ssb_idx=0; ssb_idx<MAX_NB_SSB; ssb_idx++) { // WIP-IDCC: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO
for (; ssb_idx<MAX_NB_SSB; ssb_idx++) {
// Map only the transmitted ssb_idx // Map only the transmitted ssb_idx
if (true == ssb_list.tx_ssb[ssb_idx].transmitted) { if (true == ssb_list.tx_ssb[ssb_idx].transmitted) {
ro_p->mapped_ssb_idx[ro_p->nb_mapped_ssb] = ssb_idx; ro_p->mapped_ssb_idx[ro_p->nb_mapped_ssb] = ssb_idx;
...@@ -1349,6 +1427,9 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { ...@@ -1349,6 +1427,9 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) {
ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++; ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++;
AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro);
LOG_D(MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq);
LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro);
// If all the required SSBs are mapped to this RO, exit the loop of SSBs // If all the required SSBs are mapped to this RO, exit the loop of SSBs
if (ro_p->nb_mapped_ssb == ssb_rach_ratio) { if (ro_p->nb_mapped_ssb == ssb_rach_ratio) {
ssb_idx++; ssb_idx++;
...@@ -1422,8 +1503,8 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { ...@@ -1422,8 +1503,8 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) {
LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u / total %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro, nb_mapped_ro_in_association_period); LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u / total %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro, nb_mapped_ro_in_association_period);
// Exit the loop if this SSB has been mapped to all the required ROs // 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 a given ssb_idx mapped within an assocation period: this is true if // WIP: Assuming that ssb_rach_ratio equals the maximum nb of times a given ssb_idx is mapped within an association period:
// no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule // 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) { if (nb_mapped_ro_in_association_period == ssb_rach_ratio) {
ro_in_freq++; ro_in_freq++;
break; break;
...@@ -1466,7 +1547,7 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { ...@@ -1466,7 +1547,7 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) {
} }
// Build the SSB to RO mapping upon RRC configuration update // Build the SSB to RO mapping upon RRC configuration update
void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc) { void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired){
// Clear all the lists and maps // Clear all the lists and maps
memset(&prach_assoc_pattern, 0, sizeof(prach_association_pattern_t)); memset(&prach_assoc_pattern, 0, sizeof(prach_association_pattern_t));
...@@ -1474,7 +1555,7 @@ void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc) { ...@@ -1474,7 +1555,7 @@ void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc) {
// Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config // Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config
LOG_D(MAC,"Build RO list\n"); LOG_D(MAC,"Build RO list\n");
build_ro_list(scc); build_ro_list(scc, unpaired);
// Build the list of all the valid/transmitted SSBs according to the config // Build the list of all the valid/transmitted SSBs according to the config
LOG_D(MAC,"Build SSB list\n"); LOG_D(MAC,"Build SSB list\n");
......
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
// PRACH occasion details // PRACH occasion details
typedef struct prach_occasion_info { typedef struct prach_occasion_info {
uint8_t start_symbol; // 0 - 13 (14 symbols in a slot) uint8_t start_symbol; // 0 - 13 (14 symbols in a slot)
uint8_t fdm; // 1, 2, 4 or 8 (possible values of msg1-FDM) 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 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 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 mapped_ssb_idx[MAX_SSB_PER_RO]; // List of mapped SSBs
...@@ -118,7 +118,7 @@ void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss, ...@@ -118,7 +118,7 @@ void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss,
uint16_t *slot_period, uint16_t *slot_period,
uint16_t *offset); uint16_t *offset);
void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc); void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired);
int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx, int frame, int slot, prach_occasion_info_t **prach_occasion_info_pp); int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx, int frame, int slot, prach_occasion_info_t **prach_occasion_info_pp);
int get_nr_prach_info_from_index(uint8_t index, int get_nr_prach_info_from_index(uint8_t index,
......
...@@ -358,7 +358,7 @@ int nr_rrc_mac_config_req_ue( ...@@ -358,7 +358,7 @@ int nr_rrc_mac_config_req_ue(
mac->scg = cell_group_config; mac->scg = cell_group_config;
// Setup the SSB to Rach Occasions mapping according to the config // Setup the SSB to Rach Occasions mapping according to the config
build_ssb_to_ro_map(mac->scc); build_ssb_to_ro_map(mac->scc, mac->phy_config.config_req.cell_config.frame_duplex_type);
/* /*
if(mac_cell_group_configP != NULL){ if(mac_cell_group_configP != NULL){
......
...@@ -237,6 +237,7 @@ andom-access to transmit a BSR along with the C-RNTI control element (see 5.1.4 ...@@ -237,6 +237,7 @@ andom-access to transmit a BSR along with the C-RNTI control element (see 5.1.4
@param nr_tti_tx slot for PRACH transmission @param nr_tti_tx slot for PRACH transmission
@returns indication to generate PRACH to phy */ @returns indication to generate PRACH to phy */
uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
NR_UE_PRACH *prach_vars,
module_id_t mod_id, module_id_t mod_id,
int CC_id, int CC_id,
UE_MODE_t UE_mode, UE_MODE_t UE_mode,
...@@ -254,9 +255,9 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, ...@@ -254,9 +255,9 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
void nr_get_prach_resources(module_id_t mod_id, void nr_get_prach_resources(module_id_t mod_id,
int CC_id, int CC_id,
uint8_t gNB_id, uint8_t gNB_id,
uint8_t t_id,
uint8_t first_Msg3, uint8_t first_Msg3,
NR_PRACH_RESOURCES_t *prach_resources, NR_PRACH_RESOURCES_t *prach_resources,
NR_UE_PRACH *prach_vars,
NR_RACH_ConfigDedicated_t * rach_ConfigDedicated); NR_RACH_ConfigDedicated_t * rach_ConfigDedicated);
void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id); void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id);
......
...@@ -76,9 +76,9 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac); ...@@ -76,9 +76,9 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac);
void nr_get_prach_resources(module_id_t mod_id, void nr_get_prach_resources(module_id_t mod_id,
int CC_id, int CC_id,
uint8_t gNB_id, uint8_t gNB_id,
uint8_t t_id,
uint8_t first_Msg3, uint8_t first_Msg3,
NR_PRACH_RESOURCES_t *prach_resources, NR_PRACH_RESOURCES_t *prach_resources,
NR_UE_PRACH *prach_vars,
NR_RACH_ConfigDedicated_t * rach_ConfigDedicated){ NR_RACH_ConfigDedicated_t * rach_ConfigDedicated){
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
...@@ -88,8 +88,8 @@ void nr_get_prach_resources(module_id_t mod_id, ...@@ -88,8 +88,8 @@ void nr_get_prach_resources(module_id_t mod_id,
// NR_BeamFailureRecoveryConfig_t *beam_failure_recovery_config = &mac->RA_BeamFailureRecoveryConfig; // todo // NR_BeamFailureRecoveryConfig_t *beam_failure_recovery_config = &mac->RA_BeamFailureRecoveryConfig; // todo
int messagePowerOffsetGroupB = 0, messageSizeGroupA, PLThreshold, sizeOfRA_PreamblesGroupA = 0, numberOfRA_Preambles, i, deltaPreamble_Msg3 = 0; int messagePowerOffsetGroupB = 0, messageSizeGroupA, PLThreshold, sizeOfRA_PreamblesGroupA = 0, numberOfRA_Preambles, deltaPreamble_Msg3 = 0;
uint8_t noGroupB = 0, s_id, f_id, ul_carrier_id, prach_ConfigIndex, SFN_nbr, Msg3_size; uint8_t noGroupB = 0, s_id, t_id, f_id, ul_carrier_id, Msg3_size;
AssertFatal(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup != NULL, "[UE %d] FATAL nr_rach_ConfigCommon is NULL !!!\n", mod_id); AssertFatal(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup != NULL, "[UE %d] FATAL nr_rach_ConfigCommon is NULL !!!\n", mod_id);
nr_rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; nr_rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
...@@ -101,6 +101,7 @@ void nr_get_prach_resources(module_id_t mod_id, ...@@ -101,6 +101,7 @@ void nr_get_prach_resources(module_id_t mod_id,
//////////* UE Random Access Resource Selection *////////// //////////* UE Random Access Resource Selection *//////////
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
// todo: // todo:
// - switch initialisation cases // - switch initialisation cases
// -- RA initiated by beam failure recovery operation (subclause 5.17 TS 38.321) // -- RA initiated by beam failure recovery operation (subclause 5.17 TS 38.321)
...@@ -130,12 +131,81 @@ void nr_get_prach_resources(module_id_t mod_id, ...@@ -130,12 +131,81 @@ void nr_get_prach_resources(module_id_t mod_id,
// rsrp_ThresholdSSB = *nr_rach_ConfigCommon->rsrp_ThresholdSSB; // rsrp_ThresholdSSB = *nr_rach_ConfigCommon->rsrp_ThresholdSSB;
// Determine the SSB to RACH mapping ratio
// =======================================
NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present;
boolean_t multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB
uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB
long cb_preambles_per_ssb; // Nb of preambles per SSB
int total_preambles_per_ssb;
int starting_preamble_nb = 0;
uint8_t ssb_nb_in_ro;
switch (ssb_perRACH_config){
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth:
multiple_ssb_per_ro = false;
ssb_rach_ratio = 8;
cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth:
multiple_ssb_per_ro = false;
ssb_rach_ratio = 4;
cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneFourth;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf:
multiple_ssb_per_ro = false;
ssb_rach_ratio = 2;
cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneHalf;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 1;
cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 2;
cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.two;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 4;
cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.four;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 8;
cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.eight;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 16;
cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.sixteen;
break;
default:
AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_config);
break;
}
Msg3_size = mac->RA_Msg3_size; Msg3_size = mac->RA_Msg3_size;
numberOfRA_Preambles = 64; numberOfRA_Preambles = 64;
if(nr_rach_ConfigCommon->totalNumberOfRA_Preambles != NULL) if(nr_rach_ConfigCommon->totalNumberOfRA_Preambles != NULL)
numberOfRA_Preambles = *(nr_rach_ConfigCommon->totalNumberOfRA_Preambles); numberOfRA_Preambles = *(nr_rach_ConfigCommon->totalNumberOfRA_Preambles);
// Compute the proper Preamble selection params according to the selected SSB and the ssb_perRACH_OccasionAndCB_PreamblesPerSSB configuration
if ((true == multiple_ssb_per_ro) &&
(ssb_rach_ratio > 1)) {
total_preambles_per_ssb = numberOfRA_Preambles / ssb_rach_ratio;
ssb_nb_in_ro = prach_vars->prach_pdu.ssb_nb_in_ro;
starting_preamble_nb = total_preambles_per_ssb * ssb_nb_in_ro;
}
else {
total_preambles_per_ssb = numberOfRA_Preambles;
starting_preamble_nb = 0;
}
if (!nr_rach_ConfigCommon->groupBconfigured) { if (!nr_rach_ConfigCommon->groupBconfigured) {
noGroupB = 1; noGroupB = 1;
} else { } else {
...@@ -221,27 +291,27 @@ void nr_get_prach_resources(module_id_t mod_id, ...@@ -221,27 +291,27 @@ void nr_get_prach_resources(module_id_t mod_id,
if (first_Msg3 == 1) { if (first_Msg3 == 1) {
if (noGroupB == 1) { if (noGroupB == 1) {
// use Group A preamble // use Group A preamble
prach_resources->ra_PreambleIndex = (taus()) % numberOfRA_Preambles; prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % cb_preambles_per_ssb);
mac->RA_usedGroupA = 1; mac->RA_usedGroupA = 1;
} else if ((Msg3_size < messageSizeGroupA) && (get_nr_PL(mod_id, CC_id, gNB_id) > PLThreshold)) { } else if ((Msg3_size < messageSizeGroupA) && (get_nr_PL(mod_id, CC_id, gNB_id) > PLThreshold)) {
// Group B is configured and RA preamble Group A is used // Group B is configured and RA preamble Group A is used
// - todo add condition on CCCH_sdu_size for initiation by CCCH // - todo add condition on CCCH_sdu_size for initiation by CCCH
prach_resources->ra_PreambleIndex = (taus()) % sizeOfRA_PreamblesGroupA; prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % sizeOfRA_PreamblesGroupA);
mac->RA_usedGroupA = 1; mac->RA_usedGroupA = 1;
} else { } else {
// Group B preamble is configured and used // Group B preamble is configured and used
// the first sizeOfRA_PreamblesGroupA RA preambles belong to RA Preambles Group A // the first sizeOfRA_PreamblesGroupA RA preambles belong to RA Preambles Group A
// the remaining belong to RA Preambles Group B // the remaining belong to RA Preambles Group B
prach_resources->ra_PreambleIndex = sizeOfRA_PreamblesGroupA + (taus()) % (numberOfRA_Preambles - sizeOfRA_PreamblesGroupA); prach_resources->ra_PreambleIndex = starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA));
mac->RA_usedGroupA = 0; mac->RA_usedGroupA = 0;
} }
} else { // Msg3 is being retransmitted } else { // Msg3 is being retransmitted
if (mac->RA_usedGroupA == 1 && noGroupB == 1) { if (mac->RA_usedGroupA == 1 && noGroupB == 1) {
prach_resources->ra_PreambleIndex = (taus()) % numberOfRA_Preambles; prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % cb_preambles_per_ssb);
} else if (mac->RA_usedGroupA == 1 && noGroupB == 0){ } else if (mac->RA_usedGroupA == 1 && noGroupB == 0){
prach_resources->ra_PreambleIndex = (taus()) % sizeOfRA_PreamblesGroupA; prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % sizeOfRA_PreamblesGroupA);
} else { } else {
prach_resources->ra_PreambleIndex = sizeOfRA_PreamblesGroupA + (taus()) % (numberOfRA_Preambles - sizeOfRA_PreamblesGroupA); prach_resources->ra_PreambleIndex = starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA));
} }
} }
LOG_D(MAC, "[RAPROC] - Selected RA preamble index %d for contention-based random access procedure... \n", prach_resources->ra_PreambleIndex); LOG_D(MAC, "[RAPROC] - Selected RA preamble index %d for contention-based random access procedure... \n", prach_resources->ra_PreambleIndex);
...@@ -269,27 +339,16 @@ void nr_get_prach_resources(module_id_t mod_id, ...@@ -269,27 +339,16 @@ void nr_get_prach_resources(module_id_t mod_id,
// 1) this does not apply to contention-free RA Preamble for beam failure recovery request // 1) this does not apply to contention-free RA Preamble for beam failure recovery request
// 2) getting star_symb, SFN_nbr from table 6.3.3.2-3 (TDD and FR1 scenario) // 2) getting star_symb, SFN_nbr from table 6.3.3.2-3 (TDD and FR1 scenario)
prach_ConfigIndex = rach_ConfigGeneric->prach_ConfigurationIndex;
// ra_RNTI computation // ra_RNTI computation
// - todo: this is for TDD FR1 only
// - ul_carrier_id: UL carrier used for RA preamble transmission, hardcoded for NUL carrier // - ul_carrier_id: UL carrier used for RA preamble transmission, hardcoded for NUL carrier
// - f_id: index of the PRACH occasion in the frequency domain // - f_id: index of the PRACH occasion in the frequency domain
// - s_id is starting symbol of the PRACH occasion [0...14] // - s_id is starting symbol of the PRACH occasion [0...14]
// - t_id is the first slot of the PRACH occasion in a system frame [0...80] // - t_id is the first slot of the PRACH occasion in a system frame [0...80]
ul_carrier_id = 0; // NUL ul_carrier_id = 0; // NUL
f_id = rach_ConfigGeneric->msg1_FrequencyStart; f_id = prach_vars->prach_pdu.num_ra;
SFN_nbr = table_6_3_3_2_3_prachConfig_Index[prach_ConfigIndex][4]; t_id = prach_vars->prach_pdu.prach_slot;
s_id = table_6_3_3_2_3_prachConfig_Index[prach_ConfigIndex][5]; s_id = prach_vars->prach_pdu.prach_start_symbol;
// Pick the first slot of the PRACH occasion in a system frame
for (i = 0; i < 10; i++){
if (((SFN_nbr & (1 << i)) >> i) == 1){
t_id = 2*i;
break;
}
}
prach_resources->ra_RNTI = 1 + s_id + 14 * t_id + 1120 * f_id + 8960 * ul_carrier_id; prach_resources->ra_RNTI = 1 + s_id + 14 * t_id + 1120 * f_id + 8960 * ul_carrier_id;
mac->ra_rnti = prach_resources->ra_RNTI; mac->ra_rnti = prach_resources->ra_RNTI;
...@@ -336,6 +395,7 @@ void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint ...@@ -336,6 +395,7 @@ void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint
// - add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator) // - add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator)
uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
NR_UE_PRACH *prach_vars,
module_id_t mod_id, module_id_t mod_id,
int CC_id, int CC_id,
UE_MODE_t UE_mode, UE_MODE_t UE_mode,
...@@ -450,7 +510,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, ...@@ -450,7 +510,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
// Fill in preamble and PRACH resources // Fill in preamble and PRACH resources
if (mac->generate_nr_prach) if (mac->generate_nr_prach)
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 1, prach_resources, rach_ConfigDedicated); nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_vars, rach_ConfigDedicated);
offset = nr_generate_ulsch_pdu((uint8_t *) mac_sdus, // sdus buffer offset = nr_generate_ulsch_pdu((uint8_t *) mac_sdus, // sdus buffer
(uint8_t *) payload, // UL MAC pdu pointer (uint8_t *) payload, // UL MAC pdu pointer
...@@ -573,7 +633,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, ...@@ -573,7 +633,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
// Fill in preamble and PRACH resources // Fill in preamble and PRACH resources
if (mac->generate_nr_prach) if (mac->generate_nr_prach)
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated); nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_vars, rach_ConfigDedicated);
} else { } else {
...@@ -587,7 +647,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, ...@@ -587,7 +647,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
// Fill in preamble and PRACH resources // Fill in preamble and PRACH resources
if (mac->generate_nr_prach) if (mac->generate_nr_prach)
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated); nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_vars, rach_ConfigDedicated);
} }
} }
......
...@@ -1041,6 +1041,7 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s ...@@ -1041,6 +1041,7 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s
prach_config_pdu->phys_cell_id = *scc->physCellId; prach_config_pdu->phys_cell_id = *scc->physCellId;
prach_config_pdu->num_prach_ocas = 1; prach_config_pdu->num_prach_ocas = 1;
prach_config_pdu->prach_slot = prach_occasion_info_p->slot;
prach_config_pdu->prach_start_symbol = prach_occasion_info_p->start_symbol; prach_config_pdu->prach_start_symbol = prach_occasion_info_p->start_symbol;
prach_config_pdu->num_ra = prach_occasion_info_p->fdm; prach_config_pdu->num_ra = prach_occasion_info_p->fdm;
...@@ -1052,6 +1053,13 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s ...@@ -1052,6 +1053,13 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s
// prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[n].k1; // prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[n].k1;
prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].k1; prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].k1;
// Search which SSB is mapped in the RO (among all the SSBs mapped to this RO)
for (prach_config_pdu->ssb_nb_in_ro=0; prach_config_pdu->ssb_nb_in_ro<prach_occasion_info_p->nb_mapped_ssb; prach_config_pdu->ssb_nb_in_ro++) {
if (prach_occasion_info_p->mapped_ssb_idx[prach_config_pdu->ssb_nb_in_ro] == selected_gnb_ssb_idx)
break;
}
AssertFatal(prach_config_pdu->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) { if (format1 != 0xff) {
switch(format0) { // dual PRACH format switch(format0) { // dual PRACH format
case 0xa1: case 0xa1:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment