diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container
index 37e6a0554b..3ad376f3da 100644
--- a/ci-scripts/Jenkinsfile-GitLab-Container
+++ b/ci-scripts/Jenkinsfile-GitLab-Container
@@ -65,8 +65,8 @@ pipeline {
message += " - ~BUILD-ONLY (execute only build stages)\n"
message += " - ~4G-LTE (perform 4G tests)\n"
message += " - ~5G-NR (perform 5G tests)\n"
- message += " - ~CI (perform both 4G and 5G tests)\n\n"
- message += " - ~nrUE (perform only 5G-UE related tests including physims excluding LDPC tests)\n"
+ message += " - ~CI (perform both 4G and 5G tests)\n"
+ message += " - ~nrUE (perform only 5G-UE related tests including physims excluding LDPC tests)\n\n"
message += "Not performing CI due to lack of labels"
addGitLabMRComment comment: message
error('Not performing CI due to lack of labels')
diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py
index 7293e252a1..bfa315b28e 100644
--- a/ci-scripts/cls_cluster.py
+++ b/ci-scripts/cls_cluster.py
@@ -72,8 +72,8 @@ def OC_deploy_CN(cmd, ocUserName, ocPassword, ocNamespace, path):
succeeded = OC_login(cmd, ocUserName, ocPassword, ocNamespace)
if not succeeded:
return False, CONST.OC_LOGIN_FAIL
- cmd.run('helm uninstall oai5gcn --wait --timeout 60s')
- ret = cmd.run(f'helm install --wait --timeout 120s oai5gcn {path}/ci-scripts/charts/oai-5g-basic/.')
+ cmd.run(f'helm list -aq -n {ocNamespace} | xargs -r helm uninstall -n {ocNamespace} --wait')
+ ret = cmd.run(f'helm install --wait oai5gcn {path}/ci-scripts/charts/oai-5g-basic/.')
if ret.returncode != 0:
logging.error('OC OAI CN5G: Deployment failed')
OC_logout(cmd)
@@ -100,10 +100,10 @@ def OC_undeploy_CN(cmd, ocUserName, ocPassword, ocNamespace, path):
cmd.run(f'oc logs -f {podName} {ci} &> {path}/logs/{ii}.log &')
cmd.run(f'cd {path}/logs && zip -r -qq test_logs_CN.zip *.log')
cmd.copyin(f'{path}/logs/test_logs_CN.zip','test_logs_CN.zip')
- ret = cmd.run('helm uninstall --wait --timeout 60s oai5gcn')
+ ret = cmd.run(f'helm list -aq -n {ocNamespace} | xargs -r helm uninstall -n {ocNamespace} --wait')
if ret.returncode != 0:
logging.error('OC OAI CN5G: Undeployment failed')
- cmd.run('helm uninstall --wait --timeout 60s oai5gcn')
+ cmd.run(f'helm list -aq -n {ocNamespace} | xargs -r helm uninstall -n {ocNamespace} --wait')
OC_logout(cmd)
return False, CONST.OC_PROJECT_FAIL
report = cmd.run('oc get pods')
@@ -330,7 +330,7 @@ class Cluster:
self._recreate_bc('ran-base', baseTag, 'openshift/ran-base-bc.yaml')
ranbase_job = self._start_build('ran-base')
attemptedImages += ['ran-base']
- status = ranbase_job is not None and self._wait_build_end([ranbase_job], 800)
+ status = ranbase_job is not None and self._wait_build_end([ranbase_job], 1000)
if not status: logging.error('failure during build of ran-base')
self.cmd.run(f'oc logs {ranbase_job} &> cmake_targets/log/ran-base.log') # cannot use cmd.run because of redirect
# recover logs by mounting image
@@ -392,7 +392,7 @@ class Cluster:
gnb_aw2s_job = self._start_build('oai-gnb-aw2s')
attemptedImages += ['oai-gnb-aw2s']
- wait = enb_job is not None and gnb_job is not None and gnb_aw2s_job is not None and self._wait_build_end([enb_job, gnb_job, gnb_aw2s_job], 600)
+ wait = enb_job is not None and gnb_job is not None and gnb_aw2s_job is not None and self._wait_build_end([enb_job, gnb_job, gnb_aw2s_job], 800)
if not wait: logging.error('error during build of eNB/gNB')
status = status and wait
# recover logs
@@ -421,7 +421,7 @@ class Cluster:
nrue_job = self._start_build('oai-nr-ue')
attemptedImages += ['oai-nr-ue']
- wait = nr_cuup_job is not None and lteue_job is not None and nrue_job is not None and self._wait_build_end([nr_cuup_job, lteue_job, nrue_job], 600)
+ wait = nr_cuup_job is not None and lteue_job is not None and nrue_job is not None and self._wait_build_end([nr_cuup_job, lteue_job, nrue_job], 800)
if not wait: logging.error('error during build of nr-cuup/lteUE/nrUE')
status = status and wait
# recover logs
diff --git a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml
index 5c2a069122..fe80891678 100644
--- a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml
+++ b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml
@@ -34,6 +34,9 @@
020002
030001
030002
+ 040001
+ 000004
+ 020002
100001
222222
@@ -76,6 +79,12 @@
cacofonix
+
+ IdleSleep
+ Sleep
+ 5
+
+
Ping
Ping ext-dn from NR-UE
@@ -118,6 +127,14 @@
90
+
+ Custom_Command
+ Force Msg3 C-RNTI RA
+ cacofonix
+ echo ciUE force_crnti_ra | nc 192.168.71.150 8091
+ yes
+
+
Undeploy_Object
true
diff --git a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml
index ae74649a83..2fd9a3e1fb 100644
--- a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml
+++ b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml
@@ -109,7 +109,10 @@ services:
- NET_ADMIN # for interface bringup
- NET_RAW # for ping
environment:
- USE_ADDITIONAL_OPTIONS: --rfsim -r 24 --ssb 24 --numerology 1 -C 3604800000 --uicc0.imsi 208990100001100 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time
+ USE_ADDITIONAL_OPTIONS: --rfsim -r 24 --ssb 24 --numerology 1 -C 3604800000 --uicc0.imsi 208990100001100
+ --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time
+ --telnetsrv --telnetsrv.shrmod ciUE --telnetsrv.listenaddr 192.168.71.150 --telnetsrv.listenport 8091
+ ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0
depends_on:
- oai-gnb
networks:
diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c
index 1d1e683dce..58c18bfd36 100644
--- a/common/utils/nr/nr_common.c
+++ b/common/utils/nr/nr_common.c
@@ -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;
}
diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h
index ce71500eb0..1dc6a1169d 100644
--- a/common/utils/nr/nr_common.h
+++ b/common/utils/nr/nr_common.h
@@ -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
diff --git a/common/utils/telnetsrv/telnetsrv_ciUE.c b/common/utils/telnetsrv/telnetsrv_ciUE.c
index dd95f8009c..721cb0e5cd 100644
--- a/common/utils/telnetsrv/telnetsrv_ciUE.c
+++ b/common/utils/telnetsrv/telnetsrv_ciUE.c
@@ -94,11 +94,20 @@ int force_RRC_IDLE(char *buf, int debug, telnet_printfunc_t prnt)
return 0;
}
+/** @brief Trigger RA with Msg3 C-RNTI */
+int force_crnti_ra(char *buf, int debug, telnet_printfunc_t prnt)
+{
+ NR_UE_MAC_INST_t *mac = get_mac_inst(0);
+ trigger_MAC_UE_RA(mac, NULL);
+ return 0;
+}
+
/* Telnet shell command definitions */
static telnetshell_cmddef_t cicmds[] = {
{"sync_state", "[UE_ID(int,opt)]", get_sync_state},
{"force_rlf", "", force_rlf},
{"force_RRC_IDLE", "", force_RRC_IDLE},
+ {"force_crnti_ra", "", force_crnti_ra},
{"", "", NULL},
};
diff --git a/executables/nr-ue.c b/executables/nr-ue.c
index cc72eed263..41032a3d42 100644
--- a/executables/nr-ue.c
+++ b/executables/nr-ue.c
@@ -147,6 +147,24 @@ static void *nrL1_UE_stats_thread(void *param)
return NULL;
}
+static int determine_N_TA_offset(PHY_VARS_NR_UE *ue) {
+ if (ue->sl_mode == 2)
+ return 0;
+ else {
+ int N_TA_offset = ue->nrUE_config.cell_config.N_TA_offset;
+ if (N_TA_offset == -1) {
+ return set_default_nta_offset(ue->frame_parms.freq_range, ue->frame_parms.samples_per_subframe);
+ } else {
+ // Return N_TA_offet in samples, as described in 38.211 4.1 and 4.3.1
+ // T_c[s] = 1/(Ξf_max x N_f) = 1 / (480 * 1000 * 4096)
+ // N_TA_offset[s] = N_TA_offset x T_c
+ // N_TA_offset[samples] = samples_per_second x N_TA_offset[s]
+ // N_TA_offset[samples] = N_TA_offset x samples_per_subframe x 1000 x T_c
+ return (N_TA_offset * ue->frame_parms.samples_per_subframe) / (4096 * 480);
+ }
+ }
+}
+
void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id)
{
int nb_connected_gNB = 1;
@@ -165,8 +183,8 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id)
// intialize transport
init_nr_ue_transport(ue);
- // init N_TA offset
- init_N_TA_offset(ue);
+ ue->ta_frame = -1;
+ ue->ta_slot = -1;
}
void init_nrUE_standalone_thread(int ue_idx)
@@ -519,7 +537,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 +668,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;
@@ -867,6 +888,7 @@ void *UE_thread(void *arg)
initNotifiedFIFO_nothreadSafe(&freeBlocks);
int timing_advance = UE->timing_advance;
+ UE->N_TA_offset = determine_N_TA_offset(UE);
NR_UE_MAC_INST_t *mac = get_mac_inst(UE->Mod_id);
bool syncRunning = false;
@@ -1095,9 +1117,16 @@ void *UE_thread(void *arg)
// but use current UE->timing_advance value to compute writeBlockSize
int writeBlockSize = fp->get_samples_per_slot((slot_nr + duration_rx_to_tx) % nb_slot_frame, fp) - iq_shift_to_apply;
- if (UE->timing_advance != timing_advance) {
- writeBlockSize -= UE->timing_advance - timing_advance;
- timing_advance = UE->timing_advance;
+ int new_timing_advance = UE->timing_advance;
+ if (new_timing_advance != timing_advance) {
+ writeBlockSize -= new_timing_advance- timing_advance;
+ timing_advance = new_timing_advance;
+ }
+ int new_N_TA_offset = determine_N_TA_offset(UE);
+ if (new_N_TA_offset != UE->N_TA_offset) {
+ LOG_I(PHY, "N_TA_offset changed from %d to %d\n", UE->N_TA_offset, new_N_TA_offset);
+ writeBlockSize -= new_N_TA_offset - UE->N_TA_offset;
+ UE->N_TA_offset = new_N_TA_offset;
}
if (curMsg.proc.nr_slot_tx == 0)
diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c
index d5f4a528ff..2ba05ae200 100644
--- a/executables/nr-uesoftmodem.c
+++ b/executables/nr-uesoftmodem.c
@@ -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();
diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h
index 881d7fad8e..a5d6087856 100644
--- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h
+++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h
@@ -551,7 +551,6 @@ typedef struct {
int ta_frame;
int ta_slot;
int ta_command;
- int ta_offset;
bool is_rar;
} fapi_nr_ta_command_pdu;
@@ -616,7 +615,7 @@ typedef struct
{
uint8_t phy_cell_id;//Physical Cell ID, π_{πΌπ·}^{ππππ} [38.211, sec 7.4.2.1] Value: 0 ->1007
uint8_t frame_duplex_type;//Frame duplex type Value: 0 = FDD 1 = TDD
-
+ uint32_t N_TA_offset;
} fapi_nr_cell_config_t;
typedef struct
diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c
index 9b36197e45..c7bb47c581 100644
--- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c
+++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c
@@ -218,7 +218,7 @@ static void nr_process_decode_segment(void *arg)
int decodeIterations =
LDPCdecoder(p_decoderParms, 0, 0, 0, l, llrProcBuf, p_procTime, rdata->abort_decode);
- if (decodeIterations <= p_decoderParms->numMaxIter) {
+ if (decodeIterations < p_decoderParms->numMaxIter) {
memcpy(rdata->c, llrProcBuf, K >> 3);
*rdata->decodeSuccess = true;
} else {
diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c
index 7960215ab7..b23db3781d 100644
--- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c
+++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c
@@ -277,8 +277,8 @@ int decoder_xdma(nrLDPC_TB_decoding_parameters_t *TB_params, int frame_rx, int s
for (uint32_t job = 0; job < num_threads_prepare; job++) {
args_fpga_decode_prepare_t *args = &arr[job];
- if (args->no_iteration_ldpc > TB_params->max_ldpc_iterations)
- no_iteration_ldpc = TB_params->max_ldpc_iterations + 1;
+ if (args->no_iteration_ldpc >= TB_params->max_ldpc_iterations)
+ no_iteration_ldpc = TB_params->max_ldpc_iterations;
}
// launch decode with FPGA
@@ -306,12 +306,12 @@ int decoder_xdma(nrLDPC_TB_decoding_parameters_t *TB_params, int frame_rx, int s
#ifdef DEBUG_CRC
LOG_I(PHY, "segment %d CRC NOK\n", r);
#endif
- no_iteration_ldpc = TB_params->max_ldpc_iterations + 1;
+ no_iteration_ldpc = TB_params->max_ldpc_iterations;
}
for (int i = 0; i < out_CBoffset; i++) {
segment_params->c[i] = multi_outdata[i + r * out_CBoffset];
}
- segment_params->decodeSuccess = (no_iteration_ldpc <= TB_params->max_ldpc_iterations);
+ segment_params->decodeSuccess = (no_iteration_ldpc < TB_params->max_ldpc_iterations);
if (segment_params->decodeSuccess) {
*TB_params->processedSegments = *TB_params->processedSegments + 1;
}
@@ -396,7 +396,7 @@ void nr_ulsch_FPGA_decoding_prepare_blocks(void *args)
== -1) {
stop_meas(&segment_params->ts_rate_unmatch);
LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n");
- no_iteration_ldpc = max_ldpc_iterations + 1;
+ no_iteration_ldpc = max_ldpc_iterations;
arguments->no_iteration_ldpc = no_iteration_ldpc;
return;
} else {
diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
index fcee71c151..e2ed7fce10 100644
--- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
+++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
@@ -187,7 +187,7 @@ int32_t LDPCdecoder(t_nrLDPC_dec_params* p_decParams,
// Launch LDPC decoder core for one segment
int numIter = nrLDPC_decoder_core(p_llr, p_out, numLLR, p_lut, p_decParams, p_profiler, ab);
- if (numIter > p_decParams->numMaxIter) {
+ if (numIter >= p_decParams->numMaxIter) {
LOG_D(PHY, "set abort: %d, %d\n", numIter, p_decParams->numMaxIter);
set_abort(ab, true);
}
@@ -549,13 +549,11 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
// estimated after only one iteration
// First iteration finished
- uint32_t numIter = 1;
+ uint32_t numIter = 0;
int32_t pcRes = 1; // pcRes is 0 if the ldpc decoder is succesful
- while ((numIter <= numMaxIter) && (pcRes != 0)) {
- // Increase iteration counter
- numIter++;
+ while ((numIter < numMaxIter) && (pcRes != 0)) {
if (check_abort(ab)) {
- numIter = numMaxIter + 2;
+ numIter = numMaxIter;
break;
}
// CN processing
@@ -847,7 +845,7 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
pcRes = nrLDPC_cnProcPc_BG2(p_lut, cnProcBuf, cnProcBufRes, Z);
NR_LDPC_PROFILER_DETAIL(stop_meas(&p_profiler->cnProcPc));
} else {
- if (numIter > 2) {
+ if (numIter > 0) {
int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0};
int8_t* p_llrOut = outMode == nrLDPC_outMode_LLRINT8 ? p_out : llrOut;
nrLDPC_llrRes2llrOut(p_lut, p_llrOut, llrRes, Z, BG);
@@ -861,6 +859,8 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
}
}
}
+ // Increase iteration counter
+ numIter++;
}
if (!p_decParams->check_crc) {
int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0};
diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c
index 019e386fd0..19816e215f 100644
--- a/openair1/PHY/INIT/nr_init_ue.c
+++ b/openair1/PHY/INIT/nr_init_ue.c
@@ -492,24 +492,6 @@ void clean_UE_harq(PHY_VARS_NR_UE *UE)
}
}
-
-void init_N_TA_offset(PHY_VARS_NR_UE *ue)
-{
- NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
-
- // No timing offset for Sidelink, refer to 3GPP 38.211 Section 8.5
- if (ue->sl_mode == 2)
- ue->N_TA_offset = 0;
- else
- ue->N_TA_offset = set_default_nta_offset(fp->freq_range, fp->samples_per_subframe);
- ue->ta_frame = -1;
- ue->ta_slot = -1;
-
- LOG_I(PHY,
- "UE %d Setting N_TA_offset to %d samples (UL Freq %lu, N_RB %d, mu %d)\n",
- ue->Mod_id, ue->N_TA_offset, fp->ul_CarrierFreq, fp->N_RB_DL, fp->numerology_index);
-}
-
void phy_init_nr_top(PHY_VARS_NR_UE *ue) {
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
init_delay_table(frame_parms->ofdm_symbol_size, MAX_DELAY_COMP, NR_MAX_OFDM_SYMBOL_SIZE, frame_parms->delay_table);
diff --git a/openair1/PHY/INIT/nr_phy_init.h b/openair1/PHY/INIT/nr_phy_init.h
index d2c65e939f..1b1a0fa1b0 100644
--- a/openair1/PHY/INIT/nr_phy_init.h
+++ b/openair1/PHY/INIT/nr_phy_init.h
@@ -36,7 +36,6 @@ int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp,
int init_nr_ue_signal(PHY_VARS_NR_UE *ue,int nb_connected_eNB);
void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB);
void init_nr_ue_transport(PHY_VARS_NR_UE *ue);
-void init_N_TA_offset(PHY_VARS_NR_UE *ue);
void nr_dump_frame_parms(NR_DL_FRAME_PARMS *frame_parms);
void phy_init_nr_gNB(PHY_VARS_gNB *gNB);
int init_codebook_gNB(PHY_VARS_gNB *gNB);
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
index a3138f5d7f..e6b4503e1b 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
@@ -59,14 +59,14 @@ void nr_dlsch_unscrambling(int16_t *llr, uint32_t size, uint8_t q, uint32_t Nid,
/*! \brief Prepare necessary parameters for nrLDPC_coding_interface
*/
-uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
- const UE_nr_rxtx_proc_t *proc,
- NR_UE_DLSCH_t *dlsch,
- int16_t **dlsch_llr,
- uint8_t **b,
- int *G,
- int nb_dlsch,
- uint8_t *DLSCH_ids)
+void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
+ const UE_nr_rxtx_proc_t *proc,
+ NR_UE_DLSCH_t *dlsch,
+ int16_t **dlsch_llr,
+ uint8_t **b,
+ int *G,
+ int nb_dlsch,
+ uint8_t *DLSCH_ids)
{
nrLDPC_TB_decoding_parameters_t TBs[nb_dlsch];
memset(TBs, 0, sizeof(TBs));
@@ -100,7 +100,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
if (!harq_process) {
LOG_E(PHY, "dlsch_decoding_slot.c: NULL harq_process pointer\n");
- return dlsch[DLSCH_id].max_ldpc_iterations + 1;
+ return;
}
nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pdsch_id];
@@ -164,7 +164,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
if (harq_process->C > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * TB_parameters->nb_layers) {
LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, TB_parameters->A);
- return dlsch[DLSCH_id].max_ldpc_iterations + 1;
+ return;
}
if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD) && (!slot_parameters.frame % 100))
@@ -242,7 +242,8 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
int ret_decoder = phy_vars_ue->nrLDPC_coding_interface.nrLDPC_coding_decoder(&slot_parameters);
if (ret_decoder != 0) {
- return dlsch->max_ldpc_iterations + 1;
+ LOG_E(PHY, "nrLDPC_coding_decoder returned an error: %d\n", ret_decoder);
+ return;
}
// post decode
@@ -316,11 +317,11 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
if (harq_process->decodeResult) {
LOG_D(PHY, "DLSCH received ok \n");
harq_process->status = SCH_IDLE;
- dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations;
+ dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations - 1;
} else {
LOG_D(PHY, "DLSCH received nok \n");
kpiStructure.nb_nack++;
- dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations + 1;
+ dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations;
UEdumpScopeData(phy_vars_ue, proc->nr_slot_rx, proc->frame_rx, "DLSCH_NACK");
}
@@ -355,5 +356,4 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
}
- return dlsch[0].last_iteration_cnt;
}
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
index 0ca616ba34..bb1a6c03df 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
@@ -81,14 +81,14 @@ void nr_conjch0_mult_ch1(int *ch0,
@param[in] DLSCH_ids array of active downlink shared channels
@returns 0 on success, 1 on unsuccessful decoding
*/
-uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
- const UE_nr_rxtx_proc_t *proc,
- NR_UE_DLSCH_t *dlsch,
- short **dlsch_llr,
- uint8_t **b,
- int *G,
- int nb_dlsch,
- uint8_t *DLSCH_ids);
+void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
+ const UE_nr_rxtx_proc_t *proc,
+ NR_UE_DLSCH_t *dlsch,
+ short **dlsch_llr,
+ uint8_t **b,
+ int *G,
+ int nb_dlsch,
+ uint8_t *DLSCH_ids);
/** \brief This is the alternative top-level entry point for ULSCH encoding in UE.
It handles all the HARQ processes in only one call. The routine first
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
index 419988a961..07917b9075 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
@@ -147,7 +147,7 @@ typedef struct {
/// Maximum number of LDPC iterations
uint8_t max_ldpc_iterations;
/// number of iterations used in last turbo decoding
- uint8_t last_iteration_cnt;
+ int8_t last_iteration_cnt;
/// bit mask of PT-RS ofdm symbol indicies
uint16_t ptrs_symbols;
// PTRS symbol index, to be updated every PTRS symbol within a slot.
diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h
index eb0a1acc0e..47d41db44b 100644
--- a/openair1/PHY/defs_gNB.h
+++ b/openair1/PHY/defs_gNB.h
@@ -239,7 +239,7 @@ typedef struct {
/// Maximum number of LDPC iterations
uint8_t max_ldpc_iterations;
/// number of iterations used in last LDPC decoding
- uint8_t last_iteration_cnt;
+ int8_t last_iteration_cnt;
/// Status Flag indicating for this ULSCH
bool active;
/// Flag to indicate that the UL configuration has been handled. Used to remove a stale ULSCH when frame wraps around
diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
index 1484d44ddf..4f1f8ff010 100644
--- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c
+++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
@@ -424,7 +424,7 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, boo
LOG_D(PHY, "ULSCH received ok \n");
ulsch->active = false;
ulsch_harq->round = 0;
- ulsch->last_iteration_cnt = ulsch->max_ldpc_iterations; // Setting to max_ldpc_iterations is sufficient given that this variable is only used for checking for failure
+ ulsch->last_iteration_cnt = ulsch->max_ldpc_iterations - 1; // Setting to max_ldpc_iterations - 1 is sufficient given that this variable is only used for checking for failure
} else {
LOG_D(PHY,
"[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, ndi %d, status %d, round %d, RV %d, prb_start %d, prb_size %d, "
@@ -444,7 +444,7 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, boo
gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_NACK");
ulsch->handled = 1;
LOG_D(PHY, "ULSCH %d in error\n",ULSCH_id);
- ulsch->last_iteration_cnt = ulsch->max_ldpc_iterations + 1; // Setting to max_ldpc_iterations + 1 is sufficient given that this variable is only used for checking for failure
+ ulsch->last_iteration_cnt = ulsch->max_ldpc_iterations; // Setting to max_ldpc_iterations is sufficient given that this variable is only used for checking for failure
}
}
diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
index fbfc9d8389..ba4ad4a0f7 100644
--- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
+++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
@@ -419,15 +419,6 @@ static void configure_ta_command(PHY_VARS_NR_UE *ue, fapi_nr_ta_command_pdu *ta_
LOG_D(PHY,
"TA command received in %d.%d Starting UL time alignment procedures. TA update will be applied at frame %d slot %d\n",
ta_command_pdu->ta_frame, ta_command_pdu->ta_slot, ue->ta_frame, ue->ta_slot);
-
- if (ta_command_pdu->ta_offset != -1) {
- // ta_offset_samples : ta_offset = samples_per_subframe : (Ξf_max x N_f / 1000)
- // As described in Section 4.3.1 in 38.211
- int ta_offset_samples = (ta_command_pdu->ta_offset * samples_per_subframe) / (4096 * 480);
- ue->N_TA_offset = ta_offset_samples;
- LOG_D(PHY, "Received N_TA offset %d from upper layers. Corresponds to %d samples.\n",
- ta_command_pdu->ta_offset, ta_offset_samples);
- }
}
static void nr_ue_scheduled_response_dl(NR_UE_MAC_INST_t *mac,
diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
index b57bf4eff3..283673a6df 100644
--- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
+++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
@@ -686,20 +686,18 @@ static uint32_t compute_csi_rm_unav_res(fapi_nr_dl_config_dlsch_pdu_rel15_t *dls
/*! \brief Process the whole DLSCH slot
*/
-static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
+static void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
NR_UE_DLSCH_t dlsch[2],
int16_t *llr[2]) {
if (dlsch[0].active == false) {
LOG_E(PHY, "DLSCH should be active when calling this function\n");
- return true;
+ return;
}
- bool dec = false;
int harq_pid = dlsch[0].dlsch_config.harq_process_nbr;
int frame_rx = proc->frame_rx;
int nr_slot_rx = proc->nr_slot_rx;
- uint32_t ret = UINT32_MAX;
NR_DL_UE_HARQ_t *dl_harq0 = &ue->dl_harq_processes[0][harq_pid];
NR_DL_UE_HARQ_t *dl_harq1 = &ue->dl_harq_processes[1][harq_pid];
uint16_t dmrs_len = get_num_dmrs(dlsch[0].dlsch_config.dlDmrsSymbPos);
@@ -732,7 +730,7 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
const int ack_nack_slot_and_frame =
(proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) + proc->frame_rx * ue->frame_parms.slots_per_frame;
dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS]);
- return false;
+ return;
}
int G[2];
@@ -765,11 +763,9 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
}
start_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS);
- ret = nr_dlsch_decoding(ue, proc, dlsch, llr, p_b, G, nb_dlsch, DLSCH_ids);
+ nr_dlsch_decoding(ue, proc, dlsch, llr, p_b, G, nb_dlsch, DLSCH_ids);
stop_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS);
- if (ret < ue->max_ldpc_iterations + 1) dec = true;
-
int ind_type = -1;
switch (dlsch[0].rnti_type) {
case TYPE_RA_RNTI_:
@@ -829,7 +825,6 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
else if (ue->phy_sim_dlsch_b && is_cw1_active == ACTIVE)
memcpy(ue->phy_sim_dlsch_b, p_b[1], dlsch_bytes);
- return dec;
}
static bool is_ssb_index_transmitted(const PHY_VARS_NR_UE *ue, const int index)
diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c
index de5c598015..977970c9f7 100644
--- a/openair1/SIMULATION/NR_PHY/dlschsim.c
+++ b/openair1/SIMULATION/NR_PHY/dlschsim.c
@@ -123,7 +123,6 @@ int main(int argc, char **argv)
NR_DL_FRAME_PARMS *frame_parms;
double sigma;
unsigned char qbits = 8;
- int ret;
int loglvl = OAILOG_WARNING;
uint8_t dlsch_threads = 0;
float target_error_rate = 0.01;
@@ -577,18 +576,18 @@ int main(int argc, char **argv)
short *p_channel_output_fixed = channel_output_fixed;
uint8_t *p_b = b;
int available_bits_array[1] = { available_bits };
- ret = nr_dlsch_decoding(UE,
- &proc,
- dlsch0_ue,
- &p_channel_output_fixed,
- &p_b,
- available_bits_array,
- 1,
- DLSCH_ids);
+ nr_dlsch_decoding(UE,
+ &proc,
+ dlsch0_ue,
+ &p_channel_output_fixed,
+ &p_b,
+ available_bits_array,
+ 1,
+ DLSCH_ids);
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING0, VCD_FUNCTION_OUT);
- if (ret > dlsch0_ue->max_ldpc_iterations)
+ if (dlsch0_ue->last_iteration_cnt > dlsch0_ue->max_ldpc_iterations)
n_errors++;
//count errors
diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c
index 9014cd33ef..76c8881945 100644
--- a/openair1/SIMULATION/NR_PHY/dlsim.c
+++ b/openair1/SIMULATION/NR_PHY/dlsim.c
@@ -1163,7 +1163,7 @@ printf("%d\n", slot);
//---------------------- count errors ----------------------
//----------------------------------------------------------
- if (dlsch0->last_iteration_cnt >= dlsch0->max_ldpc_iterations+1)
+ if (dlsch0->last_iteration_cnt >= dlsch0->max_ldpc_iterations)
n_errors[round]++;
int16_t *UE_llr = (int16_t*)UE->phy_sim_pdsch_llr;
diff --git a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c
index d55322156b..973aa60930 100644
--- a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c
+++ b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c
@@ -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) {}
diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c
index ce00f6ae9e..eb3537650b 100644
--- a/openair1/SIMULATION/NR_PHY/prachsim.c
+++ b/openair1/SIMULATION/NR_PHY/prachsim.c
@@ -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) {
diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c
index b45ca38254..4013951cab 100644
--- a/openair1/SIMULATION/NR_PHY/ulsim.c
+++ b/openair1/SIMULATION/NR_PHY/ulsim.c
@@ -1420,7 +1420,7 @@ int main(int argc, char *argv[])
0);
}
- if ((ulsch_gNB->last_iteration_cnt >= ulsch_gNB->max_ldpc_iterations + 1) || ul_proc_error == 1) {
+ if ((ulsch_gNB->last_iteration_cnt >= ulsch_gNB->max_ldpc_iterations) || ul_proc_error == 1) {
error_flag = 1;
n_errors[round]++;
crc_status = 1;
diff --git a/openair2/COMMON/mac_messages_types.h b/openair2/COMMON/mac_messages_types.h
index bc9e8f6c8a..ebbda2fc26 100644
--- a/openair2/COMMON/mac_messages_types.h
+++ b/openair2/COMMON/mac_messages_types.h
@@ -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 {
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h
index 143d4623d7..a83c85dd25 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h
@@ -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
//=========
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
index f3693e2791..2da3d9df93 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
@@ -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
}
}
}
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
index e5f7fb4fcf..b8d1fae38c 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
@@ -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);
diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c
index 09d0eb2928..8c905a8f58 100644
--- a/openair2/LAYER2/NR_MAC_UE/config_ue.c
+++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c
@@ -44,6 +44,44 @@
#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 int get_ta_offset(long *n_TimingAdvanceOffset)
+{
+ if (!n_TimingAdvanceOffset)
+ return -1;
+
+ switch (*n_TimingAdvanceOffset) {
+ case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n0 :
+ return 0;
+ case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n25600 :
+ return 25600;
+ case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n39936 :
+ return 39936;
+ default :
+ AssertFatal(false, "Invalid n-TimingAdvanceOffset\n");
+ }
+ return -1;
+}
+
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;
@@ -142,6 +180,7 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo
// cell config
cfg->cell_config.phy_cell_id = mac->physCellId;
cfg->cell_config.frame_duplex_type = frame_type;
+ cfg->cell_config.N_TA_offset = get_ta_offset(scc->n_TimingAdvanceOffset);
// SSB config
cfg->ssb_config.ss_pbch_power = scc->ss_PBCH_BlockPower;
@@ -187,8 +226,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);
}
@@ -344,6 +382,7 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t
// cell config
cfg->cell_config.phy_cell_id = *scc->physCellId;
cfg->cell_config.frame_duplex_type = frame_type;
+ cfg->cell_config.N_TA_offset = get_ta_offset(scc->n_TimingAdvanceOffset);
// SSB config
cfg->ssb_config.ss_pbch_power = scc->ss_PBCH_BlockPower;
@@ -411,8 +450,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 +1437,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 +1461,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++) {
@@ -1684,24 +1722,6 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t
AssertFatal(!ret, "mutex failed %d\n", ret);
}
-static int get_ta_offset(long *n_TimingAdvanceOffset)
-{
- if (!n_TimingAdvanceOffset)
- return -1;
-
- switch (*n_TimingAdvanceOffset) {
- case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n0 :
- return 0;
- case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n25600 :
- return 25600;
- case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n39936 :
- return 39936;
- default :
- AssertFatal(false, "Invalid n-TimingAdvanceOffset\n");
- }
- return -1;
-}
-
static void configure_si_schedulingInfo(NR_UE_MAC_INST_t *mac,
NR_SI_SchedulingInfo_t *si_SchedulingInfo,
NR_SI_SchedulingInfo_v1700_t *si_SchedulingInfo_v1700)
@@ -1743,17 +1763,18 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *si
AssertFatal(scc, "SIB1 SCC should not be NULL\n");
UPDATE_IE(mac->tdd_UL_DL_ConfigurationCommon, scc->tdd_UL_DL_ConfigurationCommon, NR_TDD_UL_DL_ConfigCommon_t);
configure_si_schedulingInfo(mac, si_SchedulingInfo, si_SchedulingInfo_v1700);
- 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 +1788,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);
@@ -1812,12 +1830,15 @@ static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac,
if (reconfWithSync->spCellConfigCommon) {
NR_ServingCellConfigCommon_t *scc = reconfWithSync->spCellConfigCommon;
- mac->n_ta_offset = get_ta_offset(scc->n_TimingAdvanceOffset);
if (scc->physCellId)
mac->physCellId = *scc->physCellId;
mac->dmrs_TypeA_Position = scc->dmrs_TypeA_Position;
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);
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
index fbd96532f9..cfa3952759 100644
--- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h
+++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
@@ -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;
@@ -632,7 +597,6 @@ typedef struct NR_UE_MAC_INST_s {
int dmrs_TypeA_Position;
int p_Max;
int p_Max_alt;
- int n_ta_offset; // -1 not present, otherwise value to be applied
ntn_timing_advance_componets_t ntn_ta;
@@ -670,6 +634,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;
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h
index fbc98964e3..a2b2e0f777 100644
--- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h
@@ -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);
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_tables.c b/openair2/LAYER2/NR_MAC_UE/mac_tables.c
index bd4cc6d8f3..a313600609 100644
--- a/openair2/LAYER2/NR_MAC_UE/mac_tables.c
+++ b/openair2/LAYER2/NR_MAC_UE/mac_tables.c
@@ -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;
diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c
index 35167b6173..8df19c7139 100644
--- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c
+++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c
@@ -68,7 +68,7 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
mac->uecap_maxMIMO_PUSCH_layers_nocb = 0;
mac->p_Max = INT_MIN;
mac->p_Max_alt = INT_MIN;
- mac->n_ta_offset = -1;
+ mac->msg3_C_RNTI = false;
mac->ntn_ta.ntn_params_changed = false;
reset_mac_inst(mac);
@@ -77,8 +77,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 +114,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 +179,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 +195,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
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c
index 51a3ad8c9d..01b33465e7 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c
@@ -38,126 +38,18 @@
#include "LAYER2/NR_MAC_UE/mac_proto.h"
#include
#include "openair2/LAYER2/RLC/rlc.h"
-#include "openair2/LAYER2/NR_MAC_UE/mac_defs.h"
-
int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac)
{
RA_config_t *ra = &mac->ra;
int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm);
- int16_t ra_preamble_rx_power = (int16_t)(ra->prach_resources.ra_PREAMBLE_RECEIVED_TARGET_POWER + pathloss);
- return min(ra->prach_resources.RA_PCMAX, ra_preamble_rx_power);
+ int16_t ra_preamble_rx_power = (int16_t)(ra->prach_resources.ra_preamble_rx_target_power + pathloss);
+ return min(ra->prach_resources.Pc_max, ra_preamble_rx_power);
}
-// Random Access procedure initialization as per 5.1.1 and initialization of variables specific
-// to Random Access type as specified in clause 5.1.1a (3GPP TS 38.321 version 16.2.1 Release 16)
-// todo:
-// - check if carrier to use is explicitly signalled then do (1) RA CARRIER SELECTION (SUL, NUL) (2) set PCMAX (currently hardcoded to 0)
-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)
+static void set_preambleTransMax(RA_config_t *ra, long preambleTransMax)
{
- mac->state = UE_PERFORMING_RA;
- RA_config_t *ra = &mac->ra;
- ra->RA_active = true;
- ra->ra_PreambleIndex = -1;
- ra->RA_usedGroupA = 1;
- ra->RA_RAPID_found = 0;
- ra->preambleTransMax = 0;
- ra->first_Msg3 = true;
- ra->starting_preamble_nb = 0;
- ra->RA_backoff_cnt = 0;
- ra->RA_window_cnt = -1;
-
- fapi_nr_config_request_t *cfg = &mac->phy_config.config_req;
-
- prach_resources->RA_PREAMBLE_BACKOFF = 0;
- NR_SubcarrierSpacing_t prach_scs;
- int scs_for_pcmax; // for long prach the UL BWP SCS is used for calculating RA_PCMAX
- if (nr_rach_ConfigCommon && nr_rach_ConfigCommon->msg1_SubcarrierSpacing) {
- prach_scs = *nr_rach_ConfigCommon->msg1_SubcarrierSpacing;
- scs_for_pcmax = prach_scs;
- } else {
- const unsigned int index = rach_ConfigGeneric->prach_ConfigurationIndex;
- const unsigned int unpaired = mac->phy_config.config_req.cell_config.frame_duplex_type;
- const unsigned int format = get_format0(index, unpaired, mac->frequency_range);
- prach_scs = get_delta_f_RA_long(format);
- scs_for_pcmax = mac->current_UL_BWP->scs;
- }
- int n_prbs = get_N_RA_RB(prach_scs, mac->current_UL_BWP->scs);
- int start_prb = rach_ConfigGeneric->msg1_FrequencyStart + mac->current_UL_BWP->BWPStart;
- // PRACH shall be as specified for QPSK modulated DFT-s-OFDM of equivalent RB allocation (38.101-1)
- prach_resources->RA_PCMAX = nr_get_Pcmax(mac->p_Max,
- mac->nr_band,
- mac->frame_structure.frame_type,
- mac->frequency_range,
- mac->current_UL_BWP->channel_bandwidth,
- 2,
- false,
- scs_for_pcmax,
- cfg->carrier_config.dl_grid_size[scs_for_pcmax],
- true,
- n_prbs,
- start_prb);
- prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER = 1;
- prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER = 1;
- prach_resources->POWER_OFFSET_2STEP_RA = 0;
- prach_resources->RA_SCALING_FACTOR_BI = 1;
-
-
- // Contention Free
- if (rach_ConfigDedicated) {
- if (rach_ConfigDedicated->cfra){
- LOG_I(MAC, "Initialization of 4-Step CFRA procedure\n");
- prach_resources->RA_TYPE = RA_4_STEP;
- ra->ra_type = RA_4_STEP;
- ra->cfra = 1;
- } else if (rach_ConfigDedicated->ext1){
- if (rach_ConfigDedicated->ext1->cfra_TwoStep_r16) {
- LOG_I(MAC, "Initialization of 2-Step CFRA procedure\n");
- prach_resources->RA_TYPE = RA_2_STEP;
- ra->ra_type = RA_2_STEP;
- ra->cfra = 1;
- } else {
- LOG_E(NR_MAC, "Config not handled\n");
- }
- } else {
- LOG_E(NR_MAC, "Config not handled\n");
- }
- // Contention Based
- } else if (mac->current_UL_BWP->msgA_ConfigCommon_r16) {
- LOG_I(MAC, "Initialization of 2-Step CBRA procedure\n");
- prach_resources->RA_TYPE = RA_2_STEP;
- ra->ra_type = RA_2_STEP;
- ra->cfra = 0;
- } else if (nr_rach_ConfigCommon) {
- LOG_I(MAC, "Initialization of 4-Step CBRA procedure\n");
- prach_resources->RA_TYPE = RA_4_STEP;
- ra->ra_type = RA_4_STEP;
- ra->cfra = 0;
- } else {
- LOG_E(MAC, "Config not handled\n");
- AssertFatal(false, "In %s: config not handled\n", __FUNCTION__);
- }
-
- switch (rach_ConfigGeneric->powerRampingStep){ // in dB
- case 0:
- prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 0;
- break;
- case 1:
- prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 2;
- break;
- case 2:
- prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 4;
- break;
- case 3:
- prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 6;
- break;
- }
-
- switch (rach_ConfigGeneric->preambleTransMax) {
+ switch (preambleTransMax) {
case 0:
ra->preambleTransMax = 3;
break;
@@ -191,404 +83,983 @@ void init_RA(NR_UE_MAC_INST_t *mac,
case 10:
ra->preambleTransMax = 200;
break;
- }
-
- if (ra->ra_type == RA_2_STEP) {
- if (nr_rach_ConfigCommon->ext1 && nr_rach_ConfigCommon->ext1->ra_PrioritizationForAccessIdentity_r16) {
- LOG_D(MAC, "Missing implementation for Access Identity initialization procedures\n");
- }
- // Perform initialization of variables specific to Random Access type as specified in clause 5.1.1a of TS 38.321
- NR_RACH_ConfigGenericTwoStepRA_r16_t nr_ra_ConfigGenericTwoStepRA_r16 =
- mac->current_UL_BWP->msgA_ConfigCommon_r16->rach_ConfigCommonTwoStepRA_r16.rach_ConfigGenericTwoStepRA_r16;
- // Takes the value of 2-Step RA variable
- if (nr_ra_ConfigGenericTwoStepRA_r16.msgA_PreamblePowerRampingStep_r16) {
- prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = *nr_ra_ConfigGenericTwoStepRA_r16.msgA_PreamblePowerRampingStep_r16;
- } else {
- // If 2-Step variable does not exist, it takes the value of 4-Step RA variable
- prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = nr_rach_ConfigCommon->rach_ConfigGeneric.powerRampingStep;
- }
- prach_resources->RA_SCALING_FACTOR_BI = 1;
- // Takes the value of 2-Step RA variable
- if (nr_ra_ConfigGenericTwoStepRA_r16.preambleTransMax_r16) {
- ra->preambleTransMax = (int)*nr_ra_ConfigGenericTwoStepRA_r16.preambleTransMax_r16;
- } else {
- // If 2-Step variable does not exist, it takes the value of 4-Step RA variable
- ra->preambleTransMax = (int)nr_rach_ConfigCommon->rach_ConfigGeneric.preambleTransMax;
- }
+ default:
+ AssertFatal(false, "Invalid preambleTransMax\n");
}
}
-/* TS 38.321 subclause 7.3 - return DELTA_PREAMBLE values in dB */
-static int8_t nr_get_DELTA_PREAMBLE(const NR_UE_MAC_INST_t *mac, int CC_id, uint16_t prach_format)
+static int get_Msg3SizeGroupA(long ra_Msg3SizeGroupA)
{
- const NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon;
- int prach_sequence_length = nr_rach_ConfigCommon->prach_RootSequenceIndex.present - 1;
-
- AssertFatal(CC_id == 0, "Transmission on secondary CCs is not supported yet\n");
-
- // Preamble formats given by prach_ConfigurationIndex and tables 6.3.3.2-2 and 6.3.3.2-2 in TS 38.211
-
- unsigned int prachConfigIndex = nr_rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex;
-
- if (prach_sequence_length == 0) {
- AssertFatal(prach_format < 4, "Illegal PRACH format %d for sequence length 839\n", prach_format);
- switch (prach_format) {
-
- // long preamble formats
- case 0:
- case 3:
- return 0;
-
- case 1:
- return -3;
-
- case 2:
- return -6;
-
- default:
- AssertFatal(1 == 0, "[UE %d] ue_procedures.c: FATAL, Illegal preambleFormat %d, prachConfigIndex %d\n",
- mac->ue_id,
- prach_format,
- prachConfigIndex);
- }
- } else {
- // SCS configuration from msg1_SubcarrierSpacing and table 4.2-1 in TS 38.211
-
- AssertFatal(nr_rach_ConfigCommon->msg1_SubcarrierSpacing, "msg1_SubcarrierSpacing required but missing\n");
- NR_SubcarrierSpacing_t scs = *nr_rach_ConfigCommon->msg1_SubcarrierSpacing;
- AssertFatal(scs >= NR_SubcarrierSpacing_kHz15 && scs <= NR_SubcarrierSpacing_spare1, "Unknown msg1_SubcarrierSpacing %lu\n", scs);
- const unsigned int mu = scs;
-
- switch (prach_format) { // short preamble formats
- case 0:
- case 3:
- return 8 + 3*mu;
-
- case 1:
- case 4:
- case 8:
- return 5 + 3*mu;
-
- case 2:
- case 5:
- return 3 + 3*mu;
-
- case 6:
- return 3*mu;
-
- case 7:
- return 5 + 3*mu;
-
- default:
- AssertFatal(1 == 0, "[UE %d] ue_procedures.c: FATAL, Illegal preambleFormat %d, prachConfigIndex %d\n",
- mac->ue_id,
- prach_format,
- prachConfigIndex);
- }
- }
- return 0;
-}
-
-// TS 38.321 subclause 5.1.3 - RA preamble transmission - ra_PREAMBLE_RECEIVED_TARGET_POWER configuration
-// Measurement units:
-// - preambleReceivedTargetPower dBm (-202..-60, 2 dBm granularity)
-// - delta_preamble dB
-// - RA_PREAMBLE_POWER_RAMPING_STEP dB
-// - POWER_OFFSET_2STEP_RA dB
-// returns receivedTargerPower in dBm
-static int nr_get_Po_NOMINAL_PUSCH(NR_UE_MAC_INST_t *mac, NR_PRACH_RESOURCES_t *prach_resources, uint8_t CC_id)
-{
- int8_t receivedTargerPower;
- int8_t delta_preamble;
-
- NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon;
- long preambleReceivedTargetPower = nr_rach_ConfigCommon->rach_ConfigGeneric.preambleReceivedTargetPower;
- delta_preamble = nr_get_DELTA_PREAMBLE(mac, CC_id, prach_resources->prach_format);
-
- receivedTargerPower = preambleReceivedTargetPower +
- delta_preamble +
- (prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER - 1) * prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP +
- prach_resources->POWER_OFFSET_2STEP_RA;
-
- LOG_D(MAC, "ReceivedTargerPower is %d dBm \n", receivedTargerPower);
- return receivedTargerPower;
-}
-
-void ssb_rach_config(RA_config_t *ra, NR_PRACH_RESOURCES_t *prach_resources, NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon)
-{
- // 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;
- bool 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
- int total_preambles_per_ssb;
- uint8_t ssb_nb_in_ro;
- int numberOfRA_Preambles = 64;
-
- switch (ssb_perRACH_config){
- case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth:
- multiple_ssb_per_ro = false;
- ssb_rach_ratio = 8;
- ra->cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1);
+ int bits = 0;
+ switch (ra_Msg3SizeGroupA) {
+ case NR_RACH_ConfigCommon__groupBconfigured__ra_Msg3SizeGroupA_b56:
+ bits = 56;
break;
- case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth:
- multiple_ssb_per_ro = false;
- ssb_rach_ratio = 4;
- ra->cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneFourth + 1);
+ case NR_RACH_ConfigCommon__groupBconfigured__ra_Msg3SizeGroupA_b144:
+ bits = 144;
break;
- case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf:
- multiple_ssb_per_ro = false;
- ssb_rach_ratio = 2;
- ra->cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneHalf + 1);
+ case NR_RACH_ConfigCommon__groupBconfigured__ra_Msg3SizeGroupA_b208:
+ bits = 208;
break;
- case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one:
- multiple_ssb_per_ro = true;
- ssb_rach_ratio = 1;
- ra->cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one + 1);
+ case NR_RACH_ConfigCommon__groupBconfigured__ra_Msg3SizeGroupA_b256:
+ bits = 256;
break;
- case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two:
- multiple_ssb_per_ro = true;
- ssb_rach_ratio = 2;
- ra->cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.two + 1);
+ case NR_RACH_ConfigCommon__groupBconfigured__ra_Msg3SizeGroupA_b282:
+ bits = 282;
break;
- case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four:
- multiple_ssb_per_ro = true;
- ssb_rach_ratio = 4;
- ra->cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.four;
+ case NR_RACH_ConfigCommon__groupBconfigured__ra_Msg3SizeGroupA_b480:
+ bits = 480;
break;
- case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight:
- multiple_ssb_per_ro = true;
- ssb_rach_ratio = 8;
- ra->cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.eight;
+ case NR_RACH_ConfigCommon__groupBconfigured__ra_Msg3SizeGroupA_b640:
+ bits = 640;
break;
- case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen:
- multiple_ssb_per_ro = true;
- ssb_rach_ratio = 16;
- ra->cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.sixteen;
+ case NR_RACH_ConfigCommon__groupBconfigured__ra_Msg3SizeGroupA_b800:
+ bits = 800;
+ break;
+ case NR_RACH_ConfigCommon__groupBconfigured__ra_Msg3SizeGroupA_b1000:
+ bits = 1000;
+ break;
+ case NR_RACH_ConfigCommon__groupBconfigured__ra_Msg3SizeGroupA_b72:
+ bits = 72;
break;
default:
- AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_config);
- }
-
- if (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 = ra->ssb_nb_in_ro;
- ra->starting_preamble_nb = total_preambles_per_ssb * ssb_nb_in_ro;
- } else {
- total_preambles_per_ssb = numberOfRA_Preambles;
- ra->starting_preamble_nb = 0;
+ AssertFatal(false, "Unknown ra-Msg3SizeGroupA %lu\n", ra_Msg3SizeGroupA);
}
+ return bits / 8; // returning bytes
}
-// This routine implements RA preamble configuration according to
-// section 5.1 (Random Access procedure) of 3GPP TS 38.321 version 16.2.1 Release 16
-void ra_preambles_config(NR_PRACH_RESOURCES_t *prach_resources, NR_UE_MAC_INST_t *mac, int16_t dl_pathloss){
+static int get_messagePowerOffsetGroupB(long messagePowerOffsetGroupB)
+{
+ int pow_offset = 0;
+ switch (messagePowerOffsetGroupB) {
+ case NR_RACH_ConfigCommon__groupBconfigured__messagePowerOffsetGroupB_minusinfinity:
+ pow_offset = INT_MIN;
+ break;
+ case NR_RACH_ConfigCommon__groupBconfigured__messagePowerOffsetGroupB_dB0:
+ pow_offset = 0;
+ break;
+ case NR_RACH_ConfigCommon__groupBconfigured__messagePowerOffsetGroupB_dB5:
+ pow_offset = 5;
+ break;
+ case NR_RACH_ConfigCommon__groupBconfigured__messagePowerOffsetGroupB_dB8:
+ pow_offset = 8;
+ break;
+ case NR_RACH_ConfigCommon__groupBconfigured__messagePowerOffsetGroupB_dB10:
+ pow_offset = 10;
+ break;
+ case NR_RACH_ConfigCommon__groupBconfigured__messagePowerOffsetGroupB_dB12:
+ pow_offset = 12;
+ break;
+ case NR_RACH_ConfigCommon__groupBconfigured__messagePowerOffsetGroupB_dB15:
+ pow_offset = 15;
+ break;
+ case NR_RACH_ConfigCommon__groupBconfigured__messagePowerOffsetGroupB_dB18:
+ pow_offset = 18;
+ break;
+ default:
+ AssertFatal(false, "Unknown messagePowerOffsetGroupB %lu\n", messagePowerOffsetGroupB);
+ }
+ return pow_offset;
+}
- int messageSizeGroupA = 0;
- int sizeOfRA_PreamblesGroupA = 0;
- int messagePowerOffsetGroupB = 0;
- int PLThreshold = 0;
- long deltaPreamble_Msg3 = 0;
- uint8_t noGroupB = 0;
+static void select_preamble_group(NR_UE_MAC_INST_t *mac)
+{
+ RA_config_t *ra = &mac->ra;
+ // TODO if the RA_TYPE is switched from 2-stepRA to 4-stepRA
+
+ if (!ra->Msg3_buffer) { // if Msg3 buffer is empty
+ NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon;
+ if (nr_rach_ConfigCommon && nr_rach_ConfigCommon->groupBconfigured) { // if Random Access Preambles group B is configured
+ struct NR_RACH_ConfigCommon__groupBconfigured *groupB = nr_rach_ConfigCommon->groupBconfigured;
+ // if the potential Msg3 size (UL data available for transmission plus MAC subheader(s) and,
+ // where required, MAC CEs) is greater than ra-Msg3SizeGroupA
+ // if the pathloss is less than PCMAX (of the Serving Cell performing the Random Access Procedure)
+ // β preambleReceivedTargetPower β msg3-DeltaPreamble β messagePowerOffsetGroupB
+ int groupB_pow_offset = get_messagePowerOffsetGroupB(groupB->messagePowerOffsetGroupB);
+ int PLThreshold = ra->prach_resources.Pc_max - ra->preambleRxTargetPower - ra->msg3_deltaPreamble - groupB_pow_offset;
+ int pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm);
+ // TODO if the Random Access procedure was initiated for the CCCH logical channel and the CCCH SDU size
+ // plus MAC subheader is greater than ra-Msg3SizeGroupA
+ if (ra->Msg3_size > get_Msg3SizeGroupA(groupB->ra_Msg3SizeGroupA) && pathloss < PLThreshold)
+ ra->RA_GroupA = false;
+ else
+ ra->RA_GroupA = true;
+ } else
+ ra->RA_GroupA = true;
+ }
+ // else if Msg3 is being retransmitted, we keep what used in first transmission of Msg3
+}
+
+static ssb_ro_preambles_t get_ssb_ro_preambles_4step(struct NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB *config)
+{
+ ssb_ro_preambles_t ret = {0};
+ switch (config->present) {
+ case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth:
+ ret.ssb_per_ro = 0.125;
+ ret.preambles_per_ssb = (config->choice.oneEighth + 1) << 2;
+ break;
+ case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth:
+ ret.ssb_per_ro = 0.25;
+ ret.preambles_per_ssb = (config->choice.oneFourth + 1) << 2;
+ break;
+ case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf:
+ ret.ssb_per_ro = 0.5;
+ ret.preambles_per_ssb = (config->choice.oneHalf + 1) << 2;
+ break;
+ case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one:
+ ret.ssb_per_ro = 1;
+ ret.preambles_per_ssb = (config->choice.one + 1) << 2;
+ break;
+ case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two:
+ ret.ssb_per_ro = 2;
+ ret.preambles_per_ssb = (config->choice.two + 1) << 2;
+ break;
+ case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four:
+ ret.ssb_per_ro = 4;
+ ret.preambles_per_ssb = config->choice.four;
+ break;
+ case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight:
+ ret.ssb_per_ro = 8;
+ ret.preambles_per_ssb = config->choice.eight;
+ break;
+ case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen:
+ ret.ssb_per_ro = 16;
+ ret.preambles_per_ssb = config->choice.sixteen;
+ break;
+ default:
+ AssertFatal(false, "Invalid ssb_perRACH_OccasionAndCB_PreamblesPerSSB\n");
+ }
+ LOG_D(NR_MAC, "SSB per RO %f preambles per SSB %d\n", ret.ssb_per_ro, ret.preambles_per_ssb);
+ return ret;
+}
+
+static ssb_ro_preambles_t get_ssb_ro_preambles_2step(struct NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16 *config)
+{
+ ssb_ro_preambles_t ret = {0};
+ switch (config->present) {
+ case NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16_PR_oneEighth :
+ ret.ssb_per_ro = 0.125;
+ ret.preambles_per_ssb = (config->choice.oneEighth + 1) << 2;
+ break;
+ case NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16_PR_oneFourth :
+ ret.ssb_per_ro = 0.25;
+ ret.preambles_per_ssb = (config->choice.oneFourth + 1) << 2;
+ break;
+ case NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16_PR_oneHalf :
+ ret.ssb_per_ro = 0.5;
+ ret.preambles_per_ssb = (config->choice.oneHalf + 1) << 2;
+ break;
+ case NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16_PR_one :
+ ret.ssb_per_ro = 1;
+ ret.preambles_per_ssb = (config->choice.one + 1) << 2;
+ break;
+ case NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16_PR_two :
+ ret.ssb_per_ro = 2;
+ ret.preambles_per_ssb = (config->choice.two + 1) << 2;
+ break;
+ case NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16_PR_four :
+ ret.ssb_per_ro = 4;
+ ret.preambles_per_ssb = config->choice.four;
+ break;
+ case NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16_PR_eight :
+ ret.ssb_per_ro = 8;
+ ret.preambles_per_ssb = config->choice.eight;
+ break;
+ case NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16_PR_sixteen :
+ ret.ssb_per_ro = 16;
+ ret.preambles_per_ssb = config->choice.sixteen;
+ break;
+ default :
+ AssertFatal(false, "Invalid msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16\n");
+ }
+ return ret;
+}
+
+static void config_preamble_index(NR_UE_MAC_INST_t *mac)
+{
+ RA_config_t *ra = &mac->ra;
// Random seed generation
unsigned int seed;
-
if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) {
// Overwrite seed with non-random seed for IQ player/recorder
seed = 1;
} else {
// & to truncate the int64_t and keep only the LSB bits, up to sizeof(int)
- seed = (unsigned int) (rdtsc_oai() & ~0);
+ seed = (unsigned int)(rdtsc_oai() & ~0);
}
- RA_config_t *ra = &mac->ra;
- NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon;
- NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric;
-
- if (mac->current_UL_BWP->msg3_DeltaPreamble) {
- deltaPreamble_Msg3 = (*mac->current_UL_BWP->msg3_DeltaPreamble) * 2; // dB
- LOG_D(MAC, "In %s: deltaPreamble_Msg3 set to %ld\n", __FUNCTION__, deltaPreamble_Msg3);
- }
-
- if (!setup->groupBconfigured) {
- noGroupB = 1;
- LOG_D(MAC, "In %s:%d: preambles group B is not configured...\n", __FUNCTION__, __LINE__);
- } else {
- // RA preambles group B is configured
- // - Random Access Preambles group B is configured for 4-step RA type
- // - Defining the number of RA preambles in RA Preamble Group A for each SSB
- LOG_D(MAC, "In %s:%d: preambles group B is configured...\n", __FUNCTION__, __LINE__);
- sizeOfRA_PreamblesGroupA = setup->groupBconfigured->numberOfRA_PreamblesGroupA;
- switch (setup->groupBconfigured->ra_Msg3SizeGroupA){
- /* - Threshold to determine the groups of RA preambles */
- case 0:
- messageSizeGroupA = 56;
- break;
- case 1:
- messageSizeGroupA = 144;
- break;
- case 2:
- messageSizeGroupA = 208;
- break;
- case 3:
- messageSizeGroupA = 256;
- break;
- case 4:
- messageSizeGroupA = 282;
- break;
- case 5:
- messageSizeGroupA = 480;
- break;
- case 6:
- messageSizeGroupA = 640;
- break;
- case 7:
- messageSizeGroupA = 800;
- break;
- case 8:
- messageSizeGroupA = 1000;
- break;
- case 9:
- messageSizeGroupA = 72;
- break;
- default:
- AssertFatal(1 == 0, "Unknown ra_Msg3SizeGroupA %lu\n", setup->groupBconfigured->ra_Msg3SizeGroupA);
- /* todo cases 10 -15*/
- }
-
- /* Power offset for preamble selection in dB */
- messagePowerOffsetGroupB = -9999;
- switch (setup->groupBconfigured->messagePowerOffsetGroupB){
- case 0:
- messagePowerOffsetGroupB = -9999;
- break;
- case 1:
- messagePowerOffsetGroupB = 0;
- break;
- case 2:
- messagePowerOffsetGroupB = 5;
- break;
- case 3:
- messagePowerOffsetGroupB = 8;
- break;
- case 4:
- messagePowerOffsetGroupB = 10;
- break;
- case 5:
- messagePowerOffsetGroupB = 12;
- break;
- case 6:
- messagePowerOffsetGroupB = 15;
- break;
- case 7:
- messagePowerOffsetGroupB = 18;
- break;
- default:
- AssertFatal(1 == 0,"Unknown messagePowerOffsetGroupB %lu\n", setup->groupBconfigured->messagePowerOffsetGroupB);
- }
-
- PLThreshold = prach_resources->RA_PCMAX - rach_ConfigGeneric->preambleReceivedTargetPower - deltaPreamble_Msg3 - messagePowerOffsetGroupB;
-
- }
-
- /* Msg3 has not been transmitted yet */
- if (ra->first_Msg3) {
- if(ra->ra_PreambleIndex < 0 || ra->ra_PreambleIndex > 63) {
- if (noGroupB) {
- // use Group A preamble
- ra->ra_PreambleIndex = ra->starting_preamble_nb + (rand_r(&seed) % ra->cb_preambles_per_ssb);
- ra->RA_usedGroupA = 1;
- } else if ((ra->Msg3_size < messageSizeGroupA) && (dl_pathloss > PLThreshold)) {
- // Group B is configured and RA preamble Group A is used
- // - todo add condition on CCCH_sdu_size for initiation by CCCH
- ra->ra_PreambleIndex = ra->starting_preamble_nb + (rand_r(&seed) % sizeOfRA_PreamblesGroupA);
- ra->RA_usedGroupA = 1;
- } else {
- // Group B preamble is configured and used
- // the first sizeOfRA_PreamblesGroupA RA preambles belong to RA Preambles Group A
- // the remaining belong to RA Preambles Group B
- ra->ra_PreambleIndex = ra->starting_preamble_nb + sizeOfRA_PreamblesGroupA + (rand_r(&seed) % (ra->cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA));
- ra->RA_usedGroupA = 0;
- }
- }
- } else { // Msg3 is being retransmitted
- if (ra->RA_usedGroupA && noGroupB) {
- ra->ra_PreambleIndex = ra->starting_preamble_nb + (rand_r(&seed) % ra->cb_preambles_per_ssb);
- } else if (ra->RA_usedGroupA && !noGroupB){
- ra->ra_PreambleIndex = ra->starting_preamble_nb + (rand_r(&seed) % sizeOfRA_PreamblesGroupA);
- } else {
- ra->ra_PreambleIndex = ra->starting_preamble_nb + sizeOfRA_PreamblesGroupA + (rand_r(&seed) % (ra->cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA));
- }
- }
-}
-
-// This routine implements Section 5.1.2 (UE Random Access Resource Selection)
-// and Section 5.1.3 (Random Access Preamble Transmission) from 3GPP TS 38.321
-// - currently the PRACH preamble is set through RRC configuration for 4-step CFRA mode
-// todo:
-// - determine next available PRACH occasion
-// -- if RA initiated for SI request and ra_AssociationPeriodIndex and si-RequestPeriod are configured
-// -- else if SSB is selected above
-// -- else if CSI-RS is selected above
-// - switch initialisation cases
-// -- RA initiated by beam failure recovery operation (subclause 5.17 TS 38.321)
-// --- SSB selection, set ra_PreambleIndex
-// -- RA initiated by PDCCH: ra_preamble_index provided by PDCCH && ra_PreambleIndex != 0b000000
-// --- set PREAMBLE_INDEX to ra_preamble_index
-// --- select the SSB signalled by PDCCH
-// -- RA initiated for SI request:
-// --- SSB selection, set ra_PreambleIndex
-// - condition on notification of suspending power ramping counter from lower layer (5.1.3 TS 38.321)
-// - check if SSB or CSI-RS have not changed since the selection in the last RA Preamble tranmission
-// - Contention-based RA preamble selection:
-// -- selection of SSB with SS-RSRP above rsrp-ThresholdSSB else select any SSB
-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)
-{
- RA_config_t *ra = &mac->ra;
-
NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon;
-
- LOG_D(MAC, "Getting PRACH resources frame (first_Msg3 %d)\n", ra->first_Msg3);
-
- if (rach_ConfigDedicated) {
- if (rach_ConfigDedicated->cfra){
- uint8_t cfra_ssb_resource_idx = 0;
- ra->ra_PreambleIndex = rach_ConfigDedicated->cfra->resources.choice.ssb->ssb_ResourceList.list.array[cfra_ssb_resource_idx]->ra_PreambleIndex;
- LOG_D(MAC, "Selected RA preamble index %d for contention-free random access procedure for SSB with Id %d\n",
- ra->ra_PreambleIndex,
- cfra_ssb_resource_idx);
+ int nb_of_preambles = 64;
+ bool groupBconfigured = false;
+ int preamb_ga = 0;
+ if (ra->ra_type == RA_4_STEP) {
+ AssertFatal(nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB,
+ "Not expeting ssb_perRACH_OccasionAndCB_PreamblesPerSSB to be NULL here\n");
+ ra->ssb_ro_config = get_ssb_ro_preambles_4step(nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB);
+ if (nr_rach_ConfigCommon->totalNumberOfRA_Preambles)
+ nb_of_preambles = *nr_rach_ConfigCommon->totalNumberOfRA_Preambles;
+ // Amongst the contention-based Random Access Preambles associated with an SSB the first numberOfRA-PreamblesGroupA
+ // included in groupBconfigured Random Access Preambles belong to Random Access Preambles group A.
+ // The remaining Random Access Preambles associated with the SSB belong to Random Access Preambles group B (if configured)
+ select_preamble_group(mac);
+ if (nr_rach_ConfigCommon->groupBconfigured) {
+ groupBconfigured = true;
+ preamb_ga = nr_rach_ConfigCommon->groupBconfigured->numberOfRA_PreamblesGroupA;
}
} else {
- /* TODO: This controls the tx_power of UE and the ramping procedure of RA of UE. Later we
- can abstract this, perhaps in the proxy. But for the time being lets leave it as below. */
- int16_t dl_pathloss = !get_softmodem_params()->emulate_l1 ? compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm) : 0;
- ssb_rach_config(ra, prach_resources, nr_rach_ConfigCommon);
- ra_preambles_config(prach_resources, mac, dl_pathloss);
- LOG_D(MAC, "[RAPROC] - Selected RA preamble index %d for contention-based random access procedure... \n", ra->ra_PreambleIndex);
+ NR_RACH_ConfigCommonTwoStepRA_r16_t *twostep = &mac->current_UL_BWP->msgA_ConfigCommon_r16->rach_ConfigCommonTwoStepRA_r16;
+ AssertFatal(twostep->groupB_ConfiguredTwoStepRA_r16 == NULL, "GroupB preambles not supported for 2-step RA\n");
+ ra->RA_GroupA = true;
+ // The field is mandatory present if the 2-step random access type occasions are shared with 4-step random access type,
+ // otherwise the field is not present
+ bool sharedROs = twostep->msgA_CB_PreamblesPerSSB_PerSharedRO_r16 != NULL;
+ AssertFatal(sharedROs == false, "Shared ROs between 2- and 4-step RA not supported\n");
+
+ // For Type-2 random access procedure with separate configuration of PRACH occasions with Type-1 random access procedure
+ // configuration by msgA-SSB-PerRACH-OccasionAndCB-PreamblesPerSSB when provided;
+ // otherwise, by ssb-perRACH-OccasionAndCB-PreamblesPerSSB
+ if (twostep->msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16)
+ ra->ssb_ro_config = get_ssb_ro_preambles_2step(twostep->msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16);
+ else
+ ra->ssb_ro_config = get_ssb_ro_preambles_4step(nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB);
+ if (twostep->msgA_TotalNumberOfRA_Preambles_r16)
+ nb_of_preambles = *twostep->msgA_TotalNumberOfRA_Preambles_r16;
}
- if (prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER > 1)
- prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER++;
- prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(mac, prach_resources, CC_id);
-
+ int groupOffset = 0;
+ if (groupBconfigured) {
+ AssertFatal(preamb_ga < nb_of_preambles, "Nb of preambles for groupA not compatible with total number of preambles\n");
+ if (!ra->RA_GroupA) { // groupB
+ groupOffset = preamb_ga;
+ nb_of_preambles = nb_of_preambles - preamb_ga;
+ } else {
+ nb_of_preambles = preamb_ga;
+ }
+ }
+ int rand_preamb = (rand_r(&seed) % ra->ssb_ro_config.preambles_per_ssb);
+ if (ra->ssb_ro_config.ssb_per_ro < 1)
+ ra->ra_PreambleIndex = groupOffset + rand_preamb;
+ else {
+ int ssb_pr_idx = mac->ssb_list.nb_ssb_per_index[mac->mib_ssb] % (int)ra->ssb_ro_config.ssb_per_ro;
+ ra->ra_PreambleIndex = groupOffset + (ssb_pr_idx * ra->ssb_ro_config.preambles_per_ssb) + rand_preamb;
+ }
+ AssertFatal(ra->ra_PreambleIndex < nb_of_preambles,
+ "Error! Selected preamble %d which exceeds number of prambles available %d\n",
+ ra->ra_PreambleIndex,
+ nb_of_preambles);
}
-// TbD: RA_attempt_number not used
-void nr_Msg1_transmitted(NR_UE_MAC_INST_t *mac)
+static void configure_ra_preamble(NR_UE_MAC_INST_t *mac)
{
RA_config_t *ra = &mac->ra;
- ra->ra_state = nrRA_WAIT_RAR;
- ra->RA_attempt_number++;
+ int ssb = -1; // init as not selected
+ ra->ro_mask_index = -1; // init as not selected
+ NR_RACH_ConfigDedicated_t *rach_ConfigDedicated = ra->rach_ConfigDedicated;
+ if (ra->ra_type == RA_4_STEP) {
+ // TODO if the Random Access procedure was initiated for SpCell beam failure recovery
+ // TODO if the Random Access procedure was initiated for SI request
+
+ if (ra->pdcch_order.active && ra->pdcch_order.preamble_index != 0xb000000) {
+ // set the PREAMBLE_INDEX to the signalled ra-PreambleIndex;
+ ra->ra_PreambleIndex = ra->pdcch_order.preamble_index;
+ // select the SSB signalled by PDCCH
+ ssb = ra->pdcch_order.ssb_index;
+ ra->ro_mask_index = ra->pdcch_order.prach_mask;
+ } else if (rach_ConfigDedicated && rach_ConfigDedicated->cfra) {
+ NR_CFRA_t *cfra = rach_ConfigDedicated->cfra;
+ AssertFatal(cfra->occasions == NULL, "Dedicated PRACH occasions for CFRA not supported\n");
+ AssertFatal(cfra->resources.present == NR_CFRA__resources_PR_ssb, "SSB-based CFRA supported only\n");
+ struct NR_CFRA__resources__ssb *ssb_list = cfra->resources.choice.ssb;
+ for (int i = 0; i < ssb_list->ssb_ResourceList.list.count; i++) {
+ NR_CFRA_SSB_Resource_t *res = ssb_list->ssb_ResourceList.list.array[i];
+ // TODO select an SSB with SS-RSRP above rsrp-ThresholdSSB amongst the associated SSBs
+ if (res->ssb == mac->mib_ssb) {
+ ssb = mac->mib_ssb;
+ // set the PREAMBLE_INDEX to a ra-PreambleIndex corresponding to the selected SSB
+ ra->ra_PreambleIndex = res->ra_PreambleIndex;
+ ra->ro_mask_index = ssb_list->ra_ssb_OccasionMaskIndex;
+ break;
+ }
+ }
+ } else { // for the contention-based Random Access preamble selection
+ // TODO if at least one of the SSBs with SS-RSRP above rsrp-ThresholdSSB is available
+ // else select any SSB
+ ssb = mac->mib_ssb;
+ config_preamble_index(mac);
+ }
+ } else { // 2-step RA
+ // if the contention-free 2-step RA type Resources associated with SSBs have been explicitly provided in rach-ConfigDedicated
+ // TODO and at least one SSB with SS-RSRP above msgA-RSRP-ThresholdSSB amongst the associated SSBs is available
+ if (ra->cfra) {
+ AssertFatal(rach_ConfigDedicated->ext1 && rach_ConfigDedicated->ext1->cfra_TwoStep_r16,
+ "Two-step CFRA should be configured here\n");
+ NR_CFRA_TwoStep_r16_t *cfra = rach_ConfigDedicated->ext1->cfra_TwoStep_r16;
+ AssertFatal(cfra->occasionsTwoStepRA_r16 == NULL, "Dedicated PRACH occasions for CFRA not supported\n");
+ for (int i = 0; i < cfra->resourcesTwoStep_r16.ssb_ResourceList.list.count; i++) {
+ NR_CFRA_SSB_Resource_t *res = cfra->resourcesTwoStep_r16.ssb_ResourceList.list.array[i];
+ if (res->ssb == mac->mib_ssb) {
+ ssb = mac->mib_ssb;
+ // set the PREAMBLE_INDEX to a ra-PreambleIndex corresponding to the selected SSB
+ ra->ra_PreambleIndex = res->ra_PreambleIndex;
+ ra->ro_mask_index = cfra->resourcesTwoStep_r16.ra_ssb_OccasionMaskIndex;
+ break;
+ }
+ }
+ } else { // for the contention-based Random Access Preamble selection
+ // TODO if at least one of the SSBs with SS-RSRP above msgA-RSRP-ThresholdSSB is available
+ // else select any SSB
+ ssb = mac->mib_ssb;
+ config_preamble_index(mac);
+ }
+ }
+ AssertFatal(ssb >= 0, "Something wrong! RA resource selection didn't set any SSB\n");
+ // setting the RA ssb value as the progressive number of SSB transmitted
+ // non-transmitted SSBs are not taken into account
+ int ssb_idx = mac->ssb_list.nb_ssb_per_index[ssb];
+ ra->new_ssb = ssb != ssb_idx ? true : false;
+ ra->ra_ssb = ssb_idx;
+
+ // TODO not sure how to handle the RO mask when it is limiting the RO occasions
+ AssertFatal(ra->ro_mask_index <= 0, "Handling of RACH occasion masking indication not implemented\n");
+}
+
+static bool check_mixed_slot_prach(frame_structure_t *fs, int slot, int start_prach, int end_prach)
+{
+ bool is_mixed = is_mixed_slot(slot, fs);
+ if (is_mixed) {
+ tdd_bitmap_t *bitmap = &fs->period_cfg.tdd_slot_bitmap[slot % fs->numb_slots_period];
+ if (bitmap->num_ul_symbols == 0)
+ return false;
+ int ul_end = NR_NUMBER_OF_SYMBOLS_PER_SLOT - 1;
+ int ul_start = NR_NUMBER_OF_SYMBOLS_PER_SLOT - bitmap->num_ul_symbols;
+ if (start_prach < ul_start || end_prach > ul_end)
+ return false;
+ }
+ return true;
+}
+
+static void select_prach_occasion(RA_config_t *ra,
+ int nb_tx_ssb,
+ int n,
+ prach_occasion_info_t ra_occasions_period[n],
+ int num_ra_occasions_period)
+{
+ unsigned int seed;
+ if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) {
+ // Overwrite seed with non-random seed for IQ player/recorder
+ seed = 1;
+ } else {
+ // & to truncate the int64_t and keep only the LSB bits, up to sizeof(int)
+ seed = (unsigned int)(rdtsc_oai() & ~0);
+ }
+
+ int num_ros_per_ssb = 0;
+ int idx_ssb = 0;
+ int temp_idx = 0;
+ if (ra->ssb_ro_config.ssb_per_ro < 1) {
+ num_ros_per_ssb = (int)(1 / ra->ssb_ro_config.ssb_per_ro);
+ idx_ssb = (rand_r(&seed) % num_ros_per_ssb);
+ temp_idx = ra->ra_ssb * num_ros_per_ssb + idx_ssb;
+ } else {
+ int ssb_per_ro = nb_tx_ssb < ra->ssb_ro_config.ssb_per_ro ? nb_tx_ssb : ra->ssb_ro_config.ssb_per_ro;
+ num_ros_per_ssb = ra->association_periods * ssb_per_ro * num_ra_occasions_period / nb_tx_ssb;
+ idx_ssb = (rand_r(&seed) % num_ros_per_ssb);
+ int eq_ssb = ra->ra_ssb + (idx_ssb * nb_tx_ssb);
+ temp_idx = eq_ssb / ra->ssb_ro_config.ssb_per_ro;
+ }
+ int ro_index = temp_idx % num_ra_occasions_period;
+ int ass_period_idx = temp_idx / num_ra_occasions_period;
+ ra->sched_ro_info = ra_occasions_period[ro_index];
+ ra->sched_ro_info.association_period_idx = ass_period_idx;
+}
+
+static void configure_prach_occasions(NR_UE_MAC_INST_t *mac, int scs)
+{
+ RA_config_t *ra = &mac->ra;
+ int num_ra_occasions_period = 0;
+ frame_structure_t *fs = &mac->frame_structure;
+ nr_prach_info_t prach_info = get_nr_prach_occasion_info_from_index(ra->ra_config_index, mac->frequency_range, fs->frame_type);
+ int max_num_occasions = prach_info.N_RA_sfn * prach_info.N_t_slot * prach_info.N_RA_slot * ra->num_fd_occasions;
+ prach_occasion_info_t ra_occasions_period[max_num_occasions];
+ // Number of PRACH slots within a subframe (or 60kHz slot) to be taken into account only for 30 and 120kHz
+ // as defined in 5.3.2 of 211
+ int prach_slots_in_sf = (scs == 1 || scs == 3) ? prach_info.N_RA_slot : 1;
+ uint64_t temp_s_map = prach_info.s_map;
+ int n_frames = prach_info.y2 == -1 ? 1 : 2;
+ for (int n = 0; n < n_frames; n++) {
+ int sf = 0;
+ for (int s = 0; s < prach_info.N_RA_sfn; s++) { // subframe/60kHz slot occasions in period
+ while (((temp_s_map >> sf) & 0x01) == 0)
+ sf++;
+ int sl = sf;
+ for (int i = 0; i < prach_slots_in_sf; i++) { // slot per subframe/60kHz slot
+ int add_slot = i;
+ if (scs == 1 || scs == 3) {
+ sl *= 2;
+ // if only 1 slot per subframe (or 60kHz slot) in case of 30 or 120kHz it's the odd one
+ // as defined in 5.3.2 of 211
+ if (prach_slots_in_sf == 1)
+ add_slot = 1;
+ }
+ int slot = sl + add_slot;
+ if (!is_ul_slot(slot, fs))
+ continue; // valid PRACH occasion only if slot is UL
+ for (int t = 0; t < prach_info.N_t_slot; t++) { // td occasions within a slot
+ // see 5.3.2 in 211
+ int temp_format = prach_info.format >> 8; // B1, B2 or B3 if A1/B1, A2/B2 or A3/B3 formats in tables
+ if (t != prach_info.N_t_slot - 1 || temp_format == 0xff)
+ temp_format = prach_info.format & 0xff;
+ int start_symbol = prach_info.start_symbol + t * prach_info.N_dur;
+ int end_symbol = start_symbol + prach_info.N_dur;
+ // valid occasion only if PRACH symbols are UL symbols in mixed slot
+ if (fs->frame_type == TDD && !check_mixed_slot_prach(fs, slot, start_symbol, end_symbol))
+ continue;
+ for (int f = 0; f < ra->num_fd_occasions; f++) { // fd occasions
+ ra_occasions_period[num_ra_occasions_period] =
+ (prach_occasion_info_t){.slot = slot,
+ .frame_info[0] = prach_info.x,
+ .frame_info[1] = n == 0 ? prach_info.y : prach_info.y2,
+ .start_symbol = start_symbol,
+ .fdm = f,
+ .format = temp_format};
+ LOG_D(NR_MAC,
+ "RA occasion %d: slot %d start symbol %d fd occasion %d\n",
+ num_ra_occasions_period,
+ slot,
+ start_symbol,
+ f);
+ num_ra_occasions_period++;
+ }
+ }
+ }
+ sf++;
+ }
+ }
+
+ int config_period = prach_info.x; // configuration period
+ ra->association_periods = 1;
+ int nb_eq_ssb = mac->ssb_list.nb_tx_ssb;
+ if (ra->ssb_ro_config.ssb_per_ro < 1)
+ nb_eq_ssb *= (int)(1 / ra->ssb_ro_config.ssb_per_ro);
+ int nb_eq_ro = num_ra_occasions_period;
+ if (ra->ssb_ro_config.ssb_per_ro > 1)
+ nb_eq_ro *= (int)ra->ssb_ro_config.ssb_per_ro;
+ while (nb_eq_ssb > nb_eq_ro) {
+ // not enough PRACH occasions -> need to increase association period
+ ra->association_periods <<= 1;
+ AssertFatal(ra->association_periods * config_period <= 16,
+ "Cannot find an association period for %d SSB and %d RO with %f SSB per RO\n",
+ mac->ssb_list.nb_tx_ssb,
+ num_ra_occasions_period,
+ ra->ssb_ro_config.ssb_per_ro);
+ nb_eq_ro <<= 1; // doubling the association period -> doubling ROs
+ }
+ LOG_D(NR_MAC, "PRACH configuration period %d association period %d\n", config_period, ra->association_periods);
+
+ select_prach_occasion(ra, mac->ssb_list.nb_tx_ssb, max_num_occasions, ra_occasions_period, num_ra_occasions_period);
+}
+
+/* TS 38.321 subclause 7.3 - return DELTA_PREAMBLE values in dB */
+static int nr_get_delta_preamble(int scs, int prach_format)
+{
+ int delta = 0;
+ switch (prach_format) {
+ case 0:
+ case 3:
+ delta = 0;
+ break;
+ case 1:
+ delta = -3;
+ break;
+ case 2:
+ delta = -6;
+ break;
+ case 0xa1:
+ case 0xb1:
+ delta = 8 + 3 * scs;
+ break;
+ case 0xa2:
+ case 0xb2:
+ case 0xc2:
+ delta = 5 + 3 * scs;
+ break;
+ case 0xa3:
+ case 0xb3:
+ delta = 3 + 3 * scs;
+ break;
+ case 0xb4:
+ delta = 3 * scs;
+ break;
+ case 0xc0:
+ delta = 11 + 3 * scs;
+ break;
+ default:
+ AssertFatal(false, "Invalid preamble format %x\n", prach_format);
+ }
+ return delta;
+}
+
+static int get_ra_preamble_rx_target_power(RA_config_t *ra, int scs)
+{
+ NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources;
+ int delta_preamble = nr_get_delta_preamble(scs, ra->sched_ro_info.format);
+ int tp = ra->preambleReceivedTargetPower_config + delta_preamble + prach_resources->power_offset_2step;
+ tp += (prach_resources->preamble_power_ramping_cnt - 1) * prach_resources->preamble_power_ramping_step;
+ return tp;
+}
+
+// 38.321 Sections 5.1.3 and .3a
+static void ra_preamble_msga_transmission(RA_config_t *ra, int scs)
+{
+ NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources;
+ if (prach_resources->preamble_tx_counter > 1) {
+ // TODO if the notification of suspending power ramping counter has not been received from lower layers (not implemented)
+ // this happens if the L1 does not transmit PRACH of if the spacial filter changed (UE transmitting in another beam)
+ // TODO if LBT failure indication was not received from lower layers (LBT not implemented)
+ // if SSB or CSI-RS selected is not changed from the selection in the last Random Access Preamble transmission
+ if (!ra->new_ssb)
+ prach_resources->preamble_power_ramping_cnt++;
+ }
+
+
+ prach_resources->ra_preamble_rx_target_power = get_ra_preamble_rx_target_power(ra, scs);
+
+ ra->ra_rnti = nr_get_ra_rnti(ra->sched_ro_info.start_symbol, ra->sched_ro_info.slot, ra->sched_ro_info.fdm, 0);
+ if (ra->ra_type == RA_2_STEP)
+ ra->MsgB_rnti = nr_get_MsgB_rnti(ra->sched_ro_info.start_symbol, ra->sched_ro_info.slot, ra->sched_ro_info.fdm, 0);
+}
+
+// 38.321 Section 5.1.2 Random Access Resource selection
+void ra_resource_selection(NR_UE_MAC_INST_t *mac)
+{
+ configure_ra_preamble(mac);
+ const NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
+ 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, current_UL_BWP->rach_ConfigCommon, ul_mu);
+ configure_prach_occasions(mac, mu);
+ ra_preamble_msga_transmission(&mac->ra, mu);
+}
+
+static int nr_get_RA_window_2Step_v17(long msgB_ResponseWindow)
+{
+ switch (msgB_ResponseWindow) {
+ case NR_RACH_ConfigGenericTwoStepRA_r16__ext1__msgB_ResponseWindow_v1700_sl240:
+ return 240;
+ break;
+ case NR_RACH_ConfigGenericTwoStepRA_r16__ext1__msgB_ResponseWindow_v1700_sl640:
+ return 640;
+ break;
+ case NR_RACH_ConfigGenericTwoStepRA_r16__ext1__msgB_ResponseWindow_v1700_sl960:
+ return 960;
+ break;
+ case NR_RACH_ConfigGenericTwoStepRA_r16__ext1__msgB_ResponseWindow_v1700_sl1280:
+ return 1280;
+ break;
+ case NR_RACH_ConfigGenericTwoStepRA_r16__ext1__msgB_ResponseWindow_v1700_sl1920:
+ return 1920;
+ break;
+ case NR_RACH_ConfigGenericTwoStepRA_r16__ext1__msgB_ResponseWindow_v1700_sl2560:
+ return 2590;
+ default:
+ AssertFatal(false, "illegal msgB_responseWindow value %ld\n", msgB_ResponseWindow);
+ break;
+ }
+ return 0;
+}
+
+static int nr_get_RA_window_2Step_v16(long msgB_ResponseWindow)
+{
+ switch (msgB_ResponseWindow) {
+ case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl1:
+ return 1;
+ break;
+ case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl2:
+ return 2;
+ break;
+ case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl4:
+ return 4;
+ break;
+ case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl8:
+ return 8;
+ break;
+ case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl10:
+ return 10;
+ break;
+ case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl20:
+ return 20;
+ break;
+ case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl40:
+ return 40;
+ break;
+ case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl80:
+ return 80;
+ break;
+ case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl160:
+ return 160;
+ break;
+ case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl320:
+ return 360;
+ break;
+ default:
+ AssertFatal(false, "illegal msgB_responseWindow value %ld\n", msgB_ResponseWindow);
+ break;
+ }
+ return 0;
+}
+
+static int nr_get_RA_window_4Step_v16(long ra_ResponseWindow)
+{
+ switch (ra_ResponseWindow) {
+ case NR_RACH_ConfigGeneric__ext1__ra_ResponseWindow_v1610_sl60:
+ return 60;
+ case NR_RACH_ConfigGeneric__ext1__ra_ResponseWindow_v1610_sl160:
+ return 160;
+ default:
+ AssertFatal(false, "illegal ra_ResponseWindow value %ld\n", ra_ResponseWindow);
+ }
+ return 0;
+}
+
+static int nr_get_RA_window_4Step_v17(long ra_ResponseWindow)
+{
+ switch (ra_ResponseWindow) {
+ case NR_RACH_ConfigGeneric__ext2__ra_ResponseWindow_v1700_sl240:
+ return 240;
+ case NR_RACH_ConfigGeneric__ext2__ra_ResponseWindow_v1700_sl320:
+ return 320;
+ case NR_RACH_ConfigGeneric__ext2__ra_ResponseWindow_v1700_sl640:
+ return 640;
+ case NR_RACH_ConfigGeneric__ext2__ra_ResponseWindow_v1700_sl960:
+ return 960;
+ case NR_RACH_ConfigGeneric__ext2__ra_ResponseWindow_v1700_sl1280:
+ return 1280;
+ case NR_RACH_ConfigGeneric__ext2__ra_ResponseWindow_v1700_sl1920:
+ return 1920;
+ case NR_RACH_ConfigGeneric__ext2__ra_ResponseWindow_v1700_sl2560:
+ return 2590;
+ default:
+ AssertFatal(false, "illegal msgB_responseWindow value %ld\n", ra_ResponseWindow);
+ }
+ return 0;
+}
+
+static int nr_get_RA_window_4Step(long ra_ResponseWindow)
+{
+ switch (ra_ResponseWindow) {
+ case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1:
+ return 1;
+ break;
+ case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2:
+ return 2;
+ break;
+ case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4:
+ return 4;
+ break;
+ case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8:
+ return 8;
+ break;
+ case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10:
+ return 10;
+ break;
+ case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20:
+ return 20;
+ break;
+ case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40:
+ return 40;
+ break;
+ case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80:
+ return 80;
+ break;
+ default:
+ AssertFatal(false, "illegal ra_ResponseWindow value %ld\n", ra_ResponseWindow);
+ break;
+ }
+ return 0;
+}
+
+static void setup_ra_response_window(RA_config_t *ra,
+ int slots_per_frame,
+ NR_NTN_Config_r17_t *ntn_Config_r17,
+ NR_RACH_ConfigGeneric_t *configGeneric,
+ NR_RACH_ConfigGenericTwoStepRA_r16_t *twostep,
+ ntn_timing_advance_componets_t *ntn_ta)
+{
+ int respwind_value = 0;
+ if (ra->ra_type == RA_2_STEP) {
+ long *msgB_ResponseWindow = twostep->msgB_ResponseWindow_r16;
+ if (msgB_ResponseWindow)
+ respwind_value = nr_get_RA_window_2Step_v16(*msgB_ResponseWindow);
+ if (twostep->ext1 && twostep->ext1->msgB_ResponseWindow_v1700) {
+ AssertFatal(msgB_ResponseWindow == NULL,
+ "The network does not configure msgB-ResponseWindow-r16 simultaneously with msgB-ResponseWindow-v1700\n");
+ msgB_ResponseWindow = twostep->ext1->msgB_ResponseWindow_v1700;
+ if (msgB_ResponseWindow)
+ respwind_value = nr_get_RA_window_2Step_v17(*msgB_ResponseWindow);
+ }
+ // The network configures a value lower than or equal to 40ms
+ int slots_40ms = 4 * slots_per_frame;
+ AssertFatal(respwind_value != 0 && respwind_value <= slots_40ms, "Invalid MSGB response window value\n");
+ } else {
+ AssertFatal(ra->ra_type == RA_4_STEP, "Invalid RA type\n");
+ long *response_window = NULL;
+ if (configGeneric->ext1 && configGeneric->ext1->ra_ResponseWindow_v1610)
+ respwind_value = nr_get_RA_window_4Step_v16(*configGeneric->ext1->ra_ResponseWindow_v1610);
+ if (configGeneric->ext2 && configGeneric->ext2->ra_ResponseWindow_v1700) {
+ AssertFatal(response_window == NULL, "ra_ResponseWindow_v1610 and ra_ResponseWindow_v1700 are mutually exclusive\n");
+ respwind_value = nr_get_RA_window_4Step_v17(*configGeneric->ext2->ra_ResponseWindow_v1700);
+ }
+ if (!response_window)
+ respwind_value = nr_get_RA_window_4Step(configGeneric->ra_ResponseWindow);
+ // The network configures a value lower than or equal to 10ms
+ AssertFatal(respwind_value != 0, "Invalid RAR response window value\n");
+ if (respwind_value > slots_per_frame)
+ LOG_E(NR_MAC, "RA-ResponseWindow need to be configured to a value lower than or equal to 10 ms\n");
+ }
+
+ int ta_Common_slots = 0;
+ if (ntn_Config_r17) {
+ const double ta_Common_ms = GET_COMPLETE_TIME_ADVANCE_MS(ntn_ta);
+ ta_Common_slots = (int)ceil(ta_Common_ms * slots_per_frame / 10);
+ }
+
+ ra->response_window_setup_time = respwind_value + ta_Common_slots;
+}
+
+// Random Access procedure initialization as per 5.1.1 and initialization of variables specific
+// to Random Access type as specified in clause 5.1.1a (3GPP TS 38.321 version 16.2.1 Release 16)
+bool init_RA(NR_UE_MAC_INST_t *mac, int frame)
+{
+ RA_config_t *ra = &mac->ra;
+ LOG_D(NR_MAC, "Initialization of RA\n");
+ ra->ra_state = nrRA_GENERATE_PREAMBLE;
+
+ // TODO this piece of code is required to compute MSG3_size that is used by ra_preambles_config function
+ // Not a good implementation, it needs improvements
+ int size_sdu = 0;
+
+ // Concerning the C-RNTI MAC CE,
+ // it has to be included if the UL transmission (Msg3) is not being made for the CCCH logical channel.
+ // Therefore it has been assumed that this event only occurs only when RA is done and it is not SA mode.
+ if (get_softmodem_params()->nsa) {
+
+ uint8_t mac_sdus[34 * 1056];
+ uint16_t sdu_lengths[NB_RB_MAX] = {0};
+ int TBS_bytes = 848;
+ int mac_ce_len = 0;
+ unsigned short post_padding = 1;
+
+ // fill ulsch_buffer with random data
+ for (int i = 0; i < TBS_bytes; i++) {
+ mac_sdus[i] = (unsigned char)(rand()&0xff);
+ }
+ // Sending SDUs with size 1
+ // Initialize elements of sdu_lengths
+ sdu_lengths[0] = TBS_bytes - 3 - post_padding - mac_ce_len;
+ size_sdu += sdu_lengths[0];
+
+ if (size_sdu > 0) {
+ memcpy(ra->cont_res_id, mac_sdus, sizeof(uint8_t) * 6);
+ ra->Msg3_size = size_sdu + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT);
+ }
+
+ } else if (!IS_SA_MODE(get_softmodem_params()))
+ ra->Msg3_size = sizeof(uint16_t) + sizeof(NR_MAC_SUBHEADER_FIXED);
+
+ // Random acces procedure initialization
+ mac->state = UE_PERFORMING_RA;
+ ra->RA_active = true;
+ NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources;
+ fapi_nr_config_request_t *cfg = &mac->phy_config.config_req;
+ // flush MSG3 buffer
+ free_and_zero(ra->Msg3_buffer);
+ // set the PREAMBLE_TRANSMISSION_COUNTER to 1
+ prach_resources->preamble_tx_counter = 1;
+ // set the PREAMBLE_POWER_RAMPING_COUNTER to 1
+ prach_resources->preamble_power_ramping_cnt = 1;
+ // set POWER_OFFSET_2STEP_RA to 0 dB
+ prach_resources->power_offset_2step = 0;
+
+ const NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
+ // perform the BWP operation as specified in clause 5.15
+ // if PRACH occasions are not configured for the active UL BWP
+ if (!current_UL_BWP->rach_ConfigCommon) {
+ // switch the active UL BWP to BWP indicated by initialUplinkBWP
+ current_UL_BWP = get_ul_bwp_structure(mac, 0, false);
+ // if the Serving Cell is an SpCell
+ // switch the active DL BWP to BWP indicated by initialDownlinkBWP
+ mac->current_DL_BWP = get_dl_bwp_structure(mac, 0, false);
+ } else {
+ // if the active DL BWP does not have the same bwp-Id as the active UL BWP
+ if (current_UL_BWP->bwp_id != mac->current_DL_BWP->bwp_id) {
+ // switch the active DL BWP to the DL BWP with the same bwp-Id as the active UL BWP
+ mac->current_DL_BWP = get_dl_bwp_structure(mac, 0, false);
+ }
+ }
+
+ NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = current_UL_BWP->rach_ConfigCommon;
+ AssertFatal(nr_rach_ConfigCommon, "rach-ConfigCommon should be configured here\n");
+ // stop the bwp-InactivityTimer associated with the active DL BWP of this Serving Cell, if running
+ // TODO bwp-InactivityTimer not implemented
+
+ // if the carrier to use for the Random Access procedure is explicitly signalled (always the case for us)
+ // PRACH shall be as specified for QPSK modulated DFT-s-OFDM of equivalent RB allocation (38.101-1)
+ NR_SubcarrierSpacing_t prach_scs;
+ int scs_for_pcmax; // for long prach the UL BWP SCS is used for calculating RA_PCMAX
+ NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &nr_rach_ConfigCommon->rach_ConfigGeneric;
+ if (nr_rach_ConfigCommon->msg1_SubcarrierSpacing) {
+ prach_scs = *nr_rach_ConfigCommon->msg1_SubcarrierSpacing;
+ scs_for_pcmax = prach_scs;
+ } else {
+ const unsigned int index = rach_ConfigGeneric->prach_ConfigurationIndex;
+ const unsigned int unpaired = mac->phy_config.config_req.cell_config.frame_duplex_type;
+ const unsigned int format = get_format0(index, unpaired, mac->frequency_range);
+ prach_scs = get_delta_f_RA_long(format);
+ scs_for_pcmax = mac->current_UL_BWP->scs;
+ }
+ int n_prbs = get_N_RA_RB(prach_scs, current_UL_BWP->scs);
+ int start_prb = rach_ConfigGeneric->msg1_FrequencyStart + current_UL_BWP->BWPStart;
+ prach_resources->Pc_max = nr_get_Pcmax(mac->p_Max,
+ mac->nr_band,
+ mac->frame_structure.frame_type,
+ mac->frequency_range,
+ current_UL_BWP->channel_bandwidth,
+ 2,
+ false,
+ scs_for_pcmax,
+ cfg->carrier_config.dl_grid_size[scs_for_pcmax],
+ true,
+ n_prbs,
+ start_prb);
+
+
+ // TODO if the Random Access procedure was initiated for SI request
+ // and the Random Access Resources for SI request have been explicitly provided by RRC
+
+ // TODO if the Random Access procedure was initiated for SpCell beam failure recovery
+ // and if the contention-free Random Access Resources for beam failure recovery request for 4-step RA type
+ // have been explicitly provided by RRC for the BWP selected for Random Access procedure
+
+ NR_RACH_ConfigCommonTwoStepRA_r16_t *twostep_conf = NULL;
+ NR_RACH_ConfigDedicated_t *rach_Dedicated = ra->rach_ConfigDedicated;
+
+ // if the Random Access procedure is initiated by PDCCH order
+ // and if the ra-PreambleIndex explicitly provided by PDCCH is not 0b000000
+ bool pdcch_order = (ra->pdcch_order.active && ra->pdcch_order.preamble_index != 0xb000000) ? true : false;
+ // or if the Random Access procedure was initiated for reconfiguration with sync and
+ // if the contention-free Random Access Resources for 4-step RA type have been explicitly provided
+ // in rach-ConfigDedicated for the BWP selected for Random Access procedure
+ if ((rach_Dedicated && rach_Dedicated->cfra) || pdcch_order) {
+ LOG_I(MAC, "Initialization of 4-Step CFRA procedure\n");
+ ra->ra_type = RA_4_STEP;
+ ra->cfra = true;
+ } else {
+ bool twostep_cfra = (rach_Dedicated && rach_Dedicated->ext1) ? (rach_Dedicated->ext1->cfra_TwoStep_r16 ? true : false) : false;
+ if (twostep_cfra) {
+ // if the Random Access procedure was initiated for reconfiguration with sync and
+ // if the contention-free Random Access Resources for 2-step RA type have been explicitly provided in rach-ConfigDedicated
+ LOG_I(MAC, "Initialization of 2-Step CFRA procedure\n");
+ ra->ra_type = RA_2_STEP;
+ ra->cfra = true;
+ } else {
+ bool twostep = false;
+ if (current_UL_BWP->msgA_ConfigCommon_r16) {
+ twostep_conf = ¤t_UL_BWP->msgA_ConfigCommon_r16->rach_ConfigCommonTwoStepRA_r16;
+ if (nr_rach_ConfigCommon) {
+ // if the BWP selected for Random Access procedure is configured with both 2- and 4-step RA type Random Access Resources
+ // and the RSRP of the downlink pathloss reference is above msgA-RSRP-Threshold
+ AssertFatal(twostep_conf->msgA_RSRP_Threshold_r16,
+ "msgA_RSRP_Threshold_r16 is mandatory present if both 2-step and 4-step random access types are configured\n");
+ // For thresholds the RSRP value is (IE value β 156) dBm except for the IE 127 in which case the actual value is infinity
+ int rsrp_msga_thr = *twostep_conf->msgA_RSRP_Threshold_r16 - 156;
+ if (*twostep_conf->msgA_RSRP_Threshold_r16 != 127 && mac->ssb_measurements.ssb_rsrp_dBm > rsrp_msga_thr)
+ twostep = true;
+ } else {
+ // if the BWP selected for Random Access procedure is only configured with 2-step RA type Random Access
+ twostep = true;
+ }
+ }
+ if (twostep) {
+ LOG_I(MAC, "Initialization of 2-Step CBRA procedure\n");
+ ra->ra_type = RA_2_STEP;
+ ra->cfra = false;
+ } else {
+ LOG_I(MAC, "Initialization of 4-Step CBRA procedure\n");
+ ra->ra_type = RA_4_STEP;
+ ra->cfra = false;
+ }
+ }
+ }
+
+ // need to ask RRC to send the MSG3 data to transmit if needed (CBRA originating from upper layers)
+ if (!mac->msg3_C_RNTI && ra->cfra == false)
+ nr_mac_rrc_msg3_ind(mac->ue_id, 0, true);
+
+ NR_RACH_ConfigGenericTwoStepRA_r16_t *twostep_generic = twostep_conf ? &twostep_conf->rach_ConfigGenericTwoStepRA_r16 : NULL;
+ if (ra->ra_type == RA_2_STEP && twostep_generic && twostep_generic->msgA_PreamblePowerRampingStep_r16)
+ prach_resources->preamble_power_ramping_step = *twostep_generic->msgA_PreamblePowerRampingStep_r16 << 1;
+ else
+ prach_resources->preamble_power_ramping_step = rach_ConfigGeneric->powerRampingStep << 1;
+
+ ra->scaling_factor_bi = 1;
+
+ if (ra->ra_type == RA_2_STEP && twostep_generic && twostep_generic->msgA_PreambleReceivedTargetPower_r16)
+ ra->preambleReceivedTargetPower_config = *twostep_generic->msgA_PreambleReceivedTargetPower_r16;
+ else
+ ra->preambleReceivedTargetPower_config = rach_ConfigGeneric->preambleReceivedTargetPower;
+
+ if (ra->ra_type == RA_2_STEP && twostep_generic && twostep_generic->preambleTransMax_r16)
+ set_preambleTransMax(ra, *twostep_generic->preambleTransMax_r16);
+ else
+ set_preambleTransMax(ra, rach_ConfigGeneric->preambleTransMax);
+
+ if (ra->ra_type == RA_2_STEP && twostep_generic && twostep_generic->msgA_ZeroCorrelationZoneConfig_r16)
+ ra->zeroCorrelationZoneConfig = *twostep_generic->msgA_ZeroCorrelationZoneConfig_r16;
+ else
+ ra->zeroCorrelationZoneConfig = rach_ConfigGeneric->zeroCorrelationZoneConfig;
+ if (ra->ra_type == RA_2_STEP && twostep_conf && twostep_conf->msgA_RestrictedSetConfig_r16)
+ ra->restricted_set_config = *twostep_conf->msgA_RestrictedSetConfig_r16;
+ else
+ ra->restricted_set_config = nr_rach_ConfigCommon->restrictedSetConfig;
+
+ // TODO msgA-TransMax not implemented
+ // TODO ra-Prioritization not implemented
+
+ if (ra->ra_type == RA_2_STEP && twostep_generic && twostep_generic->msgA_PreambleReceivedTargetPower_r16)
+ ra->preambleRxTargetPower = *twostep_generic->msgA_PreambleReceivedTargetPower_r16;
+ else
+ ra->preambleRxTargetPower = rach_ConfigGeneric->preambleReceivedTargetPower;
+
+ if (ra->ra_type == RA_2_STEP
+ && current_UL_BWP->msgA_ConfigCommon_r16
+ && current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16
+ && current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16->msgA_DeltaPreamble_r16)
+ ra->msg3_deltaPreamble = *current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16->msgA_DeltaPreamble_r16 << 1;
+ else
+ ra->msg3_deltaPreamble = mac->current_UL_BWP->msg3_DeltaPreamble ? *mac->current_UL_BWP->msg3_DeltaPreamble << 1 : 0;
+
+ ra->new_ssb = false;
+
+ if (ra->ra_type == RA_2_STEP && twostep_generic && twostep_generic->msgA_PRACH_ConfigurationIndex_r16)
+ ra->ra_config_index = *twostep_generic->msgA_PRACH_ConfigurationIndex_r16;
+ else {
+ if (rach_ConfigGeneric->ext1 && rach_ConfigGeneric->ext1->prach_ConfigurationIndex_v1610)
+ ra->ra_config_index = *rach_ConfigGeneric->ext1->prach_ConfigurationIndex_v1610;
+ else
+ ra->ra_config_index = rach_ConfigGeneric->prach_ConfigurationIndex;
+ }
+
+ if (ra->ra_type == RA_2_STEP && twostep_generic && twostep_generic->msgA_RO_FDM_r16)
+ ra->num_fd_occasions = 1 << *twostep_generic->msgA_RO_FDM_r16;
+ else
+ ra->num_fd_occasions = 1 << rach_ConfigGeneric->msg1_FDM;
+
+ setup_ra_response_window(ra,
+ mac->frame_structure.numb_slots_frame,
+ mac->sc_info.ntn_Config_r17,
+ rach_ConfigGeneric,
+ twostep_generic,
+ &mac->ntn_ta);
+ return true;
}
void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id)
@@ -663,7 +1134,7 @@ void nr_get_Msg3_MsgA_PUSCH_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS
}
uint8_t *pdu = buf;
- if (ra->msg3_C_RNTI)
+ if (mac->msg3_C_RNTI)
pdu = fill_msg3_crnti_pdu(ra, pdu, mac->crnti);
else
pdu = fill_msg3_pdu_from_rlc(mac, pdu, TBS_max);
@@ -679,253 +1150,6 @@ void nr_get_Msg3_MsgA_PUSCH_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS
memcpy(ra->Msg3_buffer, buf, sizeof(uint8_t) * TBS_max);
}
-/**
- * Function: handles Random Access Preamble Initialization (5.1.1 TS 38.321)
- * handles Random Access Response reception (5.1.4 TS 38.321)
- * Note: In SA mode the Msg3 contains a CCCH SDU, therefore no C-RNTI MAC CE is transmitted.
- *
- * @prach_resources pointer to PRACH resources
- * @prach_pdu pointer to FAPI UL PRACH PDU
- * @mod_id module ID
- * @CC_id CC ID
- * @frame current UL TX frame
- * @gNB_id gNB ID
- * @nr_slot_tx current UL TX slot
- */
-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)
-{
- RA_config_t *ra = &mac->ra;
- NR_RACH_ConfigDedicated_t *rach_ConfigDedicated = ra->rach_ConfigDedicated;
- NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources;
-
- // Delay init RA procedure to allow the convergence of the IIR filter on PRACH noise measurements at gNB side
- if (ra->ra_state == nrRA_UE_IDLE) {
- LOG_D(NR_MAC,
- "ra->ra_state %d frame %d mac->first_sync_frame %d xxx %d",
- ra->ra_state,
- frame,
- mac->first_sync_frame,
- ((MAX_FRAME_NUMBER + frame - mac->first_sync_frame) % MAX_FRAME_NUMBER) > 10);
- if ((mac->first_sync_frame > -1 || get_softmodem_params()->do_ra || get_softmodem_params()->nsa)
- && ((MAX_FRAME_NUMBER + frame - mac->first_sync_frame) % MAX_FRAME_NUMBER) > 150) {
- ra->ra_state = nrRA_GENERATE_PREAMBLE;
- LOG_D(NR_MAC, "PRACH Condition met: ra state %d, frame %d, sync_frame %d\n", ra->ra_state, frame, mac->first_sync_frame);
- } else {
- LOG_D(NR_MAC,
- "PRACH Condition not met: ra state %d, frame %d, sync_frame %d\n",
- ra->ra_state,
- frame,
- mac->first_sync_frame);
- return;
- }
- }
-
- LOG_D(NR_MAC, "[UE %d][%d.%d]: ra_state %d, RA_active %d\n", mac->ue_id, frame, nr_slot_tx, ra->ra_state, ra->RA_active);
-
- if (ra->ra_state > nrRA_UE_IDLE && ra->ra_state < nrRA_SUCCEEDED) {
- if (!ra->RA_active) {
- NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon;
- NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric;
- init_RA(mac, &ra->prach_resources, setup, rach_ConfigGeneric, ra->rach_ConfigDedicated);
-
- // TODO this piece of code is required to compute MSG3_size that is used by ra_preambles_config function
- // Not a good implementation, it needs improvements
- int size_sdu = 0;
-
- // Concerning the C-RNTI MAC CE, it has to be included if the UL transmission (Msg3) is not being made for the CCCH logical channel.
- // Therefore it has been assumed that this event only occurs only when RA is done and it is not SA mode.
- if (get_softmodem_params()->nsa) {
-
- uint8_t mac_sdus[34*1056];
- uint16_t sdu_lengths[NB_RB_MAX] = {0};
- int TBS_bytes = 848;
- int mac_ce_len = 0;
- unsigned short post_padding = 1;
-
- // fill ulsch_buffer with random data
- for (int i = 0; i < TBS_bytes; i++){
- mac_sdus[i] = (unsigned char) (rand()&0xff);
- }
- //Sending SDUs with size 1
- //Initialize elements of sdu_lengths
- sdu_lengths[0] = TBS_bytes - 3 - post_padding - mac_ce_len;
- size_sdu += sdu_lengths[0];
-
- if (size_sdu > 0) {
- memcpy(ra->cont_res_id, mac_sdus, sizeof(uint8_t) * 6);
- ra->Msg3_size = size_sdu + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT);
- }
-
- } else if (!IS_SA_MODE(get_softmodem_params())) {
- uint8_t temp_pdu[16] = {0};
- size_sdu = nr_write_ce_msg3_pdu(temp_pdu, mac, mac->crnti, temp_pdu + sizeof(temp_pdu));
- ra->Msg3_size = size_sdu;
- }
- } else if (ra->RA_window_cnt != -1) { // RACH is active
-
- LOG_D(MAC, "[%d.%d] RA is active: RA window count %d, RA backoff count %d\n", frame, nr_slot_tx, ra->RA_window_cnt, ra->RA_backoff_cnt);
-
- if (ra->RA_BI_found){
- prach_resources->RA_PREAMBLE_BACKOFF = prach_resources->RA_SCALING_FACTOR_BI * ra->RA_backoff_indicator;
- } else {
- prach_resources->RA_PREAMBLE_BACKOFF = 0;
- }
-
- if (ra->RA_window_cnt >= 0 && ra->RA_RAPID_found == 1) {
-
- if(ra->cfra) {
- // Reset RA_active flag: it disables Msg3 retransmission (8.3 of TS 38.213)
- nr_ra_succeeded(mac, gNB_id, frame, nr_slot_tx);
- }
-
- } else if (ra->RA_window_cnt == 0 && !ra->RA_RAPID_found && ra->ra_state != nrRA_WAIT_MSGB) {
- LOG_W(MAC, "[UE %d][%d:%d] RAR reception failed \n", mac->ue_id, frame, nr_slot_tx);
-
- nr_ra_failed(mac, CC_id, prach_resources, frame, nr_slot_tx);
-
- } else if (ra->RA_window_cnt > 0) {
-
- LOG_D(MAC, "[UE %d][%d.%d]: RAR not received yet (RA window count %d) \n", mac->ue_id, frame, nr_slot_tx, ra->RA_window_cnt);
-
- // Fill in preamble and PRACH resources
- ra->RA_window_cnt--;
- if (ra->ra_state == nrRA_GENERATE_PREAMBLE) {
- nr_get_prach_resources(mac, CC_id, gNB_id, prach_resources, rach_ConfigDedicated);
- }
- } else if (ra->RA_backoff_cnt > 0) {
-
- LOG_D(MAC, "[UE %d][%d.%d]: RAR not received yet (RA backoff count %d) \n", mac->ue_id, frame, nr_slot_tx, ra->RA_backoff_cnt);
-
- ra->RA_backoff_cnt--;
-
- if ((ra->RA_backoff_cnt > 0 && ra->ra_state == nrRA_GENERATE_PREAMBLE) || ra->RA_backoff_cnt == 0) {
- nr_get_prach_resources(mac, CC_id, gNB_id, prach_resources, rach_ConfigDedicated);
- }
- }
- }
- }
-
- if (nr_timer_is_active(&ra->contention_resolution_timer)) {
- nr_ue_contention_resolution(mac, CC_id, frame, nr_slot_tx, prach_resources);
- }
-}
-
-int16_t nr_get_RA_window_2Step(const NR_MsgA_ConfigCommon_r16_t *msgA_ConfigCommon_r16)
-{
- int16_t ra_ResponseWindow = *msgA_ConfigCommon_r16->rach_ConfigCommonTwoStepRA_r16
- .rach_ConfigGenericTwoStepRA_r16.msgB_ResponseWindow_r16;
-
- switch (ra_ResponseWindow) {
- case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl1:
- return 1;
- break;
- case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl2:
- return 2;
- break;
- case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl4:
- return 4;
- break;
- case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl8:
- return 8;
- break;
- case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl10:
- return 10;
- break;
- case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl20:
- return 20;
- break;
- case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl40:
- return 40;
- break;
- case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl80:
- return 80;
- break;
- case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl160:
- return 160;
- break;
- case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl320:
- return 360;
- break;
- default:
- AssertFatal(false, "illegal msgB_responseWindow value %d\n", ra_ResponseWindow);
- break;
- }
- return 0;
-}
-
-int16_t nr_get_RA_window_4Step(const NR_RACH_ConfigCommon_t *rach_ConfigCommon)
-{
- int16_t ra_ResponseWindow = rach_ConfigCommon->rach_ConfigGeneric.ra_ResponseWindow;
-
- switch (ra_ResponseWindow) {
- case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1:
- return 1;
- break;
- case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2:
- return 2;
- break;
- case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4:
- return 4;
- break;
- case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8:
- return 8;
- break;
- case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10:
- return 10;
- break;
- case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20:
- return 20;
- break;
- case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40:
- return 40;
- break;
- case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80:
- return 80;
- break;
- default:
- AssertFatal(false, "illegal ra_ResponseWindow value %d\n", ra_ResponseWindow);
- break;
- }
- return 0;
-}
-
-void nr_get_RA_window(NR_UE_MAC_INST_t *mac)
-{
- RA_config_t *ra = &mac->ra;
- NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon;
- AssertFatal(&setup->rach_ConfigGeneric != NULL, "In %s: FATAL! rach_ConfigGeneric is NULL...\n", __FUNCTION__);
- const double ta_Common_ms = GET_COMPLETE_TIME_ADVANCE_MS(&mac->ntn_ta);
- int slots_per_frame = mac->frame_structure.numb_slots_frame;
- const int slots_per_ms = slots_per_frame / 10;
- const int ra_Offset_slots = ra->RA_offset * slots_per_frame;
- const int ta_Common_slots = (int)ceil(ta_Common_ms * slots_per_ms);
-
- ra->RA_window_cnt = ra_Offset_slots + ta_Common_slots; // taking into account the 2 frames gap introduced by OAI gNB
-
- ra->RA_window_cnt += ra->ra_type == RA_2_STEP ? nr_get_RA_window_2Step(mac->current_UL_BWP->msgA_ConfigCommon_r16)
- : nr_get_RA_window_4Step(mac->current_UL_BWP->rach_ConfigCommon);
-}
-
-////////////////////////////////////////////////////////////////////////////
-/////////* Random Access Contention Resolution (5.1.35 TS 38.321) */////////
-////////////////////////////////////////////////////////////////////////////
-// Handling contention resolution timer
-// WIP todo:
-// - beam failure recovery
-// - RA completed
-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)
-{
- RA_config_t *ra = &mac->ra;
-
- if (nr_timer_expired(&ra->contention_resolution_timer)) {
- ra->t_crnti = 0;
- nr_timer_stop(&ra->contention_resolution_timer);
- // Signal PHY to quit RA procedure
- LOG_E(MAC, "[UE %d] 4-Step CBRA: Contention resolution timer has expired, RA procedure has failed...\n", mac->ue_id);
- nr_ra_failed(mac, cc_id, prach_resources, frame, slot);
- }
-}
-
// Handlig successful RA completion @ MAC layer
// according to section 5 of 3GPP TS 38.321 version 16.2.1 Release 16
// todo:
@@ -936,90 +1160,95 @@ void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame
if (ra->cfra) {
LOG_I(MAC, "[UE %d][%d.%d][RAPROC] RA procedure succeeded. CFRA: RAR successfully received.\n", mac->ue_id, frame, slot);
- ra->RA_window_cnt = -1;
- } else if (ra->ra_type == RA_2_STEP) {
- LOG_A(MAC,
- "[UE %d][%d.%d][RAPROC] 2-Step RA procedure succeeded. CBRA: Contention Resolution is successful.\n",
- mac->ue_id,
- frame,
- slot);
- mac->crnti = ra->t_crnti;
- ra->t_crnti = 0;
- LOG_D(MAC, "[UE %d][%d.%d] CBRA: cleared response window timer...\n", mac->ue_id, frame, slot);
} else {
LOG_A(MAC,
- "[UE %d][%d.%d][RAPROC] 4-Step RA procedure succeeded. CBRA: Contention Resolution is successful.\n",
- mac->ue_id,
- frame,
- slot);
- nr_timer_stop(&ra->contention_resolution_timer);
- mac->crnti = ra->t_crnti;
- ra->t_crnti = 0;
- LOG_D(MAC, "[UE %d][%d.%d] CBRA: cleared contention resolution timer...\n", mac->ue_id, frame, slot);
- }
-
- LOG_D(MAC, "[UE %d] clearing RA_active flag...\n", mac->ue_id);
- ra->RA_active = false;
- ra->msg3_C_RNTI = false;
- ra->ra_state = nrRA_SUCCEEDED;
- mac->state = UE_CONNECTED;
- free_and_zero(ra->Msg3_buffer);
- nr_mac_rrc_ra_ind(mac->ue_id, frame, true);
-}
-
-// Handling failure of RA procedure @ MAC layer
-// according to section 5 of 3GPP TS 38.321 version 16.2.1 Release 16
-// todo:
-// - complete handling of received contention-based RA preamble
-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)
-{
- RA_config_t *ra = &mac->ra;
- // Random seed generation
- unsigned int seed;
-
- if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) {
- // Overwrite seed with non-random seed for IQ player/recorder
- seed = 1;
- } else {
- // & to truncate the int64_t and keep only the LSB bits, up to sizeof(int)
- seed = (unsigned int) (rdtsc_oai() & ~0);
- }
-
- ra->first_Msg3 = true;
- ra->ra_PreambleIndex = -1;
- ra->ra_state = nrRA_UE_IDLE;
-
- prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER++;
-
- // when the Contention Resolution is considered not successful
- // stop timeAlignmentTimer
- nr_timer_stop(&mac->time_alignment_timer);
-
- if (prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER == ra->preambleTransMax + 1) {
-
- LOG_D(NR_MAC,
- "[UE %d][%d.%d] Maximum number of RACH attempts (%d) reached, selecting backoff time...\n",
+ "[UE %d][%d.%d][RAPROC] %d-Step RA procedure succeeded. CBRA: Contention Resolution is successful.\n",
mac->ue_id,
frame,
slot,
- ra->preambleTransMax);
+ ra->ra_type == RA_2_STEP ? 2 : 4);
+ mac->crnti = ra->t_crnti;
+ ra->t_crnti = 0;
+ nr_timer_stop(&ra->contention_resolution_timer);
+ }
- ra->RA_backoff_cnt = rand_r(&seed) % (prach_resources->RA_PREAMBLE_BACKOFF + 1);
- prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER = 1;
- prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP += 2; // 2 dB increment
- prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(mac, prach_resources, CC_id);
+ ra->RA_active = false;
+ mac->msg3_C_RNTI = false;
+ ra->ra_state = nrRA_SUCCEEDED;
+ mac->state = UE_CONNECTED;
+ free_and_zero(ra->Msg3_buffer);
+ nr_mac_rrc_ra_ind(mac->ue_id, true);
+}
+void nr_ra_backoff_setting(RA_config_t *ra)
+{
+ // select a random backoff time according to a uniform distribution
+ // between 0 and the PREAMBLE_BACKOFF
+ uint32_t seed = (unsigned int)(rdtsc_oai() & ~0);
+ uint32_t random_backoff = ra->RA_backoff_limit ? rand_r(&seed) % ra->RA_backoff_limit : 0; // in slots
+ nr_timer_setup(&ra->RA_backoff_timer, random_backoff, 1);
+ nr_timer_start(&ra->RA_backoff_timer);
+}
+
+void nr_ra_contention_resolution_failed(NR_UE_MAC_INST_t *mac)
+{
+ LOG_W(MAC, "[UE %d] Contention resolution failed\n", mac->ue_id);
+ RA_config_t *ra = &mac->ra;
+ // discard the TEMPORARY_C-RNTI
+ ra->t_crnti = 0;
+ // flush MSG3 buffer
+ free_and_zero(ra->Msg3_buffer);
+ nr_mac_rrc_msg3_ind(mac->ue_id, 0, true);
+ NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources;
+ prach_resources->preamble_tx_counter++;
+ if (prach_resources->preamble_tx_counter == ra->preambleTransMax + 1) {
+ // indicate a Random Access problem to upper layers
+ nr_mac_rrc_ra_ind(mac->ue_id, false);
} else {
- nr_get_RA_window(mac);
+ // TODO handle msgA-TransMax (go back to 4-step if the threshold is reached)
+ // starting backoff time
+ nr_ra_backoff_setting(ra);
}
}
-void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac)
+void nr_rar_not_successful(NR_UE_MAC_INST_t *mac)
+{
+ LOG_W(MAC, "[UE %d] RAR reception failed\n", mac->ue_id);
+ RA_config_t *ra = &mac->ra;
+ NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources;
+ prach_resources->preamble_tx_counter++;
+ bool ra_completed = false;
+ if (prach_resources->preamble_tx_counter == ra->preambleTransMax + 1) {
+ // if the Random Access Preamble is transmitted on the SpCell
+ // TODO to be verified, this means SA if I'm not mistaken
+ if (IS_SA_MODE(get_softmodem_params())) {
+ // indicate a Random Access problem to upper layers
+ nr_mac_rrc_ra_ind(mac->ue_id, false);
+ } else {
+ // if the Random Access Preamble is transmitted on an SCell:
+ // consider the Random Access procedure unsuccessfully completed.
+ ra_completed = true;
+ ra->ra_state = nrRA_UE_IDLE;
+ }
+ }
+ if (!ra_completed) {
+ nr_ra_backoff_setting(ra);
+ }
+}
+
+void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac, dci_pdu_rel15_t *pdcch_order)
{
LOG_W(NR_MAC, "Triggering new RA procedure for UE with RNTI %x\n", mac->crnti);
mac->state = UE_PERFORMING_RA;
reset_ra(mac, false);
- mac->ra.msg3_C_RNTI = true;
+ RA_config_t *ra = &mac->ra;
+ mac->msg3_C_RNTI = true;
+ if (pdcch_order) {
+ ra->pdcch_order.active = true;
+ ra->pdcch_order.preamble_index = pdcch_order->ra_preamble_index;
+ ra->pdcch_order.ssb_index = pdcch_order->ss_pbch_index;
+ ra->pdcch_order.prach_mask = pdcch_order->prach_mask_index;
+ }
}
void prepare_msg4_msgb_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack)
@@ -1048,16 +1277,6 @@ void prepare_msg4_msgb_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack)
release_ul_config(pdu, false);
}
-void free_rach_structures(NR_UE_MAC_INST_t *nr_mac, int bwp_id)
-{
- for (int j = 0; j < MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD; j++)
- for (int k = 0; k < MAX_NB_FRAME_IN_PRACH_CONF_PERIOD; k++)
- for (int l = 0; l < MAX_NB_SLOT_IN_FRAME; l++)
- free(nr_mac->prach_assoc_pattern[bwp_id].prach_conf_period_list[j].prach_occasion_slot_map[k][l].prach_occasion);
-
- free(nr_mac->ssb_list[bwp_id].tx_ssb);
-}
-
void reset_ra(NR_UE_MAC_INST_t *nr_mac, bool free_prach)
{
RA_config_t *ra = &nr_mac->ra;
@@ -1067,7 +1286,4 @@ void reset_ra(NR_UE_MAC_INST_t *nr_mac, bool free_prach)
if (!free_prach)
return;
-
- for (int i = 0; i < MAX_NUM_BWP_UE; i++)
- free_rach_structures(nr_mac, i);
}
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c
index aeeab40b74..3817e06759 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c
@@ -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_;
}
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c
index 7083b4a141..9db464f015 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c
@@ -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;
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
index c150cc29cd..83bbcadbe5 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
@@ -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;
}
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
index 5300c9ed1f..edd3bc1db7 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
@@ -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_ronb_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_ronb_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
}
@@ -3382,7 +2847,6 @@ static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UE_MA
fapi_nr_ta_command_pdu *ta = &dl_config->dl_config_list[dl_config->number_pdus].ta_command_pdu;
ta->ta_frame = ul_time_alignment->frame;
ta->ta_slot = ul_time_alignment->slot;
- ta->ta_offset = mac->n_ta_offset;
ta->is_rar = ul_time_alignment->ta_apply == rar_ta;
ta->ta_command = ul_time_alignment->ta_command;
dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_CONFIG_TA_COMMAND;
diff --git a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_power_procedures.cpp b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_power_procedures.cpp
index bcbec989c2..7dc0b43ec3 100644
--- a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_power_procedures.cpp
+++ b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_power_procedures.cpp
@@ -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,
diff --git a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp
index f5a402c467..25ea5edcd0 100644
--- a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp
+++ b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp
@@ -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
#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);
diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c
index d7b9b5e129..0abe35b80d 100644
--- a/openair2/LAYER2/NR_MAC_gNB/config.c
+++ b/openair2/LAYER2/NR_MAC_gNB/config.c
@@ -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);
}
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
index cc0317cf51..9bf8b739bf 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
@@ -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,13 +540,12 @@ 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);
AssertFatal(slotP + total_prach_slots - 1 < slots_frame, "PRACH cannot extend across frames\n");
} else {
- // TODO: to be revisited for format B4 (also extends beyond current slot for FR1 30kHz SCS and FR2)
- AssertFatal((format != 0xb4) || (mu_pusch < 1), "Format B4 not supported for this PUSCH SCS\n");
total_prach_slots = 1;
}
// reserve PRBs occupied by PRACH in all PRACH slot.
@@ -597,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);
}
@@ -1413,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);
diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
index 3f992f0409..8b1bb3ec5c 100644
--- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
+++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
@@ -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
diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c
index 9e7310cf40..64de7b4560 100644
--- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c
+++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c
@@ -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);
}
diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h
index e6a4bfa80b..2bbd97db84 100644
--- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h
+++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h
@@ -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
diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c
index f6dead1213..a6c2ae1c9c 100644
--- a/openair2/RRC/NR/nr_rrc_config.c
+++ b/openair2/RRC/NR/nr_rrc_config.c
@@ -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;
diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c
index 7fd34ff91c..3bfe1d34e0 100644
--- a/openair2/RRC/NR_UE/L2_interface_ue.c
+++ b/openair2/RRC/NR_UE/L2_interface_ue.c
@@ -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);
}
diff --git a/openair2/RRC/NR_UE/L2_interface_ue.h b/openair2/RRC/NR_UE/L2_interface_ue.h
index 05888cbc0e..f394e5e333 100644
--- a/openair2/RRC/NR_UE/L2_interface_ue.h
+++ b/openair2/RRC/NR_UE/L2_interface_ue.h
@@ -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
diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c
index f61ce49494..d0d1273776 100644
--- a/openair2/RRC/NR_UE/rrc_UE.c
+++ b/openair2/RRC/NR_UE/rrc_UE.c
@@ -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;