O-RU: PRACH RX and PRACH UP packet generation

This commit is contained in:
Bartosz Podrygajlo
2026-01-07 14:33:19 +01:00
parent ce42bcd30a
commit aa574dd721
10 changed files with 470 additions and 11 deletions

View File

@@ -1834,7 +1834,7 @@ target_link_libraries(nr-oru PRIVATE
radio_common softmodem_common)
target_link_libraries(nr-oru PRIVATE pthread m CONFIG_LIB rt ${T_LIB} utils
barrier actor)
target_link_libraries(nr-oru PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs nr_phy_common time_management PHY_NR)
target_link_libraries(nr-oru PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs nr_phy_common time_management PHY_NR MAC_NR_COMMON)
# nr-softmodem
###################################################

View File

@@ -207,6 +207,23 @@ int main(int argc, char **argv)
fill_split7_2_config(&ru->openair0_cfg.split7, &ru->config, fp);
ru->N_TA_offset = set_default_nta_offset(fp->freq_range, fp->samples_per_subframe);
/* set PRACH configuration */
nfapi_nr_prach_config_t *prach_config = &ru->config.prach_config;
prach_config->prach_ConfigurationIndex.value = oru.prach_config_index;
prach_config->num_prach_fd_occasions_list[0].k1.value = oru.prach_msg1_freq;
prach_config->prach_sequence_length.value = 1;
prach_config->prach_sub_c_spacing.value = 1;
prach_config->num_prach_fd_occasions.value = 1;
reset_meas(&oru.rx_prach);
oru.prach_info = get_nr_prach_occasion_info_from_index(oru.prach_config_index, FR1, fp->frame_type);
LOG_A(PHY, "PRACH configuration index %d\n", oru.prach_config_index);
LOG_A(PHY,
"PRACH format %d start_symbol %d duration %d\n",
oru.prach_info.format,
oru.prach_info.start_symbol,
oru.prach_info.N_dur);
prepare_prach_item(&oru);
ret = openair0_transport_load(&ru->ifdevice, &ru->openair0_cfg, &ru->eth_params);
AssertFatal(ret == 0, "RU %u: openair0_transport_init() ret %d: cannot initialize transport potocol\n", ru->idx, ret);

View File

@@ -18,12 +18,14 @@
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "PHY/defs_RU.h"
#include "assertions.h"
#include "common/config/config_userapi.h"
#include "nr-oru.h"
#include "openair1/PHY/defs_nr_common.h"
#include "openair1/PHY/MODULATION/nr_modulation.h"
#include "openair1/SCHED_NR/sched_nr.h"
#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h"
#define CONFIG_SECTION_ORU "ORUs.[0]"
@@ -103,6 +105,16 @@ typedef struct {
} dl_symbol_process_t;
extern void tx_rf_symbols(RU_t *ru, int frame, int slot, uint64_t timestamp, int start_symbol, int num_symbols);
extern void rx_nr_prach_ru_internal(prach_item_t *p,
int beam_id,
int prachStartSymbol,
int prachOccasion,
int32_t **rxdata,
NR_DL_FRAME_PARMS *fp,
int N_TA_offset,
int rep_index,
uint reps);
static void oru_downlink_processing(ORU_t *oru,
c16_t *txDataF_ptr[oru->ru->nb_tx],
int frame,
@@ -270,6 +282,48 @@ static openair0_timestamp_t get_timestamp(ORU_t *oru, sense_of_time_t *sense_of_
return timestamp;
}
void receive_prach(ORU_t *oru, int frame, int slot, int prach_symbol)
{
RU_t *ru = oru->ru;
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
oru->prach_item.frame = frame;
oru->prach_item.slot = slot;
rx_nr_prach_ru_internal(&oru->prach_item,
0,
oru->prach_info.start_symbol,
0,
ru->common.rxdata,
fp,
ru->N_TA_offset,
prach_symbol,
1);
for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++) {
ru->ifdevice.xran_api.write_prach((uint32_t *)oru->prach_item.rxsigF[0][aarx], aarx, frame, slot, prach_symbol);
}
}
// Returns PRACH symbol that was received in current frame, slot and symbol.
// If no PRACH symbol was received, returns -1
int get_prach_symbol(ORU_t *oru, int frame, int slot, int symbol, int numerology)
{
uint16_t RA_sfn_index;
AssertFatal(oru->ru->nr_frame_parms->frame_type == TDD, "Only supports TDD\n");
if (get_nr_prach_sched_from_info(oru->prach_info, oru->prach_config_index, frame, slot, numerology, FR1, &RA_sfn_index, true)) {
int format = oru->prach_item.pdu.prach_format;
int start_symbol = oru->prach_item.pdu.prach_start_symbol;
symbol -= start_symbol;
// TODO: Support more PRACH formats
AssertFatal(format == 8, "only support format B4\n");
// TODO: This is not exactly the case but it is correct
if (symbol > 0 && symbol < 12) {
return symbol;
}
}
return -1;
}
void *oru_north_read_thread(void *arg)
{
ORU_t *oru = (ORU_t *)arg;
@@ -400,6 +454,49 @@ void *oru_south_read_thread(void *arg)
rx_initial_sync(oru, &slot, &frame);
LOG_A(PHY, "ORU South read thread started at frame %d, slot %d\n", frame, slot);
RU_t *ru = oru->ru;
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
while (!oai_exit) {
int rx_slot_type = nr_slot_select(&ru->config, frame, slot);
for (int symbol = 0; symbol < 14; symbol++) {
int samples_to_read = get_samples_symbol_duration(fp, slot, symbol, 1);
size_t offset = get_samples_slot_timestamp(fp, slot) + get_samples_symbol_timestamp(fp, slot, symbol);
c16_t *rxp[fp->nb_antennas_rx];
for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++) {
rxp[aarx] = (c16_t *)&ru->common.rxdata[aarx][offset];
}
openair0_timestamp_t timestamp;
int num_samples_read = ru->rfdevice.trx_read_func(&ru->rfdevice, &timestamp, (void **)rxp, samples_to_read, ru->nb_rx);
AssertFatal(num_samples_read == samples_to_read, "Unexpected number of samples received\n");
LOG_D(PHY,
"[ORU south] read data: frame %d, slot %d, symbol %d, timestamp %ld num_symbols %d, samples %d\n",
frame,
slot,
symbol,
timestamp,
1,
num_samples_read);
if (rx_slot_type == NR_UPLINK_SLOT || rx_slot_type == NR_MIXED_SLOT) {
int prach_symbol = get_prach_symbol(oru, frame, slot, symbol, ru->numerology);
if (prach_symbol == 11) {
receive_prach(oru, frame, slot, prach_symbol);
}
stop_meas(&oru->rx);
}
}
slot++;
if (slot == fp->slots_per_frame) {
slot = 0;
frame++;
if (frame == 1024) {
frame = 0;
}
}
}
// Perform RX processing
return NULL;
}
@@ -511,3 +608,83 @@ static void oru_downlink_processing(ORU_t *oru,
tx_rf_symbols(ru, frame, slot, timestamp_tx, start_symbol, num_symbols);
stop_meas(&ru->tx_fhaul);
}
void prepare_prach_item(ORU_t *oru)
{
AssertFatal(oru->ru != NULL, "ORU not configured\n");
AssertFatal(oru->ru->nr_frame_parms != NULL, "ORU not configured\n");
NR_DL_FRAME_PARMS *fp = oru->ru->nr_frame_parms;
RU_t *ru = oru->ru;
prach_item_t *prach_item = &oru->prach_item;
prach_item->num_slots = oru->prach_info.format < 4 ? get_long_prach_dur(oru->prach_info.format, fp->numerology_index) : 1;
prach_item->msg1_frequencystart = oru->prach_msg1_freq;
prach_item->mu = fp->numerology_index;
nfapi_nr_config_request_scf_t *cfg = &ru->config;
prach_item->prach_sequence_length = cfg->prach_config.prach_sequence_length.value;
prach_item->restricted_set = 0;
prach_item->numerology_index = fp->numerology_index;
prach_item->nb_rx = ru->nb_rx;
prach_item->rx_prach = &oru->rx_prach;
prach_item->beams[0] = 0; // TODO: Beamforming not supported yet
// Fill PRACH PDU
nfapi_nr_prach_pdu_t *prach_pdu = &prach_item->pdu;
prach_pdu->prach_start_symbol = oru->prach_info.start_symbol;
prach_pdu->num_prach_ocas = 1; // TODO: Hardcoded.
uint16_t format0 = oru->prach_info.format & 0xff;
uint16_t format1 = (oru->prach_info.format >> 8) & 0xff;
if (format1 != 0xff) {
switch (format0) {
case 0xa1:
prach_pdu->prach_format = 11;
break;
case 0xa2:
prach_pdu->prach_format = 12;
break;
case 0xa3:
prach_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) {
case 0:
prach_pdu->prach_format = 0;
break;
case 1:
prach_pdu->prach_format = 1;
break;
case 2:
prach_pdu->prach_format = 2;
break;
case 3:
prach_pdu->prach_format = 3;
break;
case 0xa1:
prach_pdu->prach_format = 4;
break;
case 0xa2:
prach_pdu->prach_format = 5;
break;
case 0xa3:
prach_pdu->prach_format = 6;
break;
case 0xb1:
prach_pdu->prach_format = 7;
break;
case 0xb4:
prach_pdu->prach_format = 8;
break;
case 0xc0:
prach_pdu->prach_format = 9;
break;
case 0xc2:
prach_pdu->prach_format = 10;
break;
default:
AssertFatal(1 == 0, "Invalid PRACH format");
}
}
}

View File

@@ -20,8 +20,11 @@
*/
#ifndef __NR_ORU_H__
#define __NR_ORU_H__
#include "PHY/defs_nr_common.h"
#include "openair1/PHY/defs_RU.h"
#include "thread-pool.h"
#include "common/utils/nr/nr_common.h"
#include "openair2/LAYER2/NR_MAC_COMMON/nr_prach_config.h"
typedef struct {
RU_t *ru;
@@ -57,6 +60,12 @@ typedef struct {
int num_sync_messages_needed;
notifiedFIFO_t sync_fifo;
tpool_t tpool;
// PRACH related
nr_prach_info_t prach_info;
time_stats_t rx_prach;
time_stats_t rx;
prach_item_t prach_item;
} ORU_t;
int get_oru_options(ORU_t *oru);
@@ -64,5 +73,6 @@ void oru_init_frame_parms(ORU_t *oru);
void *oru_north_read_thread(void *arg);
void *oru_south_read_thread(void *arg);
void *oru_sync_thread(void *arg);
void prepare_prach_item(ORU_t *oru);
#endif

View File

@@ -125,15 +125,15 @@ prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_n
return prach;
}
static void rx_nr_prach_ru_internal(prach_item_t *p,
int beam_id,
int prachStartSymbol,
int prachOccasion,
int32_t **rxdata,
NR_DL_FRAME_PARMS *fp,
int N_TA_offset,
int rep_index,
uint reps)
void rx_nr_prach_ru_internal(prach_item_t *p,
int beam_id,
int prachStartSymbol,
int prachOccasion,
int32_t **rxdata,
NR_DL_FRAME_PARMS *fp,
int N_TA_offset,
int rep_index,
uint reps)
{
int sample_offset_slot;
const int sum = fp->ofdm_symbol_size + fp->nb_prefix_samples;

View File

@@ -680,6 +680,16 @@ struct openair0_device {
* \param num_symbols number of symbols
*/
void (*north_in_func)(uint32_t **txdataF, int nb_tx, sense_of_time_t* sense_of_time, int *num_symbols);
/*!
* \brief Write prach data for one PRACH symbol
* \param prachF Frequency domain PRACH data size 139 (only short format support)
* \param aarx
* \param frame
* \param slot
* \param symbol
*/
void (*write_prach)(uint32_t *prachF, int aarx, int frame, int slot, int symbol);
} xran_api;
};

View File

@@ -35,6 +35,9 @@
#include "xran_fh_o_ru.h"
#include "xran_compression.h"
#include "armral_bfp_compression.h"
#include <xran_pkt.h>
#include <xran_pkt_up.h>
#include <xran_transport.h>
#if defined(__arm__) || defined(__aarch64__)
#else
@@ -53,6 +56,10 @@
#include "common/utils/threadPool/notified_fifo.h"
#define RATE_LIMIT(n) if (({ static int _counter = 0; _counter++ % (n) == 0; }))
#define ETHER_TYPE_ECPRI 0xAEFE
#define MAX_NUM_ANTENNAS 4
notifiedFIFO_t ru_dl_sync_fifo;
extern volatile bool first_call_set;
@@ -231,6 +238,22 @@ static void print_statistics(packet_processor_context_t *context)
LOG_I(HW, "RU: packets dropped %lu\n", context->up_dropped);
}
typedef struct {
int section_id;
int num_prb;
int start_prb;
int slot;
int frame;
int mu;
int filter_id;
} oran_prach_cplane_config_t;
oran_prach_cplane_config_t prach_config_per_antenna[MAX_NUM_ANTENNAS] = {0};
static uint8_t prach_seq_id[MAX_NUM_ANTENNAS] = {0};
extern int32_t xran_ethdi_mbuf_send(struct rte_mbuf *mb, uint16_t ethertype, uint16_t vf_id);
extern uint16_t xran_map_ecpriPcid_to_vf(void *p_dev_ctx, int32_t dir, int32_t cc_id, int32_t ru_port_id);
void symbol_callback(void *args, struct xran_sense_of_time *p_sense_of_time)
{
if (!first_call_set) {
@@ -478,7 +501,58 @@ int process_ru_uplane(struct rte_mbuf *pkt,
int32_t process_ru_cplane(struct rte_mbuf *pkt, void *handle, uint16_t port_id, struct xran_sense_of_time *p_sense_of_time)
{
return MBUF_FREE;
const struct xran_fh_config *fh_cfg = get_xran_fh_config(port_id);
struct xran_ecpri_hdr *ecpri_hdr;
struct xran_recv_packet_info xran_recv_packet_info;
int ret = xran_parse_ecpri_hdr(pkt, &ecpri_hdr, &xran_recv_packet_info);
if (ret != XRAN_STATUS_SUCCESS) {
return MBUF_FREE;
}
struct xran_cp_radioapp_common_header *apphdr = (void *)rte_pktmbuf_adj(pkt, sizeof(struct xran_ecpri_hdr));
if (apphdr == NULL) {
LOG_W(HW, "issue extracting apphdr\n");
return MBUF_FREE;
}
apphdr->field.all_bits = rte_be_to_cpu_32(apphdr->field.all_bits);
if (apphdr->field.payloadVer != XRAN_PAYLOAD_VER) {
LOG_W(HW, "Invalid payloadVer field %d\n", apphdr->field.payloadVer);
return MBUF_FREE;
}
switch (apphdr->sectionType) {
case XRAN_CP_SECTIONTYPE_3: {
struct xran_cp_radioapp_section3_header *hdr = (struct xran_cp_radioapp_section3_header *)apphdr;
if (hdr->cmnhdr.numOfSections != 1) {
LOG_W(HW, "Only support one section\n");
return MBUF_FREE;
}
hdr->timeOffset = rte_be_to_cpu_16(hdr->timeOffset);
hdr->cpLength = rte_be_to_cpu_16(hdr->cpLength);
struct xran_cp_radioapp_section3 *section = (void *)rte_pktmbuf_adj(pkt, sizeof(struct xran_cp_radioapp_section3_header));
if (section == NULL) {
LOG_W(HW, "Issue extracting section\n");
return MBUF_FREE;
}
*((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));
int mu = hdr->frameStructure.uScs;
int aarx = xran_recv_packet_info.eaxc.ruPortId - fh_cfg->prach_conf.eAxC_offset;
oran_prach_cplane_config_t prach_config = {
.frame = hdr->cmnhdr.field.frameId,
.slot = hdr->cmnhdr.field.slotId + hdr->cmnhdr.field.subframeId + hdr->cmnhdr.field.subframeId * hdr->frameStructure.uScs,
.num_prb = section->hdr.u1.common.numPrbc,
.start_prb = section->hdr.u1.common.startPrbc,
.section_id = section->hdr.u1.common.sectionId,
.mu = mu,
.filter_id = hdr->cmnhdr.field.filterIndex
};
prach_config_per_antenna[aarx] = prach_config;
return MBUF_FREE;
}
default:
return MBUF_FREE;
}
}
void init_oru_packet_processor(void *handle, int callbacks_per_slot)
@@ -489,6 +563,13 @@ void init_oru_packet_processor(void *handle, int callbacks_per_slot)
static bool installed = false;
AssertFatal(!installed, "Cannot init oru twice\n");
installed = true;
for (int aarx = 0; aarx < MAX_NUM_ANTENNAS; aarx++) {
prach_config_per_antenna[aarx].section_id = -1;
prach_config_per_antenna[aarx].num_prb = -1;
prach_config_per_antenna[aarx].start_prb = -1;
prach_config_per_antenna[aarx].slot = -1;
prach_config_per_antenna[aarx].frame = -1;
}
// Represents RX window end
@@ -525,3 +606,112 @@ void init_oru_packet_processor(void *handle, int callbacks_per_slot)
}
xran_hook_install(handle, process_ru_uplane, NULL, process_ru_cplane, NULL, symbol_callback, &args, mu);
}
extern void *xran_ethdi_mbuf_alloc(void);
void fill_ecpri_header(struct xran_ecpri_hdr *ecpri_header,
uint8_t ecpri_mesg_type,
size_t ecpri_payload_size,
uint8_t CC_ID,
uint8_t Ant_ID,
uint8_t seq_id,
uint8_t oxu_port_id)
{
ecpri_header->cmnhdr.data.data_num_1 = 0x0;
ecpri_header->cmnhdr.bits.ecpri_ver = XRAN_ECPRI_VER;
ecpri_header->cmnhdr.bits.ecpri_mesg_type = ecpri_mesg_type;
ecpri_header->cmnhdr.bits.ecpri_payl_size = rte_cpu_to_be_16(ecpri_payload_size);
ecpri_header->ecpri_xtc_id = xran_compose_cid(0, 0, CC_ID, Ant_ID);
ecpri_header->ecpri_seq_id.bits.seq_id = seq_id;
ecpri_header->ecpri_seq_id.bits.e_bit = 1;
ecpri_header->ecpri_seq_id.bits.sub_seq_id = 0;
/// No byteswap for ecpri_seq_id. Possibly because of inverse definition in xran
}
void fill_radio_app_header(struct radio_app_common_hdr *radio_app_header,
int filter_id,
int direction,
int frame,
int slot,
int symbol,
int mu)
{
radio_app_header->frame_id = frame & 0xff;
radio_app_header->sf_slot_sym.slot_id = slot % (1 << mu);
radio_app_header->sf_slot_sym.subframe_id = slot / (1 << mu);
radio_app_header->sf_slot_sym.symb_id = symbol;
radio_app_header->sf_slot_sym.value = rte_cpu_to_be_16(radio_app_header->sf_slot_sym.value);
radio_app_header->data_feature.data_direction = direction;
radio_app_header->data_feature.payl_ver = 1;
radio_app_header->data_feature.filter_id = filter_id;
}
void fill_data_section_header(struct data_section_hdr *data_section_hdr, int num_prb, int start_prb, int section_id)
{
data_section_hdr->fields.all_bits = 0;
data_section_hdr->fields.num_prbu = (uint8_t)XRAN_CONVERT_NUMPRBC(num_prb);
data_section_hdr->fields.start_prbu = (start_prb & 0x03ff);
data_section_hdr->fields.sect_id = section_id;
data_section_hdr->fields.all_bits = rte_cpu_to_be_32(data_section_hdr->fields.all_bits);
}
void xran_oru_send_prach(uint32_t *prachF, int aarx, int frame, int slot, int symbol)
{
const struct xran_fh_config *fh_cfg = get_xran_fh_config(0);
uint8_t mu = fh_cfg->frame_conf.nNumerology;
AssertFatal(fh_cfg->ru_conf.compMeth_PRACH == XRAN_COMPMETHOD_NONE, "Compression not supported\n");
// TODO: With compression, have to add compression header to header_len
size_t header_length = sizeof(struct xran_ecpri_hdr) + sizeof(struct radio_app_common_hdr) + sizeof(struct data_section_hdr);
// TODO: For compression, have to re-evaluate data size;
// TODO: Only support short format PRACH
const uint prach_length = 139;
size_t data_len = sizeof(int32_t) * prach_length;
oran_prach_cplane_config_t *prach_config = &prach_config_per_antenna[aarx];
if (prach_config->section_id == -1) {
RATE_LIMIT(1000)
LOG_W(HW, "PRACH was not yet configured by the O-DU\n");
return;
}
if (prach_config->frame != (frame & 0xff) || prach_config->slot != slot) {
RATE_LIMIT(1000)
LOG_W(HW,
"PRACH was not configured for frame.slot %d.%d, configuration is for frame.slot %d.%d\n",
frame,
slot,
prach_config->frame,
prach_config->slot);
return;
}
struct rte_mbuf *mbuf = xran_ethdi_mbuf_alloc();
AssertFatal(mbuf != NULL, "out of mbufs\n");
char *buf = rte_pktmbuf_append(mbuf, header_length + data_len);
AssertFatal(buf, "incorrect mbuf size\n");
struct xran_ecpri_hdr *ecpri_header = (struct xran_ecpri_hdr *)rte_pktmbuf_mtod(mbuf, char *);
uint16_t ecpri_payload_size = xran_get_ecpri_hdr_size() + sizeof(struct radio_app_common_hdr) + sizeof(struct data_section_hdr) + data_len;
fill_ecpri_header(ecpri_header, ECPRI_IQ_DATA, ecpri_payload_size, 0, aarx + fh_cfg->prach_conf.eAxC_offset, prach_seq_id[aarx]++, 0);
struct radio_app_common_hdr *radio_app_header = (struct radio_app_common_hdr *)(ecpri_header + 1);
fill_radio_app_header(radio_app_header, prach_config->filter_id, XRAN_DIR_UL, frame, slot, symbol, mu);
struct data_section_hdr *data_section_header = (struct data_section_hdr *)(radio_app_header + 1);
fill_data_section_header(data_section_header, prach_config->num_prb, prach_config->start_prb, prach_config->section_id);
void *iq_data_start = (void *)(data_section_header + 1);
int16_t *dest = (int16_t *)iq_data_start;
uint16_t *src = (uint16_t *)prachF;
for (int i = 0; i < prach_length * 2; i++) {
dest[i] = (int16_t)htons(src[i]);
}
buf = rte_pktmbuf_prepend(mbuf, sizeof(struct rte_ether_hdr));
AssertFatal(buf != NULL, "incorrect mbuf size\n");
int vf_id = xran_map_ecpriPcid_to_vf(gxran_handle, XRAN_DIR_UL, 0, aarx + fh_cfg->prach_conf.eAxC_offset);
int ret = xran_ethdi_mbuf_send(mbuf, ETHER_TYPE_ECPRI, vf_id);
AssertFatal(ret == 1, "Error sending mbuf\n");
}

View File

@@ -32,5 +32,6 @@ void init_oru_packet_processor(void* handle, int callbacks_per_slot);
// Read samples DL IQ samples for frame slot symbol for all antennas
int xran_oru_tx_read_slot(uint32_t **txdataF, int nb_tx, int *frame, int *slot, int *symbol, int *num_symbols, struct timespec *ts);
void xran_oru_send_prach(uint32_t *prachF, int aarx, int frame, int slot, int symbol);
#endif

53
radio/fhi_72/oran_debug.c Normal file
View File

@@ -0,0 +1,53 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "oran_debug.h"
#include "openair1/PHY/TOOLS/tools_defs.h"
void dump_nonzero_symbol(c16_t *txdataF, uint32_t ofdm_symbol_size, int frame, int slot, int symbol, const char* loc)
{
float signal_energy = signal_energy_nodc(txdataF, ofdm_symbol_size);
if (signal_energy > 1) {
// Prepare a buffer to hold the formatted string for the symbol
const int num_chars_per_sample = 4 + 6 * 2;
char symbol_buf[ofdm_symbol_size * num_chars_per_sample]; // Enough for "(r,i) " per sample
int offset = 0;
bool is_zero_block = true;
for (int i = 0; i < ofdm_symbol_size; i++) {
bool is_zero = txdataF[i].r == 0 && txdataF[i].i == 0;
if (is_zero_block && !is_zero) {
offset += snprintf(symbol_buf + offset, sizeof(symbol_buf) - offset, "[sc %d]: ", i);
is_zero_block = false;
}
if (!is_zero_block && is_zero) {
is_zero_block = true;
}
if (!is_zero) {
offset += snprintf(symbol_buf + offset, sizeof(symbol_buf) - offset, "(%d,%d) ", txdataF[i].r, txdataF[i].i);
}
}
symbol_buf[offset] = '\0';
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
LOG_D(HW, "dump_nonzero_symbol: Frame.Slot.Symbol %d.%d.%d (%s) signal_energy %.3f time %ld.%09ld samples: %s\n", frame, slot, symbol, loc, 10 * log10(signal_energy), ts.tv_sec, ts.tv_nsec, symbol_buf);
}
}

View File

@@ -408,6 +408,7 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device_t
device->priv = eth;
device->openair0_cfg = &openair0_cfg[0];
device->xran_api.north_in_func = oran_fh_if4p5_north_in;
device->xran_api.write_prach = xran_oru_send_prach;
return 0;
}