Process PRACH packets

* Move PRACH callback in the oaioran.h/c since now used in K release.
* Reset the number of PRACH packets.
* Handle PRACH queue in the same manner as for PUSCH (95c8fa46).

Co-authored-by: Romain Beurdouche <romain.beurdouche@eurecom.fr>
Signed-off-by: Teodora Vladić <teodora.vladic@openairinterface.org>
This commit is contained in:
Teodora Vladić
2026-04-23 18:42:25 +02:00
committed by Romain Beurdouche
co-authored by Romain Beurdouche
parent 6b665a851e
commit 1bc8e64641
6 changed files with 301 additions and 45 deletions
+7 -5
View File
@@ -28,7 +28,8 @@ It calls various helper function in the same file to set up DPDK memory buffer
- `oai_xran_fh_rx_prach_callback()` through `xran_5g_prach_req()`: callback for
PRACH data; not currently used and implemented in PUSCH data callback.
- `oai_physide_dl_tti_call_back()` through `xran_reg_physide_cb()`: only used
to unblock timing in `oai_xran_fh_rx_callback()` upon first xran call.
to unblock timing in `oai_xran_fh_rx_callback()` and `oai_xran_fh_rx_prach_callback()`
upon first xran call.
More detailed information about the xran callbacks can be taken from the xran
documentation.
@@ -40,9 +41,10 @@ PDSCH.
For PDSCH, `oran_fh_if4p5_south_out()` calls `xran_fh_tx_send_slot()` that
optionally compresses IQ data, then writes it into IQ buffers of xran.
For PUSCH/PRACH, `oran_fh_if4p5_south_in()` calls `xran_fh_rx_read_slot()` that
blocks and waits for the next slot. This is done through either a message
queue, or through polling, which in both cases depends on xran calling the
callback `oai_xran_fh_rx_callback()` as installed during xran initialization.
For PUSCH/PRACH, `oran_fh_if4p5_south_in()` calls `xran_fh_rx_read_slot()`/
`xran_fh_rx_prach_read_slot()` that blocks and waits for the next slot.
This is done through either a message queue, or through polling, which in both
cases depends on xran calling the callbacks `oai_xran_fh_rx_callback()`/
`oai_xran_fh_rx_prach_callback()` as installed during xran initialization.
Once unblocked, it reads first PRACH data, then PUSCH data, before returning to
OAI.
+211 -20
View File
@@ -46,8 +46,16 @@ int xran_is_prach_slot(uint8_t PortId, uint32_t subframe_id, uint32_t slot_id
extern notifiedFIFO_t oran_sync_fifo;
#define MAX_QUEUE_LENGTH_NO_JUMP 3
atomic_int xran_queue_length = 0;
atomic_int xran_queue_prach_length = 0;
#if defined K_RELEASE
extern notifiedFIFO_t oran_sync_fifo_prach;
#endif
#else
volatile oran_sync_info_t oran_sync_info = {0};
#if defined K_RELEASE
volatile oran_sync_info_t oran_sync_info_prach = {0};
volatile bool prach_rx_awaiting = false;
#endif
#endif
/** @details xran-specific callback, called when all packets for given CC and
@@ -184,8 +192,109 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status
} // rx_sym == 7
}
/** @details Only used to unblock timing in oai_xran_fh_rx_callback() on first
* call. */
void oai_xran_fh_rx_prach_callback(void *pCallbackTag, xran_status_t status
#if defined K_RELEASE
, uint8_t mu
#endif
)
{
#if defined K_RELEASE
struct xran_cb_tag *callback_tag = (struct xran_cb_tag *)pCallbackTag;
static int32_t last_slot = -1;
// static int32_t last_frame = -1;
const struct xran_fh_init *fh_init = get_xran_fh_init();
int num_ports = fh_init->xran_ports;
const int slots_in_sf = 1 << mu;
const int sf_in_frame = 10;
static int rx_RU[XRAN_PORTS_NUM][160] = {0};
uint32_t tti = callback_tag->slotiId;
uint32_t frame = XranGetFrameNum(tti, 0, sf_in_frame, slots_in_sf);
uint32_t subframe = XranGetSubFrameNum(tti, slots_in_sf, sf_in_frame);
uint32_t slot = XranGetSlotNum(tti, slots_in_sf);
uint32_t rx_sym = callback_tag->symbol & 0xFF;
uint32_t ru_id = callback_tag->oXuId;
LOG_D(HW, "prach_rx_callback at %4d.%3d (subframe %d), rx_sym %d ru_id %d\n", frame, slot, subframe, rx_sym, ru_id);
if (rx_sym == 7) { // in F release this value is defined as XRAN_FULL_CB_SYM (full slot (offset + 7))
// if xran did not call xran_physide_dl_tti callback, it's not ready yet.
// wait till first callback to advance counters, because otherwise users
// would see periodic output with only "0" in stats counters
if (!first_call_set)
return;
uint32_t slot2 = slot + (subframe * slots_in_sf);
rx_RU[ru_id][slot2] = 1;
// if (last_frame > 0 && frame > 0
// && ((slot2 > 0 && last_frame != frame) || (slot2 == 0 && last_frame != ((1024 + frame - 1) & 1023))))
// LOG_E(HW, "Jump in frame counter last_frame %d => %d, slot %d\n", last_frame, frame, slot2);
for (int i = 0; i < num_ports; i++) {
if (rx_RU[i][slot2] == 0)
return;
}
for (int i = 0; i < num_ports; i++)
rx_RU[i][slot2] = 0;
if (last_slot == -1 || slot2 != last_slot) {
#ifndef USE_POLLING
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(oran_sync_info_t), 0, &oran_sync_fifo_prach, NULL);
oran_sync_info_t *info = NotifiedFifoData(req);
info->tti = tti;
info->sl = slot2;
info->f = frame;
info->mu = mu;
#else
LOG_D(HW, "Writing PRACH slot %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, slot2, ru_id, slot, subframe, last_slot);
oran_sync_info_prach.tti = tti;
oran_sync_info_prach.sl = slot2;
oran_sync_info_prach.f = frame;
oran_sync_info_prach.mu = mu;
#endif
struct xran_cb_tag *callback_tag = (struct xran_cb_tag *)pCallbackTag;
uint32_t tti = callback_tag->slotiId;
uint32_t ru_id = callback_tag->oXuId;
for (int ru_idx = 0; ru_idx < num_ports; ru_idx++) {
oran_buf_list_t *bufs = get_xran_buffers(ru_idx);
struct xran_fh_config *fh_config = get_xran_fh_config(ru_idx);
for (uint16_t cc_id = 0; cc_id < 1 /* fh_config->nCC */; cc_id++) { // OAI does not support multiple CC yet.
for(uint32_t ant_id = 0; ant_id < fh_config->neAxc; ant_id++) {
struct xran_prb_map *pRbMap = (struct xran_prb_map *)bufs->prachdstdecomp[ant_id][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData;
AssertFatal(pRbMap != NULL, "(%d:%d:%d)pRbMapPrach == NULL. Aborting.\n", cc_id, tti % XRAN_N_FE_BUF_LEN, ant_id);
for (uint32_t sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) {
AssertFatal(pRbMap->sFrontHaulRxPacketCtrl[sym_id].nRxPkt <= 1, "PRACH segmentation is not supported\n");
#ifndef USE_POLLING
info->nRxPkt[cc_id][ant_id][sym_id] = pRbMap->sFrontHaulRxPacketCtrl[sym_id].nRxPkt;
#else
oran_sync_info_prach.nRxPkt[cc_id][ant_id][sym_id] = pRbMap->sFrontHaulRxPacketCtrl[sym_id].nRxPkt;
#endif
pRbMap->sFrontHaulRxPacketCtrl[sym_id].nRxPkt = 0;
}
}
}
}
#ifndef USE_POLLING
LOG_D(HW, "Push PRACH slot %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, info->sl, slot, ru_id, subframe, last_slot);
atomic_fetch_add(&xran_queue_prach_length, 1);
pushNotifiedFIFO(&oran_sync_fifo_prach, req);
#else
prach_rx_awaiting = true;
#endif
} else
LOG_E(HW, "Cannot Push PRACH slot %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, slot2, ru_id, slot, subframe, last_slot);
last_slot = slot2;
// last_frame = frame;
} // rx_sym == 7
#elif defined F_RELEASE
rte_pause();
#endif
}
/** @details Only used to unblock timing in oai_xran_fh_rx_callback()/oai_xran_fh_rx_prach_callback()
* on first call. */
int oai_physide_dl_tti_call_back(void *param
#if defined K_RELEASE
, uint8_t mu
@@ -198,17 +307,67 @@ int oai_physide_dl_tti_call_back(void *param
return 0;
}
/** @brief Reads PRACH data from xran buffers.
/** @details Read PRACH data from xran buffers.
* If I/Q compression (bitwidth < 16 bits) is configured, decompresses the data
* before writing.
*
* @details Reads PRACH data from xran-specific buffers and, if I/Q compression
* (bitwidth < 16 bits) is configured, uncompresses the data. Places PRACH data
* in OAI buffer. */
static int read_prach_data(ru_info_t *ru, int frame, int slot
#if defined K_RELEASE
, uint8_t mu
#endif
)
* Function is blocking and waits for next frame/slot combination. It is unblocked
* by oai_xran_fh_rx_prach_callback(). If K_RELEASE, it writes the current slot into parameters
* frame/slot. If F_RELEASE, it takes the frame/slot. */
int xran_fh_rx_prach_read_slot(prach_list_t *prach_list, ru_info_t *ru, int *frame, int *slot)
{
#if defined K_RELEASE
#ifndef USE_POLLING
// pull next even from oran_sync_fifo_prach if any
notifiedFIFO_elt_t *res = pullNotifiedFIFO(&oran_sync_fifo_prach);
atomic_fetch_sub(&xran_queue_prach_length, 1);
oran_sync_info_t *info = NotifiedFifoData(res);
if (xran_queue_prach_length > 0 && xran_queue_prach_length < MAX_QUEUE_LENGTH_NO_JUMP) {
LOG_D(HW, "%4d.%2d TTI processing delay detected\n", info->f, info->sl);
} else if (xran_queue_prach_length >= MAX_QUEUE_LENGTH_NO_JUMP) {
uint32_t old_f = info->f;
uint32_t old_sl = info->sl;
// set the frame/slot info to what is in the last message
notifiedFIFO_elt_t *f;
while ((f = pollNotifiedFIFO(&oran_sync_fifo_prach)) != NULL) {
atomic_fetch_sub(&xran_queue_prach_length, 1);
delNotifiedFIFO_elt(res);
res = f;
}
info = NotifiedFifoData(res);
LOG_W(HW, "PRACH TTI processing delay detected, skipping %4d.%2d => %4d.%2d\n", old_f, old_sl, info->f, info->sl);
DevAssert(xran_queue_prach_length == 0);
}
int slot = info->sl;
int frame = info->f;
uint8_t mu = info->mu;
delNotifiedFIFO_elt(res);
#else
#error "POLLING is not supported for K release unless you know how to fix the race condition on prach_rx_awaiting"
if (!prach_rx_awaiting) {
return (0);
} else {
prach_rx_awaiting = false;
}
int slot = oran_sync_info_prach.sl;
int frame = oran_sync_info_prach.f;
uint8_t mu = oran_sync_info_prach.mu;
uint32_t tti_in = oran_sync_info_prach.tti;
static int last_slot = -1;
LOG_D(HW, "oran slot %d, last_slot %d\n", *slot, last_slot);
int cnt = 0;
// while (*slot == last_slot) {
while (tti_in == oran_sync_info_prach.tti) {
//*slot = oran_sync_info.sl;
cnt++;
}
LOG_D(HW, "cnt %d, Reading %d.%d\n", cnt, *frame, *slot);
last_slot = *slot;
#endif
#endif
/* calculate tti and subframe_id from frame, slot num */
int sym_idx = 0;
@@ -235,19 +394,49 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot
#elif defined F_RELEASE
int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology;
#endif
int tti = slots_per_frame * (frame) + (slot);
int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports;
/* If it is PRACH slot, copy prach IQ from XRAN PRACH buffer to OAI PRACH buffer */
if (ru->prach_buf) {
for (sym_idx = prach_start_sym; sym_idx < prach_end_sym; sym_idx++) {
for (int aa = 0; aa < ru->nb_rx; aa++) {
for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet.
for (int aa = 0; aa < ru->nb_rx; aa++) {
for (sym_idx = prach_start_sym; sym_idx < prach_end_sym; sym_idx++) {
int16_t *dst, *src;
int idx = 0;
oran_buf_list_t *bufs = get_xran_buffers(aa / nb_rx_per_ru);
// hardcoded to use only first prach occasion
dst = (int16_t *)ru->prach_buf[aa][0];
#if defined K_RELEASE
struct xran_prb_map * pPrbMap = (struct xran_prb_map *)bufs->prachdstdecomp[aa % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData;
struct xran_rx_packet_ctl *p_rx_packet_ctl = &pPrbMap->sFrontHaulRxPacketCtrl[sym_idx];
#ifndef USE_POLLING
int32_t nRxPkt = info->nRxPkt[cc_id][aa][sym_idx];
#else
int32_t nRxPkt = oran_sync_info.nRxPkt[cc_id][aa][sym_idx];
#endif
if (nRxPkt == 0) {
LOG_E(HW, "read_prach %d.%d.%d saa = %d: nRxPkt = 0!\n", *frame, *slot, sym_idx, aa);
memset(&dst[sym_idx], 0, N_ZC * 2 * sizeof(*dst));
continue;
} else if (nRxPkt > 1) { // protection
LOG_E(HW, "read_prach %d.%d.%d saa = %d: nRxPkt = %d!\n", *frame, *slot, sym_idx, aa, nRxPkt);
memset(&dst[sym_idx], 0, N_ZC * 2 * sizeof(*dst));
continue;
} else {
src = (int16_t *)p_rx_packet_ctl->pData[0];
if (src == NULL) { // protection
LOG_E(HW, "read_prach %d.%d.%d saa = %d: src = NULL!!\n", *frame, *slot, sym_idx, aa);
memset(&dst[sym_idx], 0, N_ZC * 2 * sizeof(*dst));
continue;
}
}
num_prbu = p_rx_packet_ctl->nRBSize[0];
#elif defined F_RELEASE
src = (int16_t *)bufs->prachdstdecomp[aa % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx].pData;
#endif
/* convert Network order to host order */
if (ru_conf->compMeth_PRACH == XRAN_COMPMETHOD_NONE) {
if (sym_idx == prach_start_sym) {
@@ -289,9 +478,11 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot
for (idx = 0; idx < (N_ZC * 2); idx++)
dst[idx] += (local_dst[idx + g_kbar]);
} // COMPMETHOD_BLKFLOAT
} // aa
} // symb_indx
} // sym_idx
} // aa
} // cc_id
} // ru->prach_buf
return (0);
}
@@ -347,8 +538,8 @@ static bool is_tdd_ul_guard_slot(const struct xran_frame_config *frame_conf, int
return is_tdd_ul_symbol(frame_conf, slot, XRAN_NUM_OF_SYMBOL_PER_SLOT - 1);
}
/** @details Read PRACH and PUSCH data from xran buffers. If
* I/Q compression (bitwidth < 16 bits) is configured, deccompresses the data
/** @details Read PUSCH data from xran buffers.
* If I/Q compression (bitwidth < 16 bits) is configured, decompresses the data
* before writing. Prints ON TIME counters every 128 frames.
*
* Function is blocking and waits for next frame/slot combination. It is unblocked
@@ -423,9 +614,9 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
int tti = slots_per_frame * (*frame) + (*slot);
read_prach_data(ru, *frame, *slot
#if defined K_RELEASE
, mu
read_prach_data(ru
#if defined F_RELEASE
, *frame, *slot
#endif
);
+6
View File
@@ -21,6 +21,12 @@ typedef struct {
/** @brief xran callback for fronthaul RX, see xran_5g_fronthault_config(). */
void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status
#if defined K_RELEASE
, uint8_t mu
#endif
);
/** @brief xran callback for fronthaul PRACH RX, see xran_5g_prach_req(). */
void oai_xran_fh_rx_prach_callback(void *pCallbackTag, xran_status_t status
#if defined K_RELEASE
, uint8_t mu
#endif
+58 -17
View File
@@ -100,6 +100,31 @@ static struct xran_prb_map get_xran_prb_map(const struct xran_fh_config *f, cons
return prbmap;
}
#if defined K_RELEASE
static struct xran_prb_map get_xran_prb_map_prach(const struct xran_fh_config *f)
{
struct xran_prb_map prbmap = {
.dir = XRAN_DIR_UL,
.xran_port = 0,
.band_id = 0,
.cc_id = 0,
.ru_port_id = 0,
.tti_id = 0,
.nPrbElm = 1,
};
struct xran_prb_elm *e = &prbmap.prbMap[0];
e->nStartSymb = 0;
e->numSymb = 14;
e->nRBStart = 0;
e->nRBSize = 12;
e->nBeamIndex = 0;
e->compMethod = f->ru_conf.compMeth;
e->iqWidth = f->ru_conf.iqWidth;
memset(&prbmap.sFrontHaulRxPacketCtrl, 0, XRAN_NUM_OF_SYMBOL_PER_SLOT * sizeof(struct xran_rx_packet_ctl));
return prbmap;
}
#endif
static uint32_t next_power_2(uint32_t num)
{
uint32_t power = 2;
@@ -244,16 +269,6 @@ static void oran_allocate_cplane_buffers(void *instHandle,
printf("xran_bm_allocate_buffer() hInstance %p poolIdx %u count %u\n", instHandle, poolPrb, count1);
}
/* callback not actively used */
static void oai_xran_fh_rx_prach_callback(void *pCallbackTag, xran_status_t status
#if defined K_RELEASE
, uint8_t mu
#endif
)
{
rte_pause();
}
static void oran_allocate_buffers(void *handle,
int xran_inst,
int num_sectors,
@@ -287,6 +302,9 @@ static void oran_allocate_buffers(void *handle,
// DL/UL PRB mapping depending on the duplex mode
struct xran_prb_map dlPm = get_xran_prb_map(fh_config, XRAN_DIR_DL, 0, 14);
struct xran_prb_map ulPm = get_xran_prb_map(fh_config, XRAN_DIR_UL, 0, 14);
#if defined K_RELEASE
struct xran_prb_map prachPm = get_xran_prb_map_prach(fh_config);
#endif
struct xran_prb_map dlPmMixed = {0};
struct xran_prb_map ulPmMixed = {0};
uint32_t idx = 0;
@@ -314,6 +332,17 @@ static void oran_allocate_buffers(void *handle,
uint32_t numPrbElm = (fh_config->RunSlotPrbMapBySymbolEnable) ? XRAN_NUM_OF_SYMBOL_PER_SLOT : xran_get_num_prb_elm(&dlPm, mtu);
uint32_t size_of_prb_map = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (numPrbElm);
#if defined K_RELEASE
oran_cplane_prb_config prachConf = {
.nTddPeriod = fh_config->frame_conf.nTddPeriod,
.mixed_slot_index = idx,
.slotMap = prachPm,
.mixedSlotMap = prachPm,
};
uint32_t numPrbElmPrach = (fh_config->RunSlotPrbMapBySymbolEnable) ? XRAN_NUM_OF_SYMBOL_PER_SLOT : xran_get_num_prb_elm(&prachPm, mtu);
uint32_t size_of_prb_map_prach = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (numPrbElmPrach);
#endif
// PDSCH
#if defined K_RELEASE
@@ -352,41 +381,53 @@ static void oran_allocate_buffers(void *handle,
// PRACH
const uint32_t prachBufSize = PRACH_PLAYBACK_BUFFER_BYTES;
oran_allocate_uplane_buffers(pi->instanceHandle, bl->prachdst, bl->bufs.prach, xran_max_antenna_nr, prachBufSize);
#if defined K_RELEASE
oran_allocate_cplane_buffers(pi->instanceHandle,
bl->prachdstdecomp,
bl->bufs.prachdecomp,
xran_max_antenna_nr,
xran_max_sections_per_slot,
mtu,
fh_config,
size_of_prb_map_prach,
&prachConf);
#elif defined F_RELEASE
// PRACH decomp buffer does not have separate DPDK-allocated memory pool
// bufs, it points to the same pool as the prach buffer. Unclear to me why
for (uint32_t a = 0; a < xran_max_antenna_nr; ++a) {
for (uint32_t j = 0; j < XRAN_N_FE_BUF_LEN; ++j) {
bl->prachdstdecomp[a][j].pBuffers = &bl->bufs.prachdecomp[a][j][0];
bl->prachdstdecomp[a][j].pBuffers = &bl->bufs.prachdecomp[a][j];
for (uint32_t k = 0; k < XRAN_NUM_OF_SYMBOL_PER_SLOT; ++k) {
struct xran_flat_buffer *fb = &bl->prachdstdecomp[a][j].pBuffers[k];
fb->pData = bl->prachdst[a][j].pBuffers[k].pData;
}
}
}
#endif
struct xran_buffer_list *src[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
struct xran_buffer_list *srccp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
struct xran_buffer_list *dst[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
struct xran_buffer_list *dstcp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
struct xran_buffer_list *prach[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
struct xran_buffer_list *prachdecomp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
struct xran_buffer_list *prachdst[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
struct xran_buffer_list *prachdstdecomp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
for (uint32_t a = 0; a < XRAN_MAX_ANTENNA_NR; ++a) {
for (uint32_t j = 0; j < XRAN_N_FE_BUF_LEN; ++j) {
src[a][j] = &bl->src[a][j];
srccp[a][j] = &bl->srccp[a][j];
dst[a][j] = &bl->dst[a][j];
dstcp[a][j] = &bl->dstcp[a][j];
prach[a][j] = &bl->prachdst[a][j];
prachdecomp[a][j] = &bl->prachdstdecomp[a][j];
prachdst[a][j] = &bl->prachdst[a][j];
prachdstdecomp[a][j] = &bl->prachdstdecomp[a][j];
}
}
#if defined K_RELEASE
xran_5g_fronthault_config(pi->instanceHandle, src, srccp, dst, dstcp, oai_xran_fh_rx_callback, &portInstances->pusch_tag, fh_config->nNumerology[0]);
xran_5g_prach_req(pi->instanceHandle, prach, prachdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag, fh_config->nNumerology[0]);
xran_5g_prach_req(pi->instanceHandle, prachdst, prachdstdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag, fh_config->nNumerology[0]);
#elif defined F_RELEASE
xran_5g_fronthault_config(pi->instanceHandle, src, srccp, dst, dstcp, oai_xran_fh_rx_callback, &portInstances->pusch_tag);
xran_5g_prach_req(pi->instanceHandle, prach, prachdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag);
xran_5g_prach_req(pi->instanceHandle, prachdst, prachdstdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag);
#endif
}
+1 -1
View File
@@ -15,7 +15,7 @@ typedef struct oran_bufs {
struct xran_flat_buffer rx_prbmap[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
struct xran_flat_buffer prach[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN][XRAN_NUM_OF_SYMBOL_PER_SLOT];
struct xran_flat_buffer prachdecomp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN][XRAN_NUM_OF_SYMBOL_PER_SLOT];
struct xran_flat_buffer prachdecomp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
} oran_bufs_t;
typedef struct oran_buf_list {
+18 -2
View File
@@ -39,6 +39,9 @@ typedef struct {
} oran_eth_state_t;
notifiedFIFO_t oran_sync_fifo;
#if defined K_RELEASE
notifiedFIFO_t oran_sync_fifo_prach;
#endif
int trx_oran_start(openair0_device_t *device)
{
@@ -279,12 +282,22 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
fsn_t now = {.f = *frame, .s = *slot, .mu = gNB->frame_parms.numerology_index};
if (get_next_nr_prach(&gNB->prach_ru_queue, &now, &p)) {
struct xran_fh_config *fh_cfg = get_xran_fh_config(0);
int slots_per_subframe = 1 << fh_cfg->frame_conf.nNumerology;
#if defined F_RELEASE
uint8_t mu = fh_cfg->frame_conf.nNumerology;
#elif defined K_RELEASE
uint8_t mu = fh_cfg->nNumerology[0];
#endif
int slots_per_subframe = 1 << mu;
uint32_t subframe = *slot / slots_per_subframe; // `slot` = slot in which PRACH is received
// PRACH occasion in a frame if and only if SFN % x == y, TS 38.211 Table 6.3.3.2-2/3/4
nr_prach_info_t prach_info = get_prach_info(0);
bool is_prach_frame = (*frame % prach_info.x == prach_info.y);
bool is_prach_slot = is_prach_frame && xran_is_prach_slot(0, subframe, (p.slot % slots_per_subframe)); // `p.slot` = slot in which PRACH is scheduled
bool is_prach_slot = is_prach_frame && xran_is_prach_slot(0, subframe, (p.slot % slots_per_subframe)
#if defined K_RELEASE
, mu
#endif
); // `p.slot` = slot in which PRACH is scheduled
bool is_prach_slot = is_prach_frame && check_xran_prach_slot;
if (is_prach_slot) {
ru_info.prach_buf = p.prach_buf;
} else {
@@ -458,6 +471,9 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device_t
// create message queues for ORAN sync
initNotifiedFIFO(&oran_sync_fifo);
#if defined K_RELEASE
initNotifiedFIFO(&oran_sync_fifo_prach);
#endif
eth->e.flags = ETH_RAW_IF4p5_MODE;
eth->e.compression = NO_COMPRESS;