Merge branch 'integration_2025_w11' into 'develop'

Integration: `2025.w11`

Closes #848

See merge request oai/openairinterface5g!3309

* !3306 Add a new CI label: nrUE
* !3303 remove wrong assertion for B4 PRACH format
* !3296 fix(nrLDPC_decoder): fix numIter increment
* !3150 Rework of NR UE RA procedures
* !3305 CI: Fix timeout for OC Deployments
* !3307 Add CI UE test for RA with C-RNTI
* !3271 Handle changing N_TA_offset correctly
* !3313 Small fix for jenkins message formatting
This commit is contained in:
Jaroslava Fiedlerova
2025-03-18 15:21:56 +00:00
52 changed files with 1988 additions and 2516 deletions
+2 -2
View File
@@ -65,8 +65,8 @@ pipeline {
message += " - ~BUILD-ONLY (execute only build stages)\n" message += " - ~BUILD-ONLY (execute only build stages)\n"
message += " - ~4G-LTE (perform 4G tests)\n" message += " - ~4G-LTE (perform 4G tests)\n"
message += " - ~5G-NR (perform 5G tests)\n" message += " - ~5G-NR (perform 5G tests)\n"
message += " - ~CI (perform both 4G and 5G tests)\n\n" message += " - ~CI (perform both 4G and 5G tests)\n"
message += " - ~nrUE (perform only 5G-UE related tests including physims excluding LDPC 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" message += "Not performing CI due to lack of labels"
addGitLabMRComment comment: message addGitLabMRComment comment: message
error('Not performing CI due to lack of labels') error('Not performing CI due to lack of labels')
+7 -7
View File
@@ -72,8 +72,8 @@ def OC_deploy_CN(cmd, ocUserName, ocPassword, ocNamespace, path):
succeeded = OC_login(cmd, ocUserName, ocPassword, ocNamespace) succeeded = OC_login(cmd, ocUserName, ocPassword, ocNamespace)
if not succeeded: if not succeeded:
return False, CONST.OC_LOGIN_FAIL return False, CONST.OC_LOGIN_FAIL
cmd.run('helm uninstall oai5gcn --wait --timeout 60s') cmd.run(f'helm list -aq -n {ocNamespace} | xargs -r helm uninstall -n {ocNamespace} --wait')
ret = cmd.run(f'helm install --wait --timeout 120s oai5gcn {path}/ci-scripts/charts/oai-5g-basic/.') ret = cmd.run(f'helm install --wait oai5gcn {path}/ci-scripts/charts/oai-5g-basic/.')
if ret.returncode != 0: if ret.returncode != 0:
logging.error('OC OAI CN5G: Deployment failed') logging.error('OC OAI CN5G: Deployment failed')
OC_logout(cmd) 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'oc logs -f {podName} {ci} &> {path}/logs/{ii}.log &')
cmd.run(f'cd {path}/logs && zip -r -qq test_logs_CN.zip *.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') 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: if ret.returncode != 0:
logging.error('OC OAI CN5G: Undeployment failed') 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) OC_logout(cmd)
return False, CONST.OC_PROJECT_FAIL return False, CONST.OC_PROJECT_FAIL
report = cmd.run('oc get pods') report = cmd.run('oc get pods')
@@ -330,7 +330,7 @@ class Cluster:
self._recreate_bc('ran-base', baseTag, 'openshift/ran-base-bc.yaml') self._recreate_bc('ran-base', baseTag, 'openshift/ran-base-bc.yaml')
ranbase_job = self._start_build('ran-base') ranbase_job = self._start_build('ran-base')
attemptedImages += ['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') 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 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 # recover logs by mounting image
@@ -392,7 +392,7 @@ class Cluster:
gnb_aw2s_job = self._start_build('oai-gnb-aw2s') gnb_aw2s_job = self._start_build('oai-gnb-aw2s')
attemptedImages += ['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') if not wait: logging.error('error during build of eNB/gNB')
status = status and wait status = status and wait
# recover logs # recover logs
@@ -421,7 +421,7 @@ class Cluster:
nrue_job = self._start_build('oai-nr-ue') nrue_job = self._start_build('oai-nr-ue')
attemptedImages += ['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') if not wait: logging.error('error during build of nr-cuup/lteUE/nrUE')
status = status and wait status = status and wait
# recover logs # recover logs
@@ -34,6 +34,9 @@
020002 020002
030001 030001
030002 030002
040001
000004
020002
100001 100001
222222 222222
</TestCaseRequestedList> </TestCaseRequestedList>
@@ -76,6 +79,12 @@
<nodes>cacofonix</nodes> <nodes>cacofonix</nodes>
</testCase> </testCase>
<testCase id="000004">
<class>IdleSleep</class>
<desc>Sleep</desc>
<idle_sleep_time_in_sec>5</idle_sleep_time_in_sec>
</testCase>
<testCase id="020001"> <testCase id="020001">
<class>Ping</class> <class>Ping</class>
<desc>Ping ext-dn from NR-UE</desc> <desc>Ping ext-dn from NR-UE</desc>
@@ -118,6 +127,14 @@
<iperf_bitrate_threshold>90</iperf_bitrate_threshold> <iperf_bitrate_threshold>90</iperf_bitrate_threshold>
</testCase> </testCase>
<testCase id="040001">
<class>Custom_Command</class>
<desc>Force Msg3 C-RNTI RA</desc>
<node>cacofonix</node>
<command>echo ciUE force_crnti_ra | nc 192.168.71.150 8091</command>
<command_fail>yes</command_fail>
</testCase>
<testCase id="100001"> <testCase id="100001">
<class>Undeploy_Object</class> <class>Undeploy_Object</class>
<always_exec>true</always_exec> <always_exec>true</always_exec>
@@ -109,7 +109,10 @@ services:
- NET_ADMIN # for interface bringup - NET_ADMIN # for interface bringup
- NET_RAW # for ping - NET_RAW # for ping
environment: 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: depends_on:
- oai-gnb - oai-gnb
networks: networks:
+9 -2
View File
@@ -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) void nr_timer_start(NR_timer_t *timer)
{ {
timer->active = true; timer->active = true;
timer->suspended = false;
timer->counter = 0; timer->counter = 0;
} }
void nr_timer_stop(NR_timer_t *timer) void nr_timer_stop(NR_timer_t *timer)
{ {
timer->active = false; timer->active = false;
timer->suspended = false;
timer->counter = 0; 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) bool nr_timer_is_active(const NR_timer_t *timer)
{ {
return timer->active; return timer->active;
@@ -1399,7 +1406,7 @@ bool nr_timer_tick(NR_timer_t *timer)
bool expired = false; bool expired = false;
if (timer->active) { if (timer->active) {
timer->counter += timer->step; 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; return false;
expired = nr_timer_expired(timer); expired = nr_timer_expired(timer);
if (expired) if (expired)
@@ -1410,7 +1417,7 @@ bool nr_timer_tick(NR_timer_t *timer)
bool nr_timer_expired(const 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 false;
return timer->counter >= timer->target; return timer->counter >= timer->target;
} }
+7
View File
@@ -156,6 +156,7 @@ typedef struct {
typedef struct { typedef struct {
bool active; bool active;
bool suspended;
uint32_t counter; uint32_t counter;
uint32_t target; uint32_t target;
uint32_t step; uint32_t step;
@@ -171,6 +172,12 @@ void nr_timer_start(NR_timer_t *timer);
* @param timer Timer to stopped * @param timer Timer to stopped
*/ */
void nr_timer_stop(NR_timer_t *timer); 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 * @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 * @param timer Timer to be handled
+9
View File
@@ -94,11 +94,20 @@ int force_RRC_IDLE(char *buf, int debug, telnet_printfunc_t prnt)
return 0; 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 */ /* Telnet shell command definitions */
static telnetshell_cmddef_t cicmds[] = { static telnetshell_cmddef_t cicmds[] = {
{"sync_state", "[UE_ID(int,opt)]", get_sync_state}, {"sync_state", "[UE_ID(int,opt)]", get_sync_state},
{"force_rlf", "", force_rlf}, {"force_rlf", "", force_rlf},
{"force_RRC_IDLE", "", force_RRC_IDLE}, {"force_RRC_IDLE", "", force_RRC_IDLE},
{"force_crnti_ra", "", force_crnti_ra},
{"", "", NULL}, {"", "", NULL},
}; };
+35 -6
View File
@@ -147,6 +147,24 @@ static void *nrL1_UE_stats_thread(void *param)
return NULL; 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) void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id)
{ {
int nb_connected_gNB = 1; 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 // intialize transport
init_nr_ue_transport(ue); init_nr_ue_transport(ue);
// init N_TA offset ue->ta_frame = -1;
init_N_TA_offset(ue); ue->ta_slot = -1;
} }
void init_nrUE_standalone_thread(int ue_idx) void init_nrUE_standalone_thread(int ue_idx)
@@ -519,7 +537,7 @@ void processSlotTX(void *arg)
bool sl_tx_action = false; bool sl_tx_action = false;
if (UE->if_inst) 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 (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) { 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; bool dl_slot = false;
if (proc->rx_slot_type == NR_DOWNLINK_SLOT || proc->rx_slot_type == NR_MIXED_SLOT) { if (proc->rx_slot_type == NR_DOWNLINK_SLOT || proc->rx_slot_type == NR_MIXED_SLOT) {
dl_slot = true; dl_slot = true;
@@ -867,6 +888,7 @@ void *UE_thread(void *arg)
initNotifiedFIFO_nothreadSafe(&freeBlocks); initNotifiedFIFO_nothreadSafe(&freeBlocks);
int timing_advance = UE->timing_advance; 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); NR_UE_MAC_INST_t *mac = get_mac_inst(UE->Mod_id);
bool syncRunning = false; bool syncRunning = false;
@@ -1095,9 +1117,16 @@ void *UE_thread(void *arg)
// but use current UE->timing_advance value to compute writeBlockSize // 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; 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) { int new_timing_advance = UE->timing_advance;
writeBlockSize -= UE->timing_advance - timing_advance; if (new_timing_advance != timing_advance) {
timing_advance = UE->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) if (curMsg.proc.nr_slot_tx == 0)
+4
View File
@@ -465,6 +465,10 @@ int main(int argc, char **argv)
get_channel_model_mode(uniqCfg); 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) if (!get_softmodem_params()->nsa && get_softmodem_params()->emulate_l1)
start_oai_nrue_threads(); start_oai_nrue_threads();
@@ -551,7 +551,6 @@ typedef struct {
int ta_frame; int ta_frame;
int ta_slot; int ta_slot;
int ta_command; int ta_command;
int ta_offset;
bool is_rar; bool is_rar;
} fapi_nr_ta_command_pdu; } 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 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 uint8_t frame_duplex_type;//Frame duplex type Value: 0 = FDD 1 = TDD
uint32_t N_TA_offset;
} fapi_nr_cell_config_t; } fapi_nr_cell_config_t;
typedef struct typedef struct
@@ -218,7 +218,7 @@ static void nr_process_decode_segment(void *arg)
int decodeIterations = int decodeIterations =
LDPCdecoder(p_decoderParms, 0, 0, 0, l, llrProcBuf, p_procTime, rdata->abort_decode); 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); memcpy(rdata->c, llrProcBuf, K >> 3);
*rdata->decodeSuccess = true; *rdata->decodeSuccess = true;
} else { } else {
@@ -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++) { for (uint32_t job = 0; job < num_threads_prepare; job++) {
args_fpga_decode_prepare_t *args = &arr[job]; args_fpga_decode_prepare_t *args = &arr[job];
if (args->no_iteration_ldpc > TB_params->max_ldpc_iterations) if (args->no_iteration_ldpc >= TB_params->max_ldpc_iterations)
no_iteration_ldpc = TB_params->max_ldpc_iterations + 1; no_iteration_ldpc = TB_params->max_ldpc_iterations;
} }
// launch decode with FPGA // 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 #ifdef DEBUG_CRC
LOG_I(PHY, "segment %d CRC NOK\n", r); LOG_I(PHY, "segment %d CRC NOK\n", r);
#endif #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++) { for (int i = 0; i < out_CBoffset; i++) {
segment_params->c[i] = multi_outdata[i + r * out_CBoffset]; 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) { if (segment_params->decodeSuccess) {
*TB_params->processedSegments = *TB_params->processedSegments + 1; *TB_params->processedSegments = *TB_params->processedSegments + 1;
} }
@@ -396,7 +396,7 @@ void nr_ulsch_FPGA_decoding_prepare_blocks(void *args)
== -1) { == -1) {
stop_meas(&segment_params->ts_rate_unmatch); stop_meas(&segment_params->ts_rate_unmatch);
LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n"); 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; arguments->no_iteration_ldpc = no_iteration_ldpc;
return; return;
} else { } else {
@@ -187,7 +187,7 @@ int32_t LDPCdecoder(t_nrLDPC_dec_params* p_decParams,
// Launch LDPC decoder core for one segment // Launch LDPC decoder core for one segment
int numIter = nrLDPC_decoder_core(p_llr, p_out, numLLR, p_lut, p_decParams, p_profiler, ab); 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); LOG_D(PHY, "set abort: %d, %d\n", numIter, p_decParams->numMaxIter);
set_abort(ab, true); set_abort(ab, true);
} }
@@ -549,13 +549,11 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
// estimated after only one iteration // estimated after only one iteration
// First iteration finished // First iteration finished
uint32_t numIter = 1; uint32_t numIter = 0;
int32_t pcRes = 1; // pcRes is 0 if the ldpc decoder is succesful int32_t pcRes = 1; // pcRes is 0 if the ldpc decoder is succesful
while ((numIter <= numMaxIter) && (pcRes != 0)) { while ((numIter < numMaxIter) && (pcRes != 0)) {
// Increase iteration counter
numIter++;
if (check_abort(ab)) { if (check_abort(ab)) {
numIter = numMaxIter + 2; numIter = numMaxIter;
break; break;
} }
// CN processing // 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); pcRes = nrLDPC_cnProcPc_BG2(p_lut, cnProcBuf, cnProcBufRes, Z);
NR_LDPC_PROFILER_DETAIL(stop_meas(&p_profiler->cnProcPc)); NR_LDPC_PROFILER_DETAIL(stop_meas(&p_profiler->cnProcPc));
} else { } else {
if (numIter > 2) { if (numIter > 0) {
int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0}; int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0};
int8_t* p_llrOut = outMode == nrLDPC_outMode_LLRINT8 ? p_out : llrOut; int8_t* p_llrOut = outMode == nrLDPC_outMode_LLRINT8 ? p_out : llrOut;
nrLDPC_llrRes2llrOut(p_lut, p_llrOut, llrRes, Z, BG); 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) { if (!p_decParams->check_crc) {
int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0}; int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0};
-18
View File
@@ -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) { void phy_init_nr_top(PHY_VARS_NR_UE *ue) {
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; 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); init_delay_table(frame_parms->ofdm_symbol_size, MAX_DELAY_COMP, NR_MAX_OFDM_SYMBOL_SIZE, frame_parms->delay_table);
-1
View File
@@ -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); 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 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_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 nr_dump_frame_parms(NR_DL_FRAME_PARMS *frame_parms);
void phy_init_nr_gNB(PHY_VARS_gNB *gNB); void phy_init_nr_gNB(PHY_VARS_gNB *gNB);
int init_codebook_gNB(PHY_VARS_gNB *gNB); int init_codebook_gNB(PHY_VARS_gNB *gNB);
@@ -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 /*! \brief Prepare necessary parameters for nrLDPC_coding_interface
*/ */
uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
const UE_nr_rxtx_proc_t *proc, const UE_nr_rxtx_proc_t *proc,
NR_UE_DLSCH_t *dlsch, NR_UE_DLSCH_t *dlsch,
int16_t **dlsch_llr, int16_t **dlsch_llr,
uint8_t **b, uint8_t **b,
int *G, int *G,
int nb_dlsch, int nb_dlsch,
uint8_t *DLSCH_ids) uint8_t *DLSCH_ids)
{ {
nrLDPC_TB_decoding_parameters_t TBs[nb_dlsch]; nrLDPC_TB_decoding_parameters_t TBs[nb_dlsch];
memset(TBs, 0, sizeof(TBs)); memset(TBs, 0, sizeof(TBs));
@@ -100,7 +100,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
if (!harq_process) { if (!harq_process) {
LOG_E(PHY, "dlsch_decoding_slot.c: NULL harq_process pointer\n"); 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]; 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) { 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); 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)) 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); int ret_decoder = phy_vars_ue->nrLDPC_coding_interface.nrLDPC_coding_decoder(&slot_parameters);
if (ret_decoder != 0) { 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 // post decode
@@ -316,11 +317,11 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
if (harq_process->decodeResult) { if (harq_process->decodeResult) {
LOG_D(PHY, "DLSCH received ok \n"); LOG_D(PHY, "DLSCH received ok \n");
harq_process->status = SCH_IDLE; harq_process->status = SCH_IDLE;
dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations; dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations - 1;
} else { } else {
LOG_D(PHY, "DLSCH received nok \n"); LOG_D(PHY, "DLSCH received nok \n");
kpiStructure.nb_nack++; 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"); 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;
} }
@@ -81,14 +81,14 @@ void nr_conjch0_mult_ch1(int *ch0,
@param[in] DLSCH_ids array of active downlink shared channels @param[in] DLSCH_ids array of active downlink shared channels
@returns 0 on success, 1 on unsuccessful decoding @returns 0 on success, 1 on unsuccessful decoding
*/ */
uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
const UE_nr_rxtx_proc_t *proc, const UE_nr_rxtx_proc_t *proc,
NR_UE_DLSCH_t *dlsch, NR_UE_DLSCH_t *dlsch,
short **dlsch_llr, short **dlsch_llr,
uint8_t **b, uint8_t **b,
int *G, int *G,
int nb_dlsch, int nb_dlsch,
uint8_t *DLSCH_ids); uint8_t *DLSCH_ids);
/** \brief This is the alternative top-level entry point for ULSCH encoding in UE. /** \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 It handles all the HARQ processes in only one call. The routine first
@@ -147,7 +147,7 @@ typedef struct {
/// Maximum number of LDPC iterations /// Maximum number of LDPC iterations
uint8_t max_ldpc_iterations; uint8_t max_ldpc_iterations;
/// number of iterations used in last turbo decoding /// 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 /// bit mask of PT-RS ofdm symbol indicies
uint16_t ptrs_symbols; uint16_t ptrs_symbols;
// PTRS symbol index, to be updated every PTRS symbol within a slot. // PTRS symbol index, to be updated every PTRS symbol within a slot.
+1 -1
View File
@@ -239,7 +239,7 @@ typedef struct {
/// Maximum number of LDPC iterations /// Maximum number of LDPC iterations
uint8_t max_ldpc_iterations; uint8_t max_ldpc_iterations;
/// number of iterations used in last LDPC decoding /// number of iterations used in last LDPC decoding
uint8_t last_iteration_cnt; int8_t last_iteration_cnt;
/// Status Flag indicating for this ULSCH /// Status Flag indicating for this ULSCH
bool active; bool active;
/// Flag to indicate that the UL configuration has been handled. Used to remove a stale ULSCH when frame wraps around /// Flag to indicate that the UL configuration has been handled. Used to remove a stale ULSCH when frame wraps around
+2 -2
View File
@@ -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"); LOG_D(PHY, "ULSCH received ok \n");
ulsch->active = false; ulsch->active = false;
ulsch_harq->round = 0; 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 { } else {
LOG_D(PHY, 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, " "[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"); gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_NACK");
ulsch->handled = 1; ulsch->handled = 1;
LOG_D(PHY, "ULSCH %d in error\n",ULSCH_id); 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
} }
} }
-9
View File
@@ -419,15 +419,6 @@ static void configure_ta_command(PHY_VARS_NR_UE *ue, fapi_nr_ta_command_pdu *ta_
LOG_D(PHY, 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 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); 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, static void nr_ue_scheduled_response_dl(NR_UE_MAC_INST_t *mac,
+4 -9
View File
@@ -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 /*! \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, const UE_nr_rxtx_proc_t *proc,
NR_UE_DLSCH_t dlsch[2], NR_UE_DLSCH_t dlsch[2],
int16_t *llr[2]) { int16_t *llr[2]) {
if (dlsch[0].active == false) { if (dlsch[0].active == false) {
LOG_E(PHY, "DLSCH should be active when calling this function\n"); 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 harq_pid = dlsch[0].dlsch_config.harq_process_nbr;
int frame_rx = proc->frame_rx; int frame_rx = proc->frame_rx;
int nr_slot_rx = proc->nr_slot_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_harq0 = &ue->dl_harq_processes[0][harq_pid];
NR_DL_UE_HARQ_t *dl_harq1 = &ue->dl_harq_processes[1][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); 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 = 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; (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]); dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS]);
return false; return;
} }
int G[2]; 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); 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); stop_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS);
if (ret < ue->max_ldpc_iterations + 1) dec = true;
int ind_type = -1; int ind_type = -1;
switch (dlsch[0].rnti_type) { switch (dlsch[0].rnti_type) {
case TYPE_RA_RNTI_: 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) else if (ue->phy_sim_dlsch_b && is_cw1_active == ACTIVE)
memcpy(ue->phy_sim_dlsch_b, p_b[1], dlsch_bytes); 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) static bool is_ssb_index_transmitted(const PHY_VARS_NR_UE *ue, const int index)
+9 -10
View File
@@ -123,7 +123,6 @@ int main(int argc, char **argv)
NR_DL_FRAME_PARMS *frame_parms; NR_DL_FRAME_PARMS *frame_parms;
double sigma; double sigma;
unsigned char qbits = 8; unsigned char qbits = 8;
int ret;
int loglvl = OAILOG_WARNING; int loglvl = OAILOG_WARNING;
uint8_t dlsch_threads = 0; uint8_t dlsch_threads = 0;
float target_error_rate = 0.01; float target_error_rate = 0.01;
@@ -577,18 +576,18 @@ int main(int argc, char **argv)
short *p_channel_output_fixed = channel_output_fixed; short *p_channel_output_fixed = channel_output_fixed;
uint8_t *p_b = b; uint8_t *p_b = b;
int available_bits_array[1] = { available_bits }; int available_bits_array[1] = { available_bits };
ret = nr_dlsch_decoding(UE, nr_dlsch_decoding(UE,
&proc, &proc,
dlsch0_ue, dlsch0_ue,
&p_channel_output_fixed, &p_channel_output_fixed,
&p_b, &p_b,
available_bits_array, available_bits_array,
1, 1,
DLSCH_ids); DLSCH_ids);
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING0, VCD_FUNCTION_OUT); 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++; n_errors++;
//count errors //count errors
+1 -1
View File
@@ -1163,7 +1163,7 @@ printf("%d\n", slot);
//---------------------- count errors ---------------------- //---------------------- count errors ----------------------
//---------------------------------------------------------- //----------------------------------------------------------
if (dlsch0->last_iteration_cnt >= dlsch0->max_ldpc_iterations+1) if (dlsch0->last_iteration_cnt >= dlsch0->max_ldpc_iterations)
n_errors[round]++; n_errors[round]++;
int16_t *UE_llr = (int16_t*)UE->phy_sim_pdsch_llr; int16_t *UE_llr = (int16_t*)UE->phy_sim_pdsch_llr;
@@ -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_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) {} void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id) {}
+19 -22
View File
@@ -136,13 +136,11 @@ int main(int argc, char **argv){
c16_t **txdata; 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; 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 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; uint8_t config_index = 98, prach_sequence_length = 1, restrictedSetConfig = 0;
uint16_t Nid_cell = 0, preamble_tx = 0, preamble_delay, format, format0, format1; uint16_t Nid_cell = 0, preamble_tx = 0, preamble_delay, format0, format1;
uint32_t tx_lev = 10000, prach_errors = 0; //,tx_lev_dB; uint32_t tx_lev = 10000, prach_errors = 0; //,tx_lev_dB;
uint64_t SSB_positions = 0x01; uint64_t SSB_positions = 0x01;
uint16_t RA_sfn_index; uint16_t RA_sfn_index;
uint8_t N_RA_slot;
uint8_t config_period;
int prachOccasion = 0; int prachOccasion = 0;
double DS_TDL = .03; 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.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->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, if (ret == 0) {
(int)frame, printf("No prach in %d.%d, mu %d, config_index %d\n", frame, slot, mu, config_index);
(int)slot, exit(-1);
absoluteFrequencyPointA, }
mu, format0 = prach_info.format & 0xff; // first column of format from table
frame_parms->frame_type, format1 = (prach_info.format >> 8) & 0xff; // second column of format from table
&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 (format1 != 0xff) { if (format1 != 0xff) {
switch(format0) { switch(format0) {
+1 -1
View File
@@ -1420,7 +1420,7 @@ int main(int argc, char *argv[])
0); 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; error_flag = 1;
n_errors[round]++; n_errors[round]++;
crc_status = 1; crc_status = 1;
+1 -1
View File
@@ -72,13 +72,13 @@
// Messages between RRC and MAC layers // Messages between RRC and MAC layers
typedef struct NRRrcMacRaInd_s { typedef struct NRRrcMacRaInd_s {
uint32_t frame;
bool RA_succeeded; bool RA_succeeded;
} NRRrcMacRaInd; } NRRrcMacRaInd;
typedef struct NRRrcMacMsg3Ind_s { typedef struct NRRrcMacMsg3Ind_s {
uint16_t rnti; uint16_t rnti;
int gnb_id; int gnb_id;
bool prepare_payload;
} NRRrcMacMsg3Ind; } NRRrcMacMsg3Ind;
typedef struct NRRrcMacInacInd_s { typedef struct NRRrcMacInacInd_s {
-30
View File
@@ -461,36 +461,6 @@ typedef struct {
#define NR_MAX_NUM_LCGID 8 #define NR_MAX_NUM_LCGID 8
#define MAX_RLC_SDU_SUBHEADER_SIZE 3 #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 // DCI defs
//========= //=========
+135 -263
View File
@@ -571,34 +571,33 @@ NR_tda_info_t get_dl_tda_info(const NR_UE_DL_BWP_t *dl_BWP,
return tda_info; return tda_info;
} }
uint16_t get_NCS(uint8_t index, uint16_t format0, uint8_t restricted_set_config) { 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", LOG_D(NR_MAC, "get_NCS: indx %d,format0 %d, restriced_set_config %d\n", index, format0, restricted_set_config);
index,format0,restricted_set_config);
if (format0 < 3) { if (format0 < 3) {
switch(restricted_set_config){ switch (restricted_set_config) {
case 0: case 0:
return(NCS_unrestricted_delta_f_RA_125[index]); return(NCS_unrestricted_delta_f_RA_125[index]);
case 1: case 1:
return(NCS_restricted_TypeA_delta_f_RA_125[index]); return(NCS_restricted_TypeA_delta_f_RA_125[index]);
case 2: case 2:
return(NCS_restricted_TypeB_delta_f_RA_125[index]); return(NCS_restricted_TypeB_delta_f_RA_125[index]);
default: default:
AssertFatal(1==0,"Invalid restricted set config value %d",restricted_set_config); AssertFatal(false, "Invalid restricted set config value %d", restricted_set_config);
} }
} }
else { else {
if (format0 == 3) { if (format0 == 3) {
switch(restricted_set_config){ switch (restricted_set_config) {
case 0: case 0:
return(NCS_unrestricted_delta_f_RA_5[index]); return(NCS_unrestricted_delta_f_RA_5[index]);
case 1: case 1:
return(NCS_restricted_TypeA_delta_f_RA_5[index]); return(NCS_restricted_TypeA_delta_f_RA_5[index]);
case 2: case 2:
return(NCS_restricted_TypeB_delta_f_RA_5[index]); return(NCS_restricted_TypeB_delta_f_RA_5[index]);
default: default:
AssertFatal(1==0,"Invalid restricted set config value %d",restricted_set_config); AssertFatal(false, "Invalid restricted set config value %d", restricted_set_config);
} }
} }
else 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) {0xa3, 0xb3, 1, 0, -1, 733007751850, 2, 1, 2, 6} // (subframe number :1,3,5,7,…,37,39)
}; };
int get_format0(uint8_t index, int get_format0(uint8_t index, uint8_t unpaired, frequency_range_t frequency_range)
uint8_t unpaired, {
frequency_range_t frequency_range){ int format = 0;
uint16_t format=0;
if (unpaired) { if (unpaired) {
if (frequency_range==FR1) if (frequency_range==FR1)
format = table_6_3_3_2_3_prachConfig_Index[index][0]; format = table_6_3_3_2_3_prachConfig_Index[index][0];
@@ -1438,23 +1435,6 @@ int get_format0(uint8_t index,
return format; 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, void find_aggregation_candidates(uint8_t *aggregation_level,
uint8_t *nr_of_candidates, uint8_t *nr_of_candidates,
const NR_SearchSpace_t *ss, 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, nr_prach_info_t get_nr_prach_occasion_info_from_index(uint8_t index, frequency_range_t freq_range, uint8_t unpaired)
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)
{ {
int x;
uint64_t s_map;
uint8_t format2 = 0xff; uint8_t format2 = 0xff;
if (pointa > 2016666) { //FR2 nr_prach_info_t info;
x = table_6_3_3_2_4_prachConfig_Index[index][2]; if (freq_range == FR2) {
s_map = table_6_3_3_2_4_prachConfig_Index[index][5]; info.x = table_6_3_3_2_4_prachConfig_Index[index][2];
*N_RA_sfn += count_bits64(s_map); info.y = table_6_3_3_2_4_prachConfig_Index[index][3];
*N_RA_slot = table_6_3_3_2_4_prachConfig_Index[index][7]; // Number of RACH slots within a subframe info.y2 = table_6_3_3_2_4_prachConfig_Index[index][4];
*max_association_period = 160/(x * 10); info.s_map = table_6_3_3_2_4_prachConfig_Index[index][5];
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ info.N_RA_sfn += count_bits64(info.s_map);
*start_symbol = table_6_3_3_2_4_prachConfig_Index[index][6];//multiple prach occasions in diff slot info.N_RA_slot = table_6_3_3_2_4_prachConfig_Index[index][7];
*N_t_slot = table_6_3_3_2_4_prachConfig_Index[index][8]; info.max_association_period = 160 / (info.x * 10);
*N_dur = table_6_3_3_2_4_prachConfig_Index[index][9]; info.start_symbol = table_6_3_3_2_4_prachConfig_Index[index][6];
if (table_6_3_3_2_4_prachConfig_Index[index][1] != -1) info.N_t_slot = table_6_3_3_2_4_prachConfig_Index[index][8];
format2 = (uint8_t) table_6_3_3_2_4_prachConfig_Index[index][1]; 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)
*format = ((uint8_t) table_6_3_3_2_4_prachConfig_Index[index][0]) | (format2<<8); format2 = (uint8_t)table_6_3_3_2_4_prachConfig_Index[index][1];
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", info.format = ((uint8_t)table_6_3_3_2_4_prachConfig_Index[index][0]) | (format2 << 8);
index, LOG_D(NR_MAC,
pointa, "PRACH info from index %d frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_sfn = %u\n",
mu, index,
unpaired, unpaired,
*start_symbol, info.start_symbol,
*N_t_slot, info.N_t_slot,
*N_dur, info.N_dur,
*N_RA_sfn); info.N_RA_sfn);
} return info;
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;
}
} }
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) 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; return format;
} }
int get_nr_prach_info_from_index(uint8_t index, bool get_nr_prach_sched_from_info(nr_prach_info_t info,
int frame, int config_index,
int slot, int frame,
uint32_t pointa, int slot,
uint8_t mu, int mu,
uint8_t unpaired, frequency_range_t freq_range,
uint16_t *format, uint16_t *RA_sfn_index,
uint8_t *start_symbol, uint8_t unpaired)
uint8_t *N_t_slot,
uint8_t *N_dur,
uint16_t *RA_sfn_index,
uint8_t *N_RA_slot,
uint8_t *config_period)
{ {
int x,y; if (freq_range == FR2) {
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];
// checking n_sfn mod x = y // checking n_sfn mod x = y
if ((frame % x) == y || (frame % x) == y2) { if ((frame % info.x) == info.y || (frame % info.x) == info.y2) {
slot_60khz = slot >> (mu - 2); // in table slots are numbered wrt 60kHz int 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 ((info.s_map >> slot_60khz) & 0x01) {
if ((s_map >> slot_60khz) & 0x01) {
for(int i = 0; i <= slot_60khz ;i++) { for(int i = 0; i <= slot_60khz ;i++) {
if ((s_map >> i) & 0x01) { if ((info.s_map >> i) & 0x01) {
(*RA_sfn_index)++; (*RA_sfn_index)++;
} }
} }
} }
if (((s_map >> slot_60khz) & 0x01)) { if (((info.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 (mu == 3) { if (mu == 3) {
if ((*N_RA_slot == 1) && (slot % 2 == 0) ) if ((info.N_RA_slot == 1) && (slot % 2 == 0))
return 0; // no prach in even slots @ 120kHz for 1 prach per 60khz slot 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){ return true;
*config_period = x; } else
*start_symbol = table_6_3_3_2_4_prachConfig_Index[index][6]; return false; // no prach in current 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,"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
} }
else else
return 0; // no prach in current frame return false; // no prach in current frame
} } else {
else { if (unpaired) { // TDD
uint8_t subframe; if ((frame % info.x) == info.y) {
if (unpaired) { int subframe = slot >> mu;
x = table_6_3_3_2_3_prachConfig_Index[index][2]; if ((info.s_map >> subframe) & 0x01) {
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) {
for(int i = 0; i <= subframe ;i++) { for(int i = 0; i <= subframe ;i++) {
if ((s_map >> i) & 0x01) { if ((info.s_map >> i) & 0x01) {
(*RA_sfn_index)++; (*RA_sfn_index)++;
} }
} }
} }
if ((s_map >> subframe) & 0x01 ) { if ((info.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 (config_index >= 67) {
if (index >= 67) { if ((mu == 1) && (info.N_RA_slot <= 1) && (slot % 2 == 0))
if ((mu == 1) && (*N_RA_slot <= 1) && (slot % 2 == 0)) return false; // no prach in even slots @ 30kHz for 1 prach per subframe
return 0; // no prach in even slots @ 30kHz for 1 prach per subframe
} else { } else {
if ((slot % 2) && (mu > 0)) 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) { return true;
*config_period = x; } else
*start_symbol = table_6_3_3_2_3_prachConfig_Index[index][5]; return false; // no prach in current slot
*N_t_slot = table_6_3_3_2_3_prachConfig_Index[index][7]; } else
*N_dur = table_6_3_3_2_3_prachConfig_Index[index][8]; return false; // no prach in current frame
if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1) } else { // FDD
format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[index][1]; if ((frame % info.x) == info.y) {
*format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2<<8); int subframe = slot >> mu;
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", if ((info.s_map >> subframe) & 0x01) {
frame, if (config_index >= 87) {
slot, if ((mu == 1) && (info.N_RA_slot <= 1) && (slot % 2 == 0)) {
index, return false; // no prach in even slots @ 30kHz for 1 prach per subframe
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
} }
} else { } else {
if ((slot % 2) && (mu > 0)) if ((slot % 2) && (mu > 0))
return 0; // slot does not contain start symbol of this prach time resource return 0; // slot does not contain start symbol of this prach time resource
} }
for(int i = 0; i <= subframe ; i++) { for(int i = 0; i <= subframe ; i++) {
if ((s_map >> i) & 0x01) { if ((info.s_map >> i) & 0x01) {
(*RA_sfn_index)++; (*RA_sfn_index)++;
} }
} }
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ return true;
*start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5]; } else
*config_period = x; return false; // no prach in current slot
*N_t_slot = table_6_3_3_2_2_prachConfig_Index[index][7]; } else
*N_dur = table_6_3_3_2_2_prachConfig_Index[index][8]; return false; // no prach in current frame
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
} }
} }
} }
+24 -27
View File
@@ -52,6 +52,20 @@ typedef enum {
pusch_len2 = 2 pusch_len2 = 2
} pusch_maxLength_t; } 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); uint32_t get_Y(const NR_SearchSpace_t *ss, int slot, rnti_t rnti);
uint8_t get_BG(uint32_t A, uint16_t R); 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); 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, bool get_nr_prach_sched_from_info(nr_prach_info_t info,
int frame, int config_index,
int slot, int frame,
uint32_t pointa, int slot,
uint8_t mu, int mu,
uint8_t unpaired, frequency_range_t freq_range,
uint16_t *format, uint16_t *RA_sfn_index,
uint8_t *start_symbol, uint8_t unpaired);
uint8_t *N_t_slot,
uint8_t *N_dur,
uint16_t *RA_sfn_index,
uint8_t *N_RA_slot,
uint8_t *config_period);
int get_nr_prach_occasion_info_from_index(uint8_t index, nr_prach_info_t get_nr_prach_occasion_info_from_index(uint8_t index, frequency_range_t freq_range, uint8_t unpaired);
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);
uint8_t get_pusch_mcs_table(long *mcs_Table, uint8_t get_pusch_mcs_table(long *mcs_Table,
int is_tp, 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); 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); int get_format0(uint8_t index, uint8_t unpaired, frequency_range_t frequency_range);
const int64_t *get_prach_config_info(frequency_range_t freq_range, uint8_t index, uint8_t unpaired);
uint16_t get_NCS(uint8_t index, uint16_t format, uint8_t restricted_set_config); uint16_t get_NCS(uint8_t index, uint16_t format, uint8_t restricted_set_config);
int compute_pucch_crc_size(int O_uci); int compute_pucch_crc_size(int O_uci);
+56 -40
View File
@@ -44,6 +44,44 @@
#include "oai_asn1.h" #include "oai_asn1.h"
#include "executables/position_interface.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) 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; 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 // cell config
cfg->cell_config.phy_cell_id = mac->physCellId; cfg->cell_config.phy_cell_id = mac->physCellId;
cfg->cell_config.frame_duplex_type = frame_type; cfg->cell_config.frame_duplex_type = frame_type;
cfg->cell_config.N_TA_offset = get_ta_offset(scc->n_TimingAdvanceOffset);
// SSB config // SSB config
cfg->ssb_config.ss_pbch_power = scc->ss_PBCH_BlockPower; 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 { else {
// If absent, the UE applies the SCS as derived from the prach-ConfigurationIndex (for 839) // If absent, the UE applies the SCS as derived from the prach-ConfigurationIndex (for 839)
int config_index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; 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 = get_format0(config_index, frame_type, mac->frequency_range);
int format = prach_config_info_p[0];
cfg->prach_config.prach_sub_c_spacing = get_delta_f_RA_long(format); 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 // cell config
cfg->cell_config.phy_cell_id = *scc->physCellId; cfg->cell_config.phy_cell_id = *scc->physCellId;
cfg->cell_config.frame_duplex_type = frame_type; cfg->cell_config.frame_duplex_type = frame_type;
cfg->cell_config.N_TA_offset = get_ta_offset(scc->n_TimingAdvanceOffset);
// SSB config // SSB config
cfg->ssb_config.ss_pbch_power = scc->ss_PBCH_BlockPower; 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 { else {
// If absent, the UE applies the SCS as derived from the prach-ConfigurationIndex (for 839) // If absent, the UE applies the SCS as derived from the prach-ConfigurationIndex (for 839)
int config_index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; 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 = get_format0(config_index, frame_type, mac->frequency_range);
int format = prach_config_info_p[0];
cfg->prach_config.prach_sub_c_spacing = format == 3 ? 5 : 4; 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; NR_UE_DL_BWP_t *bwp = NULL;
for (int i = 0; i < mac->dl_BWPs.count; i++) { 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; 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; NR_UE_UL_BWP_t *bwp = NULL;
for (int i = 0; i < mac->ul_BWPs.count; i++) { 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); 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, static void configure_si_schedulingInfo(NR_UE_MAC_INST_t *mac,
NR_SI_SchedulingInfo_t *si_SchedulingInfo, NR_SI_SchedulingInfo_t *si_SchedulingInfo,
NR_SI_SchedulingInfo_v1700_t *si_SchedulingInfo_v1700) 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"); 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); 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); 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); config_common_ue_sa(mac, scc, cc_idP);
configure_common_BWP_dl(mac,
0, // bwp-id // Build the list of all the valid/transmitted SSBs according to the config
&scc->downlinkConfigCommon.initialDownlinkBWP); 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) { if (scc->uplinkConfigCommon) {
mac->timeAlignmentTimerCommon = scc->uplinkConfigCommon->timeAlignmentTimerCommon; mac->timeAlignmentTimerCommon = scc->uplinkConfigCommon->timeAlignmentTimerCommon;
configure_common_BWP_ul(mac, configure_common_BWP_ul(mac, bwp_id, &scc->uplinkConfigCommon->initialUplinkBWP);
0, // bwp-id
&scc->uplinkConfigCommon->initialUplinkBWP);
} }
// set current BWP only if coming from non-connected state // set current BWP only if coming from non-connected state
// otherwise it is just a periodically update of the SIB1 content // 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) if (mac->state == UE_RECEIVING_SIB && can_start_ra)
mac->state = UE_PERFORMING_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) if (!get_softmodem_params()->emulate_l1)
mac->if_module->phy_config_request(&mac->phy_config); mac->if_module->phy_config_request(&mac->phy_config);
ret = pthread_mutex_unlock(&mac->if_mutex); 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) { if (reconfWithSync->spCellConfigCommon) {
NR_ServingCellConfigCommon_t *scc = reconfWithSync->spCellConfigCommon; NR_ServingCellConfigCommon_t *scc = reconfWithSync->spCellConfigCommon;
mac->n_ta_offset = get_ta_offset(scc->n_TimingAdvanceOffset);
if (scc->physCellId) if (scc->physCellId)
mac->physCellId = *scc->physCellId; mac->physCellId = *scc->physCellId;
mac->dmrs_TypeA_Position = scc->dmrs_TypeA_Position; 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); 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); 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; const int bwp_id = 0;
if (scc->downlinkConfigCommon) if (scc->downlinkConfigCommon)
configure_common_BWP_dl(mac, bwp_id, scc->downlinkConfigCommon->initialDownlinkBWP); 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) if (ue_Capability)
handle_mac_uecap_info(mac, 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) if (!mac->dl_config_request || !mac->ul_config_request)
ue_init_config_request(mac, mac->frame_structure.numb_slots_frame); ue_init_config_request(mac, mac->frame_structure.numb_slots_frame);
ret = pthread_mutex_unlock(&mac->if_mutex); ret = pthread_mutex_unlock(&mac->if_mutex);
+63 -98
View File
@@ -79,23 +79,7 @@
/*!\brief value for indicating BSR Timer is not running */ /*!\brief value for indicating BSR Timer is not running */
#define NR_MAC_UE_BSR_TIMER_NOT_RUNNING (0xFFFF) #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_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 // DCI fields defs
@@ -169,6 +153,23 @@
UE_STATE(UE_CONNECTED) \ UE_STATE(UE_CONNECTED) \
UE_STATE(UE_DETACHING) 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 { typedef enum {
phr_cause_prohibit_timer = 0, phr_cause_prohibit_timer = 0,
phr_cause_periodic_timer, 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"}; {"UE_IDLE", "GENERATE_PREAMBLE", "WAIT_RAR", "WAIT_MSGB", "WAIT_CONTENTION_RESOLUTION", "RA_SUCCEEDED", "RA_FAILED"};
typedef struct { typedef struct {
/// PRACH format retrieved from prach_ConfigIndex
uint16_t prach_format;
/// Preamble Tx Counter /// Preamble Tx Counter
uint8_t RA_PREAMBLE_TRANSMISSION_COUNTER; uint8_t preamble_tx_counter;
/// Preamble Power Ramping Counter /// Preamble Power Ramping Counter
uint8_t RA_PREAMBLE_POWER_RAMPING_COUNTER; uint8_t preamble_power_ramping_cnt;
/// 2-step RA power offset /// 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. /// 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; int ra_preamble_rx_target_power;
/// PRACH index for TDD (0 ... 6) depending on TDD configuration and prachConfigIndex
uint8_t ra_TDD_map_index;
/// RA Preamble Power Ramping Step in dB /// RA Preamble Power Ramping Step in dB
uint32_t RA_PREAMBLE_POWER_RAMPING_STEP; uint32_t 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;
/// UE configured maximum output power /// UE configured maximum output power
int RA_PCMAX; int Pc_max;
} NR_PRACH_RESOURCES_t; } NR_PRACH_RESOURCES_t;
typedef struct { 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 // pointer to RACH config dedicated
NR_RACH_ConfigDedicated_t *rach_ConfigDedicated; NR_RACH_ConfigDedicated_t *rach_ConfigDedicated;
/// state of RA procedure /// state of RA procedure
nrRA_UE_state_t ra_state; nrRA_UE_state_t ra_state;
/// RA contention type /// RA contention type
uint8_t cfra; bool cfra;
/// RA type /// RA type
nr_ra_type_t 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 /// MsgB SuccessRAR MAC subheader
int8_t MsgB_R; int8_t MsgB_R;
int8_t MsgB_CH_ACESS_CPEXT; int8_t MsgB_CH_ACESS_CPEXT;
@@ -321,53 +321,51 @@ typedef struct {
uint16_t MsgB_rnti; uint16_t MsgB_rnti;
/// Temporary CRNTI /// Temporary CRNTI
uint16_t t_crnti; uint16_t t_crnti;
/// number of attempt for rach
uint8_t RA_attempt_number;
/// Random-access procedure flag /// Random-access procedure flag
bool RA_active; bool RA_active;
/// Random-access preamble index /// Random-access preamble index
int ra_PreambleIndex; 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 int zeroCorrelationZoneConfig;
uint8_t ssb_nb_in_ro; int restricted_set_config;
// selected SSB for RACH (not the SSB-Index but the cumulative index, excluding not trasmitted SSBs)
/// Random-access window counter int ra_ssb;
int16_t RA_window_cnt; /// Random-access response window timer
/// Flag to monitor if matching RAPID was received in RAR NR_timer_t response_window_timer;
uint8_t RA_RAPID_found; int response_window_setup_time;
/// Flag to monitor if BI was received in RAR /// Random-access backoff timer
uint8_t RA_BI_found; NR_timer_t RA_backoff_timer;
/// Random-access backoff counter int RA_backoff_limit;
int16_t RA_backoff_indicator; uint8_t scaling_factor_bi;
/// Flag to indicate whether preambles Group A was used /// Flag to indicate whether preambles Group A is selected
uint8_t RA_usedGroupA; bool RA_GroupA;
/// RA backoff counter
int16_t RA_backoff_cnt;
/// RA max number of preamble transmissions /// RA max number of preamble transmissions
int preambleTransMax; int preambleTransMax;
/// Nb of preambles per SSB
long cb_preambles_per_ssb;
int starting_preamble_nb;
/// Received TPC command (in dB) from RAR /// Received TPC command (in dB) from RAR
int8_t Msg3_TPC; int8_t Msg3_TPC;
/// Flag to indicate whether it is the first Msg3 to be transmitted
bool first_Msg3;
/// RA Msg3 size in bytes /// RA Msg3 size in bytes
uint8_t Msg3_size; uint8_t Msg3_size;
/// Msg3 buffer /// Msg3 buffer
uint8_t *Msg3_buffer; uint8_t *Msg3_buffer;
// initial Random Access Preamble power
bool msg3_C_RNTI; int preambleRxTargetPower;
int msg3_deltaPreamble;
int preambleReceivedTargetPower_config;
/// Random-access Contention Resolution Timer /// Random-access Contention Resolution Timer
NR_timer_t contention_resolution_timer; NR_timer_t contention_resolution_timer;
/// Transmitted UE Contention Resolution Identifier /// Transmitted UE Contention Resolution Identifier
uint8_t cont_res_id[6]; uint8_t cont_res_id[6];
/// BeamfailurerecoveryConfig NR_pdcch_order_config_t pdcch_order;
NR_BeamFailureRecoveryConfig_t RA_BeamFailureRecoveryConfig;
NR_PRACH_RESOURCES_t prach_resources; 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; } RA_config_t;
typedef struct { typedef struct {
@@ -435,39 +433,8 @@ typedef struct NR_UL_TIME_ALIGNMENT {
int slot; int slot;
} NR_UL_TIME_ALIGNMENT_t; } 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 // List of all the possible SSBs and their details
typedef struct ssb_list_info { typedef struct ssb_list_info {
ssb_info_t *tx_ssb;
int nb_tx_ssb; int nb_tx_ssb;
int nb_ssb_per_index[MAX_NB_SSB]; int nb_ssb_per_index[MAX_NB_SSB];
} ssb_list_info_t; } ssb_list_info_t;
@@ -571,14 +538,12 @@ typedef struct NR_UE_MAC_INST_s {
NR_UE_L2_STATE_t state; NR_UE_L2_STATE_t state;
int servCellIndex; int servCellIndex;
long physCellId; long physCellId;
int first_sync_frame;
bool get_sib1; bool get_sib1;
bool get_otherSI; bool get_otherSI;
NR_MIB_t *mib; NR_MIB_t *mib;
si_schedInfo_t si_SchedInfo; si_schedInfo_t si_SchedInfo;
ssb_list_info_t ssb_list[MAX_NUM_BWP_UE]; ssb_list_info_t ssb_list;
prach_association_pattern_t prach_assoc_pattern[MAX_NUM_BWP_UE];
NR_UE_ServingCell_Info_t sc_info; NR_UE_ServingCell_Info_t sc_info;
A_SEQUENCE_OF(NR_UE_DL_BWP_t) dl_BWPs; 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 dmrs_TypeA_Position;
int p_Max; int p_Max;
int p_Max_alt; int p_Max_alt;
int n_ta_offset; // -1 not present, otherwise value to be applied
ntn_timing_advance_componets_t ntn_ta; ntn_timing_advance_componets_t ntn_ta;
@@ -670,6 +634,7 @@ typedef struct NR_UE_MAC_INST_s {
int f_b_f_c; int f_b_f_c;
bool pusch_power_control_initialized; bool pusch_power_control_initialized;
int delta_msg2; int delta_msg2;
bool msg3_C_RNTI;
pthread_mutex_t if_mutex; pthread_mutex_t if_mutex;
ue_mac_stats_t stats; ue_mac_stats_t stats;
} NR_UE_MAC_INST_t; } NR_UE_MAC_INST_t;
+14 -58
View File
@@ -45,8 +45,12 @@
\param mac MAC pointer */ \param mac MAC pointer */
void nr_ue_init_mac(NR_UE_MAC_INST_t *mac); 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 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); 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 /**\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; enum { b_none, b_long, b_short, b_short_trunc, b_long_trunc } type_bsr;
} type_bsr_t; } 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, int nr_write_ce_ulsch_pdu(uint8_t *mac_ce,
NR_UE_MAC_INST_t *mac, NR_UE_MAC_INST_t *mac,
NR_SINGLE_ENTRY_PHR_MAC_CE *power_headroom, 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); 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); 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); 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, int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac,
int scs, int scs,
NR_PUCCH_Config_t *pucch_Config, 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, dci_pdu_rel15_t *dci,
nr_dci_format_t dci_format); nr_dci_format_t dci_format);
bool init_RA(NR_UE_MAC_INST_t *mac, int frame);
/* Random Access */ /* Random Access */
/* \brief This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211 tables 6.3.3.2.x /* \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. 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_size,
uint32_t bwp_start); 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); void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame_t frame, const int slot);
void nr_ra_backoff_setting(RA_config_t *ra);
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_get_RA_window(NR_UE_MAC_INST_t *mac); 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 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 configure_initial_pucch(PUCCH_sched_t *pucch, int res_ind);
void release_PUCCH_SRS(NR_UE_MAC_INST_t *mac); 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_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); 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 * @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); 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); 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 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 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 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); 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, 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, int start_DLBWP,
dci_field_t frequency_domain_assignment); 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 scs);
void ue_init_config_request(NR_UE_MAC_INST_t *mac, int slots_per_frame);
fapi_nr_dl_config_request_t *get_dl_config_request(NR_UE_MAC_INST_t *mac, int slot); fapi_nr_dl_config_request_t *get_dl_config_request(NR_UE_MAC_INST_t *mac, int slot);
-24
View File
@@ -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}, {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) static inline uint16_t packBits(const uint8_t *toPack, const int nb)
{ {
int res = 0; int res = 0;
+8 -6
View File
@@ -68,7 +68,7 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
mac->uecap_maxMIMO_PUSCH_layers_nocb = 0; mac->uecap_maxMIMO_PUSCH_layers_nocb = 0;
mac->p_Max = INT_MIN; mac->p_Max = INT_MIN;
mac->p_Max_alt = 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; mac->ntn_ta.ntn_params_changed = false;
reset_mac_inst(mac); 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->ssb_measurements, 0, sizeof(mac->ssb_measurements));
memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment)); memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment));
memset(mac->ssb_list, 0, sizeof(mac->ssb_list)); memset(&mac->ssb_list, 0, sizeof(mac->ssb_list));
memset(mac->prach_assoc_pattern, 0, sizeof(mac->prach_assoc_pattern));
for (int i = 0; i < NR_MAX_SR_ID; i++) 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])); 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) void nr_ue_reset_sync_state(NR_UE_MAC_INST_t *mac)
{ {
// reset synchornization status // reset synchornization status
mac->first_sync_frame = -1;
mac->state = UE_NOT_SYNC; mac->state = UE_NOT_SYNC;
mac->ra.ra_state = nrRA_UE_IDLE; 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) if (nr_mac->data_inactivity_timer)
nr_timer_stop(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->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.sr_DelayTimer);
nr_timer_stop(&nr_mac->scheduling_info.retxBSR_Timer); 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++) for (int i = 0; i < NR_MAX_SR_ID; i++)
nr_timer_stop(&nr_mac->scheduling_info.sr_info[i].prohibitTimer); 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 nr_mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value
// stop any ongoing RACH procedure // 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_state = nrRA_UE_IDLE;
nr_mac->ra.RA_active = false;
}
// discard explicitly signalled contention-free Random Access Resources // discard explicitly signalled contention-free Random Access Resources
// TODO not sure what needs to be done here // TODO not sure what needs to be done here
File diff suppressed because it is too large Load Diff
@@ -442,8 +442,8 @@ bool search_space_monitoring_ocasion_other_si(NR_UE_MAC_INST_t *mac,
get_monitoring_period_offset(ss, &period, &offset); get_monitoring_period_offset(ss, &period, &offset);
for (int i = 0; i < duration; i++) { for (int i = 0; i < duration; i++) {
if (((frame * slots_per_frame + slot - offset - i) % period) == 0) { if (((frame * slots_per_frame + slot - offset - i) % period) == 0) {
int N = mac->ssb_list[bwp_id].nb_tx_ssb; int N = mac->ssb_list.nb_tx_ssb;
int K = mac->ssb_list->nb_ssb_per_index[mac->mib_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 // numbering current frame and slot in terms of monitoring occasions in window
int rel_slot = abs_slot - mac->si_SchedInfo.si_window_start; 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); 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 RA is ongoing use RA search space
if (is_ss_monitor_occasion(frame, slot, slots_per_frame, pdcch_config->ra_SS)) { if (is_ss_monitor_occasion(frame, slot, slots_per_frame, pdcch_config->ra_SS)) {
nr_rnti_type_t rnti_type = 0; nr_rnti_type_t rnti_type = 0;
if (mac->ra.ra_type == RA_4_STEP) { if (ra->ra_type == RA_4_STEP) {
rnti_type = mac->ra.ra_state == nrRA_WAIT_RAR ? TYPE_RA_RNTI_ : TYPE_TC_RNTI_; rnti_type = ra->ra_state == nrRA_WAIT_RAR ? TYPE_RA_RNTI_ : TYPE_TC_RNTI_;
} else { } else {
rnti_type = TYPE_MSGB_RNTI_; rnti_type = TYPE_MSGB_RNTI_;
} }
@@ -372,8 +372,8 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac,
if (mac->pucch_power_control_initialized == false) { if (mac->pucch_power_control_initialized == false) {
// Initialize power control state // Initialize power control state
// Assuming only sending on PCell // Assuming only sending on PCell
NR_PRACH_RESOURCES_t* prach_resources = &mac->ra.prach_resources; NR_PRACH_RESOURCES_t *prach_res = &mac->ra.prach_resources;
float DELTA_P_rampup_requested = (prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER - 1) * prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP; 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); 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); DELTA_P_rampup = max(min(0, DELTA_P_rampup), DELTA_P_rampup_requested);
mac->G_b_f_c = DELTA_P_rampup + sum_delta_pucch; 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) { if (current_UL_BWP->msg3_DeltaPreamble) {
DELTA_PREAMBLE_MSG3 = *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; int P_O_PRE = mac->ra.prach_resources.ra_preamble_rx_target_power;
long preambleReceivedTargetPower = nr_rach_ConfigCommon->rach_ConfigGeneric.preambleReceivedTargetPower;
int P_O_PRE = preambleReceivedTargetPower;
P_O_NOMINAL_PUSCH = P_O_PRE + DELTA_PREAMBLE_MSG3; P_O_NOMINAL_PUSCH = P_O_PRE + DELTA_PREAMBLE_MSG3;
if (has_pusch_power_control_config && pusch_Config->pusch_PowerControl->msg3_Alpha) { 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; f_b_f_c = delta_pusch;
} else { } else {
if (!mac->pusch_power_control_initialized && is_rar_tx_retx) { if (!mac->pusch_power_control_initialized && is_rar_tx_retx) {
NR_PRACH_RESOURCES_t* prach_resources = &mac->ra.prach_resources; NR_PRACH_RESOURCES_t *prach_res = &mac->ra.prach_resources;
float DELTA_P_rampup_requested = (prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER - 1) * prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP; 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); 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)); DELTA_P_rampup = min(DELTA_P_rampup_requested, max(0, DELTA_P_rampup));
mac->f_b_f_c = DELTA_P_rampup + delta_pusch; 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 (!is_tpc_accumulation_provided && (!is_configured_for_pusch_on_current_bwp || separate_pc_adjustment_state)) {
if (!current_UL_BWP->srs_power_control_initialized) { if (!current_UL_BWP->srs_power_control_initialized) {
NR_PRACH_RESOURCES_t *prach_resources = &mac->ra.prach_resources; NR_PRACH_RESOURCES_t *prach = &mac->ra.prach_resources;
float DELTA_P_rampup_requested = float DELTA_P_rampup_requested = (prach->preamble_power_ramping_cnt - 1) * prach->preamble_power_ramping_step;
(prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER - 1) * prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP;
float DELTA_P_rampup = P_CMAX - (P_0_SRS + m_srs_component + alpha * pathloss); 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)); DELTA_P_rampup = min(DELTA_P_rampup_requested, max(0, DELTA_P_rampup));
current_UL_BWP->srs_power_control_initialized = true; current_UL_BWP->srs_power_control_initialized = true;
+198 -204
View File
@@ -59,6 +59,25 @@
// #define DEBUG_MIB // #define DEBUG_MIB
// #define ENABLE_MAC_PAYLOAD_DEBUG 1 // #define ENABLE_MAC_PAYLOAD_DEBUG 1
// #define DEBUG_RAR // #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 */ /* 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] static const int sequence_cyclic_shift_1_harq_ack_bit[2]
/* HARQ-ACK Value 0 1 */ /* 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->ssb_subcarrier_offset = ssb_subcarrier_offset;
mac->dmrs_TypeA_Position = mac->mib->dmrs_TypeA_Position; 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) if (get_softmodem_params()->phy_test)
mac->state = UE_CONNECTED; mac->state = UE_CONNECTED;
else if (mac->state == UE_NOT_SYNC) { 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; dlsch_pdu->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon + 2;
} else { } else {
dlsch_pdu->SubcarrierSpacing = current_DL_BWP->scs; 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; dl_conf_req->pdu_type = FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH;
} else { } else {
dl_conf_req->pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH; 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); nr_timer_start(mac->data_inactivity_timer);
// DL data arrival during RRC_CONNECTED when UL synchronisation status is "non-synchronised" // 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) { 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; break;
} }
nr_ue_process_mac_pdu(mac, dl_info, pdu_id); 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); 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"); 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); EXTRACT_DCI_ITEM(dci_pdu_rel15->ss_pbch_index, 6);
// prach_mask_index 4 bits // prach_mask_index 4 bits
EXTRACT_DCI_ITEM(dci_pdu_rel15->prach_mask_index, 4); EXTRACT_DCI_ITEM(dci_pdu_rel15->prach_mask_index, 4);
trigger_MAC_UE_RA(mac, dci_pdu_rel15);
return true;
} // end if } // end if
else {
// Time domain assignment 4bit // Time domain assignment 4bit
EXTRACT_DCI_ITEM(dci_pdu_rel15->time_domain_assignment.val, 4); EXTRACT_DCI_ITEM(dci_pdu_rel15->time_domain_assignment.val, 4);
// VRB to PRB mapping 1bit // VRB to PRB mapping 1bit
EXTRACT_DCI_ITEM(dci_pdu_rel15->vrb_to_prb_mapping.val, 1); EXTRACT_DCI_ITEM(dci_pdu_rel15->vrb_to_prb_mapping.val, 1);
// MCS 5bit //bit over 32, so dci_pdu ++ // MCS 5bit //bit over 32, so dci_pdu ++
EXTRACT_DCI_ITEM(dci_pdu_rel15->mcs, 5); EXTRACT_DCI_ITEM(dci_pdu_rel15->mcs, 5);
// New data indicator 1bit // New data indicator 1bit
EXTRACT_DCI_ITEM(dci_pdu_rel15->ndi, 1); EXTRACT_DCI_ITEM(dci_pdu_rel15->ndi, 1);
// Redundancy version 2bit // Redundancy version 2bit
EXTRACT_DCI_ITEM(dci_pdu_rel15->rv, 2); EXTRACT_DCI_ITEM(dci_pdu_rel15->rv, 2);
// HARQ process number 4/5 bit // HARQ process number 4/5 bit
EXTRACT_DCI_ITEM(dci_pdu_rel15->harq_pid.val, dci_pdu_rel15->harq_pid.nbits); EXTRACT_DCI_ITEM(dci_pdu_rel15->harq_pid.val, dci_pdu_rel15->harq_pid.nbits);
// Downlink assignment index 2bit // Downlink assignment index 2bit
EXTRACT_DCI_ITEM(dci_pdu_rel15->dai[0].val, 2); EXTRACT_DCI_ITEM(dci_pdu_rel15->dai[0].val, 2);
// TPC command for scheduled PUCCH 2bit // TPC command for scheduled PUCCH 2bit
EXTRACT_DCI_ITEM(dci_pdu_rel15->tpc, 2); EXTRACT_DCI_ITEM(dci_pdu_rel15->tpc, 2);
// PUCCH resource indicator 3bit // PUCCH resource indicator 3bit
EXTRACT_DCI_ITEM(dci_pdu_rel15->pucch_resource_indicator, 3); EXTRACT_DCI_ITEM(dci_pdu_rel15->pucch_resource_indicator, 3);
// PDSCH-to-HARQ_feedback timing indicator 3bit // PDSCH-to-HARQ_feedback timing indicator 3bit
EXTRACT_DCI_ITEM(dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val, 3); EXTRACT_DCI_ITEM(dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val, 3);
} // end else return false;
} }
static void extract_00_c_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dci_pdu, int pos) 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); int n_RB = get_nrb_for_dci(mac, format, ss_type);
if (n_RB == 0) if (n_RB == 0)
return NR_DCI_NONE; 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 { else {
format = NR_UL_DCI_FORMAT_0_0; 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, static int nr_ue_validate_successrar(uint8_t *pduP,
int32_t pdu_len, int32_t pdu_len,
NR_UE_MAC_INST_t *mac, NR_UE_MAC_INST_t *mac,
uint8_t gNB_index, uint8_t gNB_index,
frame_t frameP, frame_t frameP,
int slot) int slot)
{ {
// TS 38.321 - Figure 6.1.5a-1: BI MAC subheader // TS 38.321 - Figure 6.1.5a-1: BI MAC subheader
// TS 38.321 - Figure 6.1.5a-3: SuccessRAR 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 E = 1;
uint8_t cont_res_id[6]; uint8_t cont_res_id[6];
RA_config_t *ra = &mac->ra; RA_config_t *ra = &mac->ra;
ra->RA_backoff_limit = 0;
while (n < pdu_len && E) { while (n < pdu_len && E) {
E = (pduP[n] >> 7) & 0x1; 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 if (SUCESS_RAR_header_T1 == 0) { // T2 exist
int SUCESS_RAR_header_T2 = (pduP[n] >> 5) & 0x1; int SUCESS_RAR_header_T2 = (pduP[n] >> 5) & 0x1;
if (SUCESS_RAR_header_T2 == 0) { // BI 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++; n++;
} else { // S } else { // S
n++; 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); bool ra_success = check_ra_contention_resolution(cont_res_id, ra->cont_res_id);
if (ra->RA_active && ra_success) { if (ra->RA_active && ra_success) {
nr_timer_stop(&ra->response_window_timer);
nr_ra_succeeded(mac, gNB_index, frameP, slot); nr_ra_succeeded(mac, gNB_index, frameP, slot);
} else if (!ra_success) { } else if (!ra_success) {
// nr_ra_failed(mac, CC_id, &ra->prach_resources, frameP, slot); nr_ra_backoff_setting(ra);
ra->ra_state = nrRA_UE_IDLE;
ra->RA_active = 0;
} }
} }
} else { // RAPID } 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; mac_len = 6;
if (ra->ra_state == nrRA_WAIT_CONTENTION_RESOLUTION) { 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, mac->ue_id,
frameP, frameP,
pduP[1], 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[5],
pduP[6]); pduP[6]);
nr_timer_stop(&ra->contention_resolution_timer);
bool ra_success = check_ra_contention_resolution(&pduP[1], ra->cont_res_id); bool ra_success = check_ra_contention_resolution(&pduP[1], ra->cont_res_id);
if (ra->RA_active && ra_success) { if (ra->RA_active && ra_success) {
nr_ra_succeeded(mac, gNB_index, frameP, slot); nr_ra_succeeded(mac, gNB_index, frameP, slot);
} else if (!ra_success) { } else if (!ra_success) {
// TODO: Handle failure of RA procedure @ MAC layer // consider this Contention Resolution not successful and discard the successfully decoded MAC PDU
// nr_ra_failed(module_idP, CC_id, prach_resources, frameP, slot); // prach_resources is a PHY structure nr_ra_contention_resolution_failed(mac);
ra->ra_state = nrRA_UE_IDLE; return;
ra->RA_active = false;
} }
} }
break; 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 * Function: generating MAC CEs (MAC CE and subheader) for the ULSCH PDU
* Parameters: * Parameters:
@@ -3848,6 +3860,117 @@ int nr_write_ce_ulsch_pdu(uint8_t *mac_ce,
return mac_ce - pdu; 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 // // Random Access Response PDU //
// TS 38.213 ch 8.2 // // 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_config_t *ra = &mac->ra;
ra->t_crnti = 0;
uint8_t n_subPDUs = 0; // number of RAR payloads uint8_t n_subPDUs = 0; // number of RAR payloads
uint8_t n_subheaders = 0; // number of MAC RAR subheaders 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 *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_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 NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 1); // RAR subPDU pointer
uint8_t preamble_index = ra->ra_PreambleIndex; 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(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)); 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) { while (1) {
n_subheaders++; 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++; n_subPDUs++;
LOG_I(NR_MAC, "[UE %d][RAPROC][RA-RNTI %04x] Got RAPID RAR subPDU\n", mac->ue_id, rnti); LOG_I(NR_MAC, "[UE %d][RAPROC][RA-RNTI %04x] Got RAPID RAR subPDU\n", mac->ue_id, rnti);
} else { } else {
ra->RA_backoff_indicator = get_backoff_indicator(((NR_RA_HEADER_BI *)rarh)->BI); int bi_ms = table_7_2_1[((NR_RA_HEADER_BI *)rarh)->BI] * ra->scaling_factor_bi;
ra->RA_BI_found = 1; int slots_per_ms = mac->frame_structure.numb_slots_frame / 10;
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); ra->RA_backoff_limit = bi_ms * slots_per_ms;
if ( ((NR_RA_HEADER_BI *)rarh)->E == 1) { 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); rarh += sizeof(NR_RA_HEADER_BI);
continue; continue;
} else { } 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) { 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); 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)); 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) { if (get_softmodem_params()->emulate_l1) {
/* When we are emulating L1 with multiple UEs, the rx_indication will have /* 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, 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, slot,
rarh->RAPID, rarh->RAPID,
preamble_index); preamble_index);
// resume RAR response window timer if MSG2 decoding failed
nr_timer_suspension(&mac->ra.response_window_timer);
break; break;
} else { } else {
rarh += sizeof(NR_MAC_RAR) + 1; 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, rarh->RAPID,
preamble_index); preamble_index);
#endif #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; return;
} }
+133 -669
View File
@@ -182,17 +182,26 @@ void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac)
// TODO not sure what to do here // 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) { if (mac->data_inactivity_timer) {
bool inactivity_timer_expired = nr_timer_tick(mac->data_inactivity_timer); bool inactivity_timer_expired = nr_timer_tick(mac->data_inactivity_timer);
if (inactivity_timer_expired) if (inactivity_timer_expired)
nr_mac_rrc_inactivity_timer_ind(mac->ue_id); nr_mac_rrc_inactivity_timer_ind(mac->ue_id);
} }
bool alignment_timer_expired = nr_timer_tick(&mac->time_alignment_timer); bool contention_resolution_expired = nr_timer_tick(&mac->ra.contention_resolution_timer);
if (alignment_timer_expired) if (contention_resolution_expired)
handle_time_alignment_timer_expired(mac); nr_ra_contention_resolution_failed(mac);
nr_timer_tick(&mac->ra.contention_resolution_timer);
for (int j = 0; j < NR_MAX_SR_ID; j++) 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_info[j].prohibitTimer);
nr_timer_tick(&mac->scheduling_info.sr_DelayTimer); 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); 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) 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) if (get_softmodem_params()->phy_test)
return; // cannot trigger RA in phytest mode 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 PUCCH for all Serving Cells;
// release SRS for all Serving Cells; // release SRS for all Serving Cells;
release_PUCCH_SRS(mac); 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_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; 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 return; // cannot schedule SR if there is no schedulingRequestResource configured
if (lc_info->sr_id < 0 || lc_info->sr_id >= NR_MAX_SR_ID) 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; uint32_t gNB_index = ul_info->gNB_index;
RA_config_t *ra = &mac->ra; 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); if (mac->state == UE_PERFORMING_RA && ra->ra_state == nrRA_UE_IDLE) {
nr_ue_prach_scheduler(mac, frame_tx, slot_tx); 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; bool BSRsent = false;
if (mac->state == UE_CONNECTED) { if (mac->state == UE_CONNECTED) {
nr_ue_periodic_srs_scheduling(mac, frame_tx, slot_tx); 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))) { && (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) { 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" // 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; return;
} }
// Getting IP traffic to be transmitted // Getting IP traffic to be transmitted
@@ -1561,547 +1595,6 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac,
return 0; 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, static bool schedule_uci_on_pusch(NR_UE_MAC_INST_t *mac,
frame_t frame_tx, frame_t frame_tx,
int slot_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 // 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. // PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3.
// - todo: // - 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) 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_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; 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)) { if (is_ul_slot(slotP, &mac->frame_structure)) {
// WIP Need to get the proper selected ssb_idx if (slotP == prach_occasion_info->slot) {
// 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
fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frameP, slotP, FAPI_NR_UL_CONFIG_TYPE_PRACH); fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frameP, slotP, FAPI_NR_UL_CONFIG_TYPE_PRACH);
if (!pdu) { if (!pdu) {
LOG_E(NR_MAC, "Error in PRACH allocation\n"); LOG_E(NR_MAC, "Error in PRACH allocation\n");
return; 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){ pdu->prach_config_pdu = (fapi_nr_ul_config_prach_pdu){
.phys_cell_id = mac->physCellId, .phys_cell_id = mac->physCellId,
.num_prach_ocas = 1, .num_prach_ocas = 1,
.prach_slot = prach_occasion_info_p->slot, .prach_slot = prach_occasion_info->slot,
.prach_start_symbol = prach_occasion_info_p->start_symbol, .prach_start_symbol = prach_occasion_info->start_symbol,
.num_ra = prach_occasion_info_p->fdm, .num_ra = prach_occasion_info->fdm,
.num_cs = ncs, .num_cs = get_NCS(ra->zeroCorrelationZoneConfig, format, ra->restricted_set_config),
.root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].prach_root_sequence_index, .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, .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, LOG_I(NR_MAC,
"PRACH scheduler: Selected RO Frame %u, Slot %u, Symbol %u, Fdm %u\n", "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.prach_start_symbol,
pdu->prach_config_pdu.num_ra); pdu->prach_config_pdu.num_ra);
// Search which SSB is mapped in the RO (among all the SSBs mapped to this RO) switch (format) { // single PRACH format
for (int ssb_nb_in_ro=0; ssb_nb_in_ro<prach_occasion_info_p->nb_mapped_ssb; ssb_nb_in_ro++) { case 0:
if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb_in_ro] == selected_gnb_ssb_idx) { pdu->prach_config_pdu.prach_format = 0;
ra->ssb_nb_in_ro = ssb_nb_in_ro;
break; break;
} case 1:
pdu->prach_config_pdu.prach_format = 1;
break;
case 2:
pdu->prach_config_pdu.prach_format = 2;
break;
case 3:
pdu->prach_config_pdu.prach_format = 3;
break;
case 0xa1:
pdu->prach_config_pdu.prach_format = 4;
break;
case 0xa2:
pdu->prach_config_pdu.prach_format = 5;
break;
case 0xa3:
pdu->prach_config_pdu.prach_format = 6;
break;
case 0xb1:
pdu->prach_config_pdu.prach_format = 7;
break;
case 0xb4:
pdu->prach_config_pdu.prach_format = 8;
break;
case 0xc0:
pdu->prach_config_pdu.prach_format = 9;
break;
case 0xc2:
pdu->prach_config_pdu.prach_format = 10;
break;
default:
AssertFatal(false, "Invalid PRACH format");
} }
AssertFatal(ra->ssb_nb_in_ro<prach_occasion_info_p->nb_mapped_ssb, "%u not found in the mapped SSBs to the PRACH occasion", selected_gnb_ssb_idx);
if (format1 != 0xff) {
switch (format0) { // dual PRACH format
case 0xa1:
pdu->prach_config_pdu.prach_format = 11;
break;
case 0xa2:
pdu->prach_config_pdu.prach_format = 12;
break;
case 0xa3:
pdu->prach_config_pdu.prach_format = 13;
break;
default:
AssertFatal(1 == 0, "Only formats A1/B1 A2/B2 A3/B3 are valid for dual format");
}
} else {
switch (format0) { // single PRACH format
case 0:
pdu->prach_config_pdu.prach_format = 0;
break;
case 1:
pdu->prach_config_pdu.prach_format = 1;
break;
case 2:
pdu->prach_config_pdu.prach_format = 2;
break;
case 3:
pdu->prach_config_pdu.prach_format = 3;
break;
case 0xa1:
pdu->prach_config_pdu.prach_format = 4;
break;
case 0xa2:
pdu->prach_config_pdu.prach_format = 5;
break;
case 0xa3:
pdu->prach_config_pdu.prach_format = 6;
break;
case 0xb1:
pdu->prach_config_pdu.prach_format = 7;
break;
case 0xb4:
pdu->prach_config_pdu.prach_format = 8;
break;
case 0xc0:
pdu->prach_config_pdu.prach_format = 9;
break;
case 0xc2:
pdu->prach_config_pdu.prach_format = 10;
break;
default:
AssertFatal(1 == 0, "Invalid PRACH format");
}
} // if format1
nr_get_prach_resources(mac, 0, 0, &ra->prach_resources, ra->rach_ConfigDedicated);
pdu->prach_config_pdu.ra_PreambleIndex = ra->ra_PreambleIndex; pdu->prach_config_pdu.ra_PreambleIndex = ra->ra_PreambleIndex;
pdu->prach_config_pdu.prach_tx_power = get_prach_tx_power(mac); 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); release_ul_config(pdu, false);
nr_scheduled_response_t scheduled_response = {.ul_config = mac->ul_config_request + slotP, nr_scheduled_response_t scheduled_response = {.ul_config = mac->ul_config_request + slotP,
.mac = mac, .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(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)); 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) { 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) { } else if (ra->ra_type == RA_2_STEP) {
NR_MsgA_PUSCH_Resource_r16_t *msgA_PUSCH_Resource = NR_MsgA_PUSCH_Resource_r16_t *msgA_PUSCH_Resource =
mac->current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16; 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; slot_t msgA_pusch_slot = (slotP + msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16) % n_slots_frame;
frame_t msgA_pusch_frame = frame_t msgA_pusch_frame =
(frameP + ((slotP + msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16) / n_slots_frame)) % 1024; (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); remove_ul_config_last_item(pdu);
release_ul_config(pdu, false); 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]); LOG_D(NR_MAC, "ra->ra_state %s\n", nrra_ue_text[ra->ra_state]);
ra->ra_state = nrRA_WAIT_MSGB; ra->ra_state = nrRA_WAIT_MSGB;
ra->t_crnti = 0; 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 { } else {
AssertFatal(false, "RA type %d not implemented!\n", ra->ra_type); AssertFatal(false, "RA type %d not implemented!\n", ra->ra_type);
} }
// rnti = ra->t_crnti;
} // is_nr_prach_slot } // is_nr_prach_slot
} // if is_nr_UL_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; 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_frame = ul_time_alignment->frame;
ta->ta_slot = ul_time_alignment->slot; 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->is_rar = ul_time_alignment->ta_apply == rar_ta;
ta->ta_command = ul_time_alignment->ta_command; ta->ta_command = ul_time_alignment->ta_command;
dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_CONFIG_TA_COMMAND; dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_CONFIG_TA_COMMAND;
@@ -192,8 +192,6 @@ TEST(pusch_power_control, pusch_power_control_msg3)
current_UL_BWP.BWPSize = 106; current_UL_BWP.BWPSize = 106;
current_UL_BWP.channel_bandwidth = 40; current_UL_BWP.channel_bandwidth = 40;
mac.current_UL_BWP = &current_UL_BWP; mac.current_UL_BWP = &current_UL_BWP;
NR_RACH_ConfigCommon_t nr_rach_ConfigCommon = {0};
current_UL_BWP.rach_ConfigCommon = &nr_rach_ConfigCommon;
mac.nr_band = 78; mac.nr_band = 78;
NR_PUSCH_Config_t pusch_Config = {0}; NR_PUSCH_Config_t pusch_Config = {0};
current_UL_BWP.pusch_Config = &pusch_Config; current_UL_BWP.pusch_Config = &pusch_Config;
@@ -229,8 +227,8 @@ TEST(pusch_power_control, pusch_power_control_msg3)
num_rb, num_rb,
start_prb); start_prb);
long preambleReceivedTargetPower = -96; int preambleReceivedTargetPower = -96;
nr_rach_ConfigCommon.rach_ConfigGeneric.preambleReceivedTargetPower = preambleReceivedTargetPower; mac.ra.prach_resources.ra_preamble_rx_target_power = preambleReceivedTargetPower;
int power = get_pusch_tx_power_ue(&mac, int power = get_pusch_tx_power_ue(&mac,
num_rb, num_rb,
@@ -247,7 +245,7 @@ TEST(pusch_power_control, pusch_power_control_msg3)
false); false);
EXPECT_EQ(power, -84); EXPECT_EQ(power, -84);
EXPECT_LT(power, P_CMAX); 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, int reduced_power = get_pusch_tx_power_ue(&mac,
num_rb, num_rb,
@@ -372,8 +370,6 @@ TEST(pusch_power_control, pusch_power_control_state_initialization)
current_UL_BWP.BWPSize = 106; current_UL_BWP.BWPSize = 106;
current_UL_BWP.channel_bandwidth = 40; current_UL_BWP.channel_bandwidth = 40;
mac.current_UL_BWP = &current_UL_BWP; mac.current_UL_BWP = &current_UL_BWP;
NR_RACH_ConfigCommon_t nr_rach_ConfigCommon = {0};
current_UL_BWP.rach_ConfigCommon = &nr_rach_ConfigCommon;
mac.nr_band = 78; mac.nr_band = 78;
NR_PUSCH_Config_t pusch_Config = {0}; NR_PUSCH_Config_t pusch_Config = {0};
current_UL_BWP.pusch_Config = &pusch_Config; 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; uint32_t sum_bits_in_codeblocks = 56;
int delta_pusch = 0; int delta_pusch = 0;
bool is_rar_tx_retx = true; bool is_rar_tx_retx = true;
long preambleReceivedTargetPower = -96; int preambleReceivedTargetPower = -96;
nr_rach_ConfigCommon.rach_ConfigGeneric.preambleReceivedTargetPower = preambleReceivedTargetPower; mac.ra.prach_resources.ra_preamble_rx_target_power = preambleReceivedTargetPower;
get_pusch_tx_power_ue(&mac, get_pusch_tx_power_ue(&mac,
num_rb, num_rb,
@@ -29,20 +29,11 @@ softmodem_params_t *get_softmodem_params(void)
{ {
return &softmodem_params; 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, void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, bool prepare_payload)
NR_UE_MAC_INST_t *mac,
NR_SINGLE_ENTRY_PHR_MAC_CE *power_headroom,
const type_bsr_t *bsr,
uint8_t *mac_ce_end)
{ {
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, tbs_size_t mac_rlc_data_req(const module_id_t module_idP,
const rnti_t rntiP, const rnti_t rntiP,
@@ -77,6 +68,14 @@ int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac,
{ {
return 0; return 0;
} }
NR_UE_DL_BWP_t *get_dl_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup)
{
return NULL;
}
NR_UE_UL_BWP_t *get_ul_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup)
{
return NULL;
}
} }
#include <cstdio> #include <cstdio>
#include "common/utils/LOG/log.h" #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) TEST(test_init_ra, four_step_cbra)
{ {
NR_UE_MAC_INST_t mac = {0}; 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_ConfigCommon_t nr_rach_ConfigCommon = {0};
NR_RACH_ConfigGeneric_t rach_ConfigGeneric = {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_UL_BWP_t current_bwp;
NR_UE_DL_BWP_t dl_bwp;
mac.current_UL_BWP = &current_bwp; mac.current_UL_BWP = &current_bwp;
mac.current_DL_BWP = &dl_bwp;
mac.mib_ssb = 0;
long scs = 1; long scs = 1;
current_bwp.scs = scs; current_bwp.scs = scs;
current_bwp.bwp_id = 0;
dl_bwp.bwp_id = 0;
current_bwp.channel_bandwidth = 40; current_bwp.channel_bandwidth = 40;
nr_rach_ConfigCommon.msg1_SubcarrierSpacing = &scs; 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.p_Max = 23;
mac.nr_band = 78; mac.nr_band = 78;
mac.frame_structure.frame_type = TDD; mac.frame_structure.frame_type = TDD;
mac.frame_structure.numb_slots_frame = 20;
mac.frequency_range = FR1; 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.ra.ra_type, RA_4_STEP);
EXPECT_EQ(mac.state, UE_PERFORMING_RA); 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) TEST(test_init_ra, four_step_cfra)
{ {
NR_UE_MAC_INST_t mac = {0}; 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_ConfigCommon_t nr_rach_ConfigCommon = {0};
NR_RACH_ConfigGeneric_t rach_ConfigGeneric = {0}; NR_RACH_ConfigGeneric_t rach_ConfigGeneric = {0};
NR_UE_UL_BWP_t current_bwp; NR_UE_UL_BWP_t current_bwp;
NR_UE_DL_BWP_t dl_bwp;
mac.current_UL_BWP = &current_bwp; mac.current_UL_BWP = &current_bwp;
mac.current_DL_BWP = &dl_bwp;
mac.mib_ssb = 0;
long scs = 1; long scs = 1;
current_bwp.scs = scs; current_bwp.scs = scs;
current_bwp.bwp_id = 0;
dl_bwp.bwp_id = 0;
current_bwp.channel_bandwidth = 40; current_bwp.channel_bandwidth = 40;
nr_rach_ConfigCommon.msg1_SubcarrierSpacing = &scs; 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.p_Max = 23;
mac.nr_band = 78; mac.nr_band = 78;
mac.frame_structure.frame_type = TDD; mac.frame_structure.frame_type = TDD;
mac.frame_structure.numb_slots_frame = 20;
mac.frequency_range = FR1; mac.frequency_range = FR1;
int frame = 151;
NR_RACH_ConfigDedicated_t rach_ConfigDedicated = {0}; NR_RACH_ConfigDedicated_t rach_ConfigDedicated = {0};
struct NR_CFRA cfra; NR_CFRA_t cfra;
rach_ConfigDedicated.cfra = &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.ra.ra_type, RA_4_STEP);
EXPECT_EQ(mac.state, UE_PERFORMING_RA); EXPECT_EQ(mac.state, UE_PERFORMING_RA);
+1 -2
View File
@@ -521,8 +521,7 @@ static void config_common(gNB_MAC_INST *nrmac,
// If absent, use SCS as derived from the prach-ConfigurationIndex (for 839) // If absent, use SCS as derived from the prach-ConfigurationIndex (for 839)
int config_index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; int config_index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex;
int frame_type = get_frame_type(band, frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing); 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 = get_nr_prach_format_from_index(config_index, UL_pointA, frame_type) & 0xff;
int format = prach_config_info_p[0];
cfg->prach_config.prach_sub_c_spacing.value = get_delta_f_RA_long(format); cfg->prach_config.prach_sub_c_spacing.value = get_delta_f_RA_long(format);
} }
+42 -80
View File
@@ -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]; float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value];
uint16_t start_symbol_index = 0; 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; uint8_t temp_start_symbol = 0;
uint16_t format,RA_sfn_index = -1; uint16_t RA_sfn_index = -1;
uint8_t config_period = 1;
uint16_t prach_occasion_id = -1; uint16_t prach_occasion_id = -1;
uint8_t num_active_ssb = cc->num_active_ssb; uint8_t num_active_ssb = cc->num_active_ssb;
NR_MsgA_ConfigCommon_r16_t *msgacc = NULL; 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; 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 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); 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; uint8_t index = 0, slot_index = 0;
for (slot_index = 0; slot_index < N_RA_slot; slot_index++) { for (slot_index = 0; slot_index < cc->prach_info.N_RA_slot; slot_index++) {
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)) 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++) { for (int i = 0; i < cc->prach_info.N_t_slot; i++) {
temp_start_symbol = (start_symbol + i * N_dur + 14 * slot_index) % 14; temp_start_symbol = (cc->prach_info.start_symbol + i * cc->prach_info.N_dur + 14 * slot_index) % 14;
if(symbol == temp_start_symbol) { if(symbol == temp_start_symbol) {
start_symbol_index = i; start_symbol_index = i;
break; 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)) 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 = 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) + prach_occasion_id =
(RA_sfn_index + slot_index) * N_t_slot * fdm + start_symbol_index * fdm + freq_index; (((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 //one SSB have more than one continuous RO
if(num_ssb_per_RO <= 1) 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]; nfapi_nr_config_request_scf_t *cfg = &nrmac->config[0];
NR_RACH_ConfigCommon_t *rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; 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 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 unused_RA_occasion, repetition = 0;
uint16_t format,N_RA_sfn = 0,unused_RA_occasion,repetition = 0;
uint8_t num_active_ssb = 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; 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: case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth:
cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1); cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1);
break; break;
@@ -194,31 +181,16 @@ void find_SSB_and_RO_available(gNB_MAC_INST *nrmac)
default: default:
AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present); AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present);
break; 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 // 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, frequency_range_t freq_range = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA > 2016666 ? FR2 : FR1;
scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, nr_prach_info_t prach_info = get_nr_prach_occasion_info_from_index(config_index, freq_range, cc->frame_type);
mu,
cc->frame_type,
&format,
&start_symbol,
&N_t_slot,
&N_dur,
&N_RA_slot,
&N_RA_sfn,
&max_association_period);
float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value]; 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; 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; 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++) { 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 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; 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)); cc->max_association_period = (1 << (i - 1));
total_RA_occasions = total_RA_occasions * cc->max_association_period; total_RA_occasions = total_RA_occasions * cc->max_association_period;
if(total_RA_occasions >= (int) (num_active_ssb / num_ssb_per_RO)) { 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); 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->total_prach_occasions = total_RA_occasions - unused_RA_occasion;
cc->num_active_ssb = num_active_ssb; cc->num_active_ssb = num_active_ssb;
cc->prach_info = prach_info;
LOG_D(NR_MAC, 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->total_prach_occasions,
cc->num_active_ssb, cc->num_active_ssb,
unused_RA_occasion, unused_RA_occasion,
cc->max_association_period, cc->max_association_period,
N_RA_sfn, prach_info.N_RA_sfn,
cc->total_prach_occasions_per_config_period); 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)) { if (is_ul_slot(slotP, &RC.nrmac[module_idP]->frame_structure)) {
const NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &rach_ConfigCommon->rach_ConfigGeneric; const NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &rach_ConfigCommon->rach_ConfigGeneric;
uint8_t config_index = rach_ConfigGeneric->prach_ConfigurationIndex; 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; int slot_index = 0;
uint16_t prach_occasion_id = -1; 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 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); 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 // 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, uint16_t RA_sfn_index = -1;
(int)frameP, frequency_range_t freq_range = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA > 2016666 ? FR2 : FR1;
(int)slotP, if (get_nr_prach_sched_from_info(cc->prach_info, config_index, frameP, slotP, mu, freq_range, &RA_sfn_index, cc->frame_type)) {
scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, uint16_t format0 = cc->prach_info.format & 0xff; // first column of format from table
mu, uint16_t format1 = (cc->prach_info.format >> 8) & 0xff; // second column of format from table
cc->frame_type,
&format,
&start_symbol,
&N_t_slot,
&N_dur,
&RA_sfn_index,
&N_RA_slot,
&config_period)) {
uint16_t format0 = format & 0xff; // first column of format from table if (cc->prach_info.N_RA_slot > 1) { // more than 1 PRACH slot in a subframe
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 (slotP % 2 == 1) if (slotP % 2 == 1)
slot_index = 1; slot_index = 1;
else else
slot_index = 0; 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; 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->Slot = slotP;
UL_tti_req->rach_present = 1; UL_tti_req->rach_present = 1;
NR_beam_alloc_t beam = {0}; 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 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++) { 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) + 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; (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 // filling the prach fapi structure
prach_pdu->phys_cell_id = *scc->physCellId; prach_pdu->phys_cell_id = *scc->physCellId;
prach_pdu->num_prach_ocas = N_t_slot; 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_ra = fdm_index;
prach_pdu->num_cs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, prach_pdu->num_cs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig,
format0, format0,
@@ -499,7 +460,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
slotP, slotP,
prach_occasion_id, prach_occasion_id,
prach_pdu->num_ra, prach_pdu->num_ra,
prach_pdu->prach_start_symbol, start_symb,
slot_index, slot_index,
RA_sfn_index); RA_sfn_index);
// SCF PRACH PDU format field does not consider A1/B1 etc. possibilities // 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); 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 // mark PRBs as occupied for current and future slots if prach extends beyond current slot
int total_prach_slots; int total_prach_slots;
uint32_t N_dur = cc->prach_info.N_dur;
if (format0 < 4) { if (format0 < 4) {
N_dur = 14; // number of PRACH symbols in PRACH slot N_dur = 14; // number of PRACH symbols in PRACH slot
total_prach_slots = get_long_prach_dur(format0, mu_pusch); total_prach_slots = get_long_prach_dur(format0, mu_pusch);
AssertFatal(slotP + total_prach_slots - 1 < slots_frame, "PRACH cannot extend across frames\n"); AssertFatal(slotP + total_prach_slots - 1 < slots_frame, "PRACH cannot extend across frames\n");
} else { } 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; total_prach_slots = 1;
} }
// reserve PRBs occupied by PRACH in all PRACH slot. // 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, gNB->vrb_map_UL_size,
slots_frame, slots_frame,
bwp_start + rach_ConfigGeneric->msg1_FrequencyStart, bwp_start + rach_ConfigGeneric->msg1_FrequencyStart,
start_symbol, start_symb,
N_t_slot * N_dur, N_t_slot * N_dur,
cc); cc);
} }
@@ -1413,6 +1373,8 @@ static bool msg2_in_response_window(int rach_frame,
int current_slot) int current_slot)
{ {
int window_slots = get_response_window(rrc_ra_ResponseWindow); 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_rach = n_slots_frame * rach_frame + rach_slot;
int abs_now = n_slots_frame * current_frame + current_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); int diff = (n_slots_frame * 1024 + abs_now - abs_rach) % (n_slots_frame * 1024);
+1
View File
@@ -302,6 +302,7 @@ typedef struct {
int cb_preambles_per_ssb; int cb_preambles_per_ssb;
/// Max prach length in slots /// Max prach length in slots
int prach_len; int prach_len;
nr_prach_info_t prach_info;
} NR_COMMON_channels_t; } NR_COMMON_channels_t;
// SP ZP CSI-RS Resource Set Activation/Deactivation MAC CE // SP ZP CSI-RS Resource Set Activation/Deactivation MAC CE
+18 -8
View File
@@ -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 already. Only once the RA procedure succeeds is the CRNTI value updated
to the TC_RNTI. */ to the TC_RNTI. */
if (get_softmodem_params()->nsa) { if (get_softmodem_params()->nsa) {
if (received_pdu->RNTI != mac->crnti && if (received_pdu->RNTI != mac->crnti && (received_pdu->RNTI != mac->ra.ra_rnti))
(received_pdu->RNTI != mac->ra.ra_rnti || mac->ra.RA_RAPID_found))
return false; return false;
} }
if (IS_SA_MODE(get_softmodem_params())) { 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 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 // if the C-RNTI MAC CE was included in Msg3
// consider this Contention Resolution successful // 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); 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); 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; ret_mask |= (handle_dlsch(mac, dl_info, i)) << FAPI_NR_RX_PDU_TYPE_DLSCH;
break; break;
case FAPI_NR_RX_PDU_TYPE_RAR: 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"); 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"); LOG_I(PHY, "RAR-Msg2 decoded\n");
}
ret_mask |= (handle_dlsch(mac, dl_info, i)) << FAPI_NR_RX_PDU_TYPE_RAR;
break; break;
case FAPI_NR_CSIRS_IND: case FAPI_NR_CSIRS_IND:
ret_mask |= (handle_csirs_measurements(mac, ret_mask |= (handle_csirs_measurements(mac,
@@ -1330,12 +1337,15 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info)
return ret2; 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); NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
int ret = pthread_mutex_lock(&mac->if_mutex); int ret = pthread_mutex_lock(&mac->if_mutex);
AssertFatal(!ret, "mutex failed %d\n", ret); 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); ret = pthread_mutex_unlock(&mac->if_mutex);
AssertFatal(!ret, "mutex failed %d\n", ret); AssertFatal(!ret, "mutex failed %d\n", ret);
} }
+1 -1
View File
@@ -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 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 * Generic type of an application-defined callback to return various
+1 -5
View File
@@ -3819,11 +3819,7 @@ NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t u
uplink->ra_Prioritization = NULL; uplink->ra_Prioritization = NULL;
uplink->cfra = calloc(1, sizeof(struct NR_CFRA)); uplink->cfra = calloc(1, sizeof(struct NR_CFRA));
uplink->cfra->ext1 = NULL; uplink->cfra->ext1 = NULL;
uplink->cfra->occasions = calloc(1, sizeof(struct NR_CFRA__occasions)); uplink->cfra->occasions = NULL;
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->resources.present = NR_CFRA__resources_PR_ssb; 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 = calloc(1, sizeof(struct NR_CFRA__resources__ssb));
uplink->cfra->resources.choice.ssb->ra_ssb_OccasionMaskIndex = 0; uplink->cfra->resources.choice.ssb->ra_ssb_OccasionMaskIndex = 0;
+3 -4
View File
@@ -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); 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); 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).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); 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); 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); 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; 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); itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(mod_id), message_p);
} }
+2 -2
View File
@@ -37,9 +37,9 @@ void nr_mac_rrc_data_ind_ue(const module_id_t module_id,
const uint8_t* pduP, const uint8_t* pduP,
const sdu_size_t pdu_len); const sdu_size_t pdu_len);
void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id); 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_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 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); void process_msg_rcc_to_mac(MessageDef *msg);
#endif #endif
+43 -17
View File
@@ -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; SI_info->sib1_validity = SIB_VALID;
if (rrc->nrRrcState == RRC_STATE_IDLE_NR) { if (rrc->nrRrcState == RRC_STATE_IDLE_NR) {
rrc->ra_trigger = RRC_CONNECTION_SETUP; 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; 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); nr_timer_stop(&timers->T311);
rrc->ra_trigger = RRC_CONNECTION_REESTABLISHMENT; 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 // apply the default MAC Cell Group configuration
// (done at MAC by calling nr_ue_mac_default_configs) // (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; 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) 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; 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); nr_timer_stop(&timers->T304);
// TODO handle the rest of procedures as described in 5.3.5.3 for when // TODO handle the rest of procedures as described in 5.3.5.3 for when
// reconfigurationWithSync is included in spCellConfig // 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; break;
case NR_RRC_MAC_MSG3_IND: 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; break;
case NR_RRC_MAC_RA_IND: case NR_RRC_MAC_RA_IND:
LOG_D(NR_RRC, LOG_D(NR_RRC,
"[UE %ld] Received %s: frame %d RA %s\n", "[UE %ld] Received %s: RA %s\n",
rrc->ue_id, rrc->ue_id,
ITTI_MSG_NAME(msg_p), ITTI_MSG_NAME(msg_p),
NR_RRC_MAC_RA_IND(msg_p).frame, NR_RRC_MAC_RA_IND(msg_p).RA_succeeded ? "successful" : "failed");
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); nr_rrc_handle_ra_indication(rrc, NR_RRC_MAC_RA_IND(msg_p).RA_succeeded);
break; break;