mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
Use two queues for PRACH processing: - prach_ru_queue: pass jobs from TX thread (scheduler) to RU thread. For split 8, the RU thread itself handles PRACH processing; for split 7.2, it is the library that is responsible for handling PRACH messages (see oran_fh_if4p5_south_in()) - prach_l1rx_queue: after jobs have been handled in RU thread, use this queue to pass jobs to the RX thread. There, preamble detection is performed, and RACH.indication FAPI messages are filled if a preamble has been detected. Together, these queues replace a linear search in a global array that has been modified by three threads at the same time. The design ensures that access now is thread-safe, and with less overhead. Signed-off-by: Robert Schmidt <robert.schmidt@openairinterface.org>
100 lines
4.1 KiB
C
100 lines
4.1 KiB
C
/*
|
|
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
|
*/
|
|
|
|
/*!
|
|
* \brief Implementation of gNB prach procedures from 38.213 LTE specifications
|
|
*/
|
|
|
|
#include "PHY/defs_gNB.h"
|
|
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
|
#include "nfapi_nr_interface_scf.h"
|
|
#include "nfapi_pnf.h"
|
|
#include "common/utils/LOG/log.h"
|
|
#include "assertions.h"
|
|
#include <time.h>
|
|
|
|
int get_nr_prach_duration(uint8_t prach_format)
|
|
{
|
|
const int val[14] = {0, 0, 0, 0, 2, 4, 6, 2, 12, 2, 6, 2, 4, 6};
|
|
AssertFatal(prach_format < sizeofArray(val), "Invalid Prach format %d\n", prach_format);
|
|
return val[prach_format];
|
|
}
|
|
|
|
void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, prach_item_t *prach_id, nfapi_nr_rach_indication_t *rach_ind)
|
|
{
|
|
const frame_t frame = prach_id->frame;
|
|
const slot_t slot = prach_id->slot;
|
|
rach_ind->sfn = frame;
|
|
rach_ind->slot = slot;
|
|
nfapi_nr_prach_pdu_t *prach_pdu = &prach_id->pdu;
|
|
LOG_D(NR_PHY_RACH, "%d.%d, prachstart slot %d prach entry occas %d\n", frame, slot, prach_id->slot, prach_pdu->num_prach_ocas);
|
|
int N_dur = get_nr_prach_duration(prach_pdu->prach_format);
|
|
|
|
for (int prach_oc = 0; prach_oc < prach_pdu->num_prach_ocas; prach_oc++) {
|
|
uint prachStartSymbol = prach_pdu->prach_start_symbol + prach_oc * N_dur;
|
|
// comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is
|
|
// given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots
|
|
// where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}.
|
|
rx_prach_out_t res = rx_nr_prach(prach_id, prach_oc);
|
|
LOG_D(NR_PHY,
|
|
"[RAPROC] Frame %d, slot %d, occasion %d (prachStartSymbol %d) : Most likely preamble %d, energy %d.%d dB delay %d "
|
|
"(prach_energy counter %d)\n",
|
|
frame,
|
|
slot,
|
|
prach_oc,
|
|
prachStartSymbol,
|
|
res.max_preamble,
|
|
res.max_preamble_energy / 10,
|
|
res.max_preamble_energy % 10,
|
|
res.max_preamble_delay,
|
|
gNB->prach_energy_counter);
|
|
|
|
if ((gNB->prach_energy_counter == NUM_PRACH_RX_FOR_NOISE_ESTIMATE)
|
|
&& (res.max_preamble_energy > gNB->measurements.prach_I0 + gNB->prach_thres)
|
|
&& (rach_ind->number_of_pdus < MAX_NUM_NR_RX_RACH_PDUS)) {
|
|
LOG_A(NR_PHY,
|
|
"[RAPROC] %d.%d Initiating RA procedure with preamble %d, energy %d.%d dB (I0 %d, thres %d), delay %d start symbol "
|
|
"%u freq index %u\n",
|
|
frame,
|
|
slot,
|
|
res.max_preamble,
|
|
res.max_preamble_energy / 10,
|
|
res.max_preamble_energy % 10,
|
|
gNB->measurements.prach_I0,
|
|
gNB->prach_thres,
|
|
res.max_preamble_delay,
|
|
prachStartSymbol,
|
|
prach_pdu->num_ra);
|
|
|
|
T(T_ENB_PHY_INITIATE_RA_PROCEDURE,
|
|
T_INT(gNB->Mod_id),
|
|
T_INT(frame),
|
|
T_INT(slot),
|
|
T_INT(res.max_preamble),
|
|
T_INT(res.max_preamble_energy),
|
|
T_INT(res.max_preamble_delay));
|
|
|
|
nfapi_nr_prach_indication_pdu_t *ind = rach_ind->pdu_list + rach_ind->number_of_pdus;
|
|
*ind = (nfapi_nr_prach_indication_pdu_t){
|
|
.phy_cell_id = gNB->gNB_config.cell_config.phy_cell_id.value,
|
|
.symbol_index = prachStartSymbol,
|
|
.slot_index = slot,
|
|
.freq_index = prach_pdu->num_ra,
|
|
.avg_rssi = (res.max_preamble_energy < 631) ? (128 + (res.max_preamble_energy / 5)) : 254,
|
|
.avg_snr = 0xff, // invalid for now
|
|
.num_preamble = 1,
|
|
.preamble_list = {
|
|
{.preamble_index = res.max_preamble, .timing_advance = res.max_preamble_delay, .preamble_pwr = 0xffffffff}}};
|
|
rach_ind->number_of_pdus++;
|
|
}
|
|
gNB->measurements.prach_I0 = ((gNB->measurements.prach_I0 * 900) >> 10) + ((res.max_preamble_energy * 124) >> 10);
|
|
if (frame == 0)
|
|
LOG_I(PHY, "prach_I0 = %d.%d dB\n", gNB->measurements.prach_I0 / 10, gNB->measurements.prach_I0 % 10);
|
|
if (gNB->prach_energy_counter < NUM_PRACH_RX_FOR_NOISE_ESTIMATE)
|
|
gNB->prach_energy_counter++;
|
|
} // if prach_id>0
|
|
LOG_D(NR_PHY_RACH, "Freeing PRACH entry\n");
|
|
free_nr_prach_entry(prach_id);
|
|
}
|