Compare commits

...

6 Commits

Author SHA1 Message Date
Raymond Knopp
b7dbf72968 added TX path again. Works except for real-time issue when PRACH processing happens 2026-02-15 07:47:50 +01:00
Raymond Knopp
3acd553be8 RX path ok, TX causes massive late receptions 2026-02-14 15:36:26 +01:00
Raymond Knopp
67fcc123b2 extra logging for usrp debugging 2026-02-13 11:13:32 +01:00
Alessandro Serra
b269374aaf changes for n96 400 MHz 2026-02-12 10:37:45 +01:00
Alessandro Serra
b2ccd1b2bf testing 400 MHz channel BW with USRP X410 2026-02-11 14:50:34 +01:00
Alessandro Serra
3180d99ca6 testing 400 MHz channel BW with USRP X410 2026-02-11 14:43:00 +01:00
10 changed files with 305 additions and 18 deletions

View File

@@ -362,7 +362,7 @@ const sync_raster_t sync_raster[] = {
{92, 0, 3584, 1, 3787},
{93, 0, 3572, 1, 3574},
{94, 0, 3584, 1, 3787},
{96, 1, 9531, 1, 10363},
{96, 3, 9531, 1, 10363},
{100, 0, 2303, 1, 2307},
{101, 0, 4754, 1, 4768},
{101, 1, 4760, 1, 4764},
@@ -1066,6 +1066,11 @@ void get_samplerate_and_bw(int mu,
}
} else if (mu == 3) {
switch(n_rb) {
case 264:
*sample_rate=491.52e6;
*tx_bw = 400e6;
*rx_bw = 400e6;
break;
case 132:
case 128:
if (threequarter_fs) {

View File

@@ -571,7 +571,7 @@ static void rx_rf(RU_t *ru, int *frame, int *slot)
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1);
openair0_timestamp_t old_ts = proc->timestamp_rx;
LOG_D(PHY,"Reading %d samples for slot %d (%p)\n", samples_per_slot, *slot, rxp[0]);
//if (/**slot == 0 && */(*frame&127) == 0) LOG_I(PHY,"Reading %d samples for slot %d (%p)\n", samples_per_slot, *slot, rxp[0]);
openair0_timestamp_t ts;
unsigned int rxs;
@@ -605,7 +605,7 @@ static void rx_rf(RU_t *ru, int *frame, int *slot)
proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023;
proc->tti_rx = get_slot_from_timestamp(proc->timestamp_rx, fp);
// synchronize first reception to frame 0 subframe 0
LOG_D(PHY,
if ((proc->frame_rx&127) == 0 && proc->tti_rx == 0) LOG_I(PHY,
"RU %d/%d TS %ld, GPS %f, SR %f, frame %d, slot %d.%d / %d\n",
ru->idx,
0,
@@ -785,12 +785,16 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp + ru->ts_offset) & 0xffffffff);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1);
// prepare tx buffer pointers
if ((frame &127) == 0 && slot == 0) LOG_I(PHY,"[TXPATH] Frame.Slot %d.%d sending %d samples @ %lld\n",frame,slot,siglen + sf_extension,timestamp + ru->ts_offset - sf_extension);
uint32_t txs = ru->rfdevice.trx_write_func(&ru->rfdevice,
timestamp + ru->ts_offset - sf_extension,
txp,
siglen + sf_extension,
nt,
flags);
/*
LOG_D(PHY,
"[TXPATH] RU %d tx_rf, writing to TS %lu, %d.%d, unwrapped_frame %d, slot %d, flags %d, siglen+sf_extension %d, "
"returned %d, E %f\n",
@@ -804,7 +808,8 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
siglen + sf_extension,
txs,
10 * log10((double)signal_energy(txp[0], siglen + sf_extension)));
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0);
*/
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0);
}
static void fill_rf_config(RU_t *ru, char *rf_config_file)
@@ -1120,6 +1125,8 @@ void *ru_thread(void *param)
LOG_I(PHY, "RU %d RF started cpu_meas_enabled %d\n", ru->idx, cpu_meas_enabled);
// start trx write thread
if (usrp_tx_thread == 1) {
ru->rfdevice.tx_write_thread_affinity = ru->tx_write_thread_core;
LOG_I(HW,"Setting tx_write_thread_affinity to %d\n",ru->rfdevice.tx_write_thread_affinity);
if (ru->start_write_thread) {
if (ru->start_write_thread(ru) != 0) {
LOG_E(HW, "Could not start tx write thread\n");
@@ -1192,7 +1199,8 @@ void *ru_thread(void *param)
if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) {
if (!wait_free_rx_tti(&gNB->L1_rx_out, rx_tti_busy, proc->frame_rx, proc->tti_rx))
break; // nothing to wait for: we have to stop
if (ru->feprx) {
if (ru->feprx) {
ru->feprx(ru,proc->tti_rx);
LOG_D(NR_PHY, "Setting %d.%d (%d) to busy\n", proc->frame_rx, proc->tti_rx, proc->tti_rx % RU_RX_SLOT_DEPTH);
//LOG_M("rxdata.m","rxs",ru->common.rxdata[0],1228800,1,1);
@@ -1810,6 +1818,7 @@ static void NRRCconfig_RU(configmodule_interface_t *cfg)
ru->num_tpcores = *param[RU_NUM_TP_CORES].iptr;
ru->half_slot_parallelization = *param[RU_HALF_SLOT_PARALLELIZATION].iptr;
ru->ru_thread_core = *param[RU_RU_THREAD_CORE].iptr;
ru->tx_write_thread_core = *param[RU_TX_WRITE_THREAD_CORE].iptr;
LOG_D(PHY, "[RU %d] Setting half-slot parallelization to %d\n", j, ru->half_slot_parallelization);
AssertFatal(ru->num_tpcores <= param[RU_TP_CORES].numelt, "Number of TP cores should be <=16\n");
for (int i = 0; i < ru->num_tpcores; i++)

253
g410.conf Normal file
View File

@@ -0,0 +1,253 @@
Active_gNBs = ( "gNB-OAI");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
gNBs =
(
{
////////// Identification parameters:
gNB_ID = 0xe00;
gNB_name = "gNB-OAI";
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1;
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1; }) });
nr_cellid = 12345678L;
////////// Physical parameters:
pdsch_AntennaPorts_XP = 1;
pusch_AntennaPorts = 1;
do_CSIRS = 1;
do_SRS = 1;
min_rxtxtime = 6;
servingCellConfigCommon = (
{
#spCellConfigCommon
physCellId = 0;
# downlinkConfigCommon
#frequencyInfoDL
# This is 6700.8MHz + 132*12 * 120e3 MHz = 6890.88 MHz (GSCN:10201 )
absoluteFrequencySSB = 2090683;
dl_frequencyBand = 257
# This is 6700.8 MHz
dl_absoluteFrequencyPointA = 2089251;
#scs-SpecificCarrierList
dl_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
dl_subcarrierSpacing = 3;
dl_carrierBandwidth = 264;
#initialDownlinkBWP
#genericParameters
# This is RBstart = 0, L = 32: (275 * (L - 1)) + RBstart
initialDLBWPlocationAndBandwidth = 36025;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialDLBWPsubcarrierSpacing = 3;
#pdcch-ConfigCommon
initialDLBWPcontrolResourceSetZero = 4;
initialDLBWPsearchSpaceZero = 0;
#uplinkConfigCommon
#frequencyInfoUL
ul_frequencyBand = 257
#scs-SpecificCarrierList
ul_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
ul_subcarrierSpacing = 3;
ul_carrierBandwidth = 264;
pMax = 20;
#initialUplinkBWP
#genericParameters
initialULBWPlocationAndBandwidth = 36025;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialULBWPsubcarrierSpacing = 3;
#rach-ConfigCommon
#rach-ConfigGeneric
prach_ConfigurationIndex = 135;
#prach_msg1_FDM
#0 = one, 1=two, 2=four, 3=eight
prach_msg1_FDM = 0;
prach_msg1_FrequencyStart = 0;
zeroCorrelationZoneConfig = 1;
preambleReceivedTargetPower = -118;
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
preambleTransMax = 8;
#powerRampingStep
# 0=dB0,1=dB2,2=dB4,3=dB6
powerRampingStep = 2;
ra_ResponseWindow = 7;
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3;
#one (0..15) 4,8,12,16,...60,64
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15;
#ra_ContentionResolutionTimer
#(0..7) 8,16,24,32,40,48,56,64
ra_ContentionResolutionTimer = 7;
rsrp_ThresholdSSB = 19;
#prach-RootSequenceIndex_PR
#1 = 839, 2 = 139
prach_RootSequenceIndex_PR = 2;
prach_RootSequenceIndex = 1;
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
#
msg1_SubcarrierSpacing = 3;
# restrictedSetConfig
# 0=unrestricted, 1=restricted type A, 2=restricted type B
restrictedSetConfig = 0,
msg3_DeltaPreamble = 0;
p0_NominalWithGrant =-90;
# pucch-ConfigCommon setup :
# pucchGroupHopping
# 0 = neither, 1= group hopping, 2=sequence hopping
pucchGroupHopping = 0;
hoppingId = 40;
p0_nominal = -90;
ssb_PositionsInBurst_PR = 3;
ssb_PositionsInBurst_Bitmap = 1;
# ssb_periodicityServingCell
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
ssb_periodicityServingCell = 1;
# dmrs_TypeA_position
# 0 = pos2, 1 = pos3
dmrs_TypeA_Position = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
subcarrierSpacing = 3;
#tdd-UL-DL-ConfigurationCommon
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
referenceSubcarrierSpacing = 3;
# pattern1
# dl_UL_TransmissionPeriodicity
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
dl_UL_TransmissionPeriodicity = 3;
nrofDownlinkSlots = 7;
nrofDownlinkSymbols = 6;
nrofUplinkSlots = 2;
nrofUplinkSymbols = 4;
ssPBCH_BlockPower = 0;
}
);
# ------- SCTP definitions
SCTP :
{
# Number of streams to use in input/output
SCTP_INSTREAMS = 2;
SCTP_OUTSTREAMS = 2;
};
////////// AMF parameters:
amf_ip_address = ({ ipv4 = "172.21.6.5"; });
NETWORK_INTERFACES :
{
GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.51";
GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.51";
GNB_PORT_FOR_S1U = 2152; # Spec 2152
};
}
);
MACRLCs = (
{
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
#pusch_TargetSNRx10 = 150;
#pucch_TargetSNRx10 = 200;
}
);
L1s = (
{
num_cc = 1;
tr_n_preference = "local_mac";
prach_dtx_threshold = 920;
#pucch0_dtx_threshold = 120;
L1_tx_thread_core = 11;
L1_rx_thread_core = 10;
}
);
RUs = (
{
local_rf = "yes";
nb_tx = 1;
nb_rx = 1;
att_tx = 0;
att_rx = 0;
sl_ahead = 10;
bands = [257];
max_pdschReferenceSignalPower = -27;
max_rxgain = 60;
eNB_instances = [0];
ru_thread_core = 6;
tx_write_thread_core = 7;
tp_cores = [8,9];
if_freq = 6900000000L;
#clock_src = "internal";
sdr_addrs = "mgmt_addr=172.21.19.115,addr=192.168.10.2,clock_source=internal,time_source=internal,,use_dpdk=1"
}
);
rfsimulator :
{
serveraddr = "server";
serverport = 4043;
options = (); #("saviq"); or/and "chanmod"
modelname = "AWGN";
IQfile = "/tmp/rfsimulator.iqs";
};
security = {
# preferred ciphering algorithms
# the first one of the list that an UE supports in chosen
# valid values: nea0, nea1, nea2, nea3
ciphering_algorithms = ( "nea0" );
# preferred integrity algorithms
# the first one of the list that an UE supports in chosen
# valid values: nia0, nia1, nia2, nia3
integrity_algorithms = ( "nia2", "nia0" );
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
drb_ciphering = "yes";
drb_integrity = "no";
};
log_config :
{
global_log_level ="info";
hw_log_level ="info";
phy_log_level ="info";
mac_log_level ="info";
rlc_log_level ="info";
pdcp_log_level ="info";
rrc_log_level ="info";
ngap_log_level ="info";
f1ap_log_level ="info";
};

View File

@@ -333,6 +333,11 @@ static void rx_nr_prach_ru_internal(prach_item_t *p,
dftlen <<= 3;
break;
case 491520:
Ncp <<= 4;
dftlen <<=4;
break;
default:
AssertFatal(1==0,"sample rate %f MHz not supported for numerology %d\n", fp->samples_per_subframe / 1000.0, mu);
}

View File

@@ -634,6 +634,8 @@ typedef struct RU_t_s {
int num_fd;
/// Core id of ru_thread
int ru_thread_core;
/// Core id of tx_write_thread
int tx_write_thread_core;
/// list of cores for RU ThreadPool
int tpcores[16];
/// number of cores for RU ThreadPool

View File

@@ -99,6 +99,7 @@ typedef enum {
#define CONFIG_STRING_RU_NUM_INTERFACES "num_interfaces"
#define CONFIG_STRING_RU_HALF_SLOT_PARALLELIZATION "half_slot_parallelization"
#define CONFIG_STRING_RU_RU_THREAD_CORE "ru_thread_core"
#define CONFIG_STRING_RU_TX_WRITE_THREAD_CORE "tx_write_thread_core"
#define CONFIG_STRING_RU_GPIO_CONTROL "gpio_controller"
#define HLP_RU_SF_AHEAD "LTE TX processing advance"
@@ -112,6 +113,7 @@ typedef enum {
#define HLP_RU_NUM_INTERFACES "Number of network interfaces for RU"
#define HLP_RU_HALF_SLOT_PARALLELIZATION "run half slots in parallel in RU FEP"
#define HLP_RU_RU_THREAD_CORE "id of core to pin ru_thread, -1 is default"
#define HLP_RU_TX_WRITE_THREAD_CORE "id of core to pin tx_write_thread, -1 is default"
#define HLP_RU_GPIO_CONTROL "set the GPIO control type for the RU"
#define RU_LOCAL_IF_NAME_IDX 0
@@ -157,6 +159,7 @@ typedef enum {
#define RU_HALF_SLOT_PARALLELIZATION 40
#define RU_RU_THREAD_CORE 41
#define RU_GPIO_CONTROL 42
#define RU_TX_WRITE_THREAD_CORE 43
/*-----------------------------------------------------------------------------------------------------------------------------------------*/
/* RU configuration parameters */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
@@ -206,6 +209,7 @@ typedef enum {
{CONFIG_STRING_RU_HALF_SLOT_PARALLELIZATION, HLP_RU_HALF_SLOT_PARALLELIZATION, 0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \
{CONFIG_STRING_RU_RU_THREAD_CORE, HLP_RU_RU_THREAD_CORE, 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0}, \
{CONFIG_STRING_RU_GPIO_CONTROL, HLP_RU_GPIO_CONTROL, 0, .strptr=NULL, .defstrval="generic", TYPE_STRING, 0}, \
{CONFIG_STRING_RU_TX_WRITE_THREAD_CORE, HLP_RU_TX_WRITE_THREAD_CORE, 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0}, \
}
// clang-format on

View File

@@ -563,12 +563,13 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap)
NR_RACH_ConfigCommon_t *rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
long config_index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex;
frequency_range_t freq_range = get_freq_range_from_arfcn(dlcc->frequencyInfoDL->absoluteFrequencyPointA);
int band = (int)*dlcc->frequencyInfoDL->frequencyBandList.list.array[0];
frame_type_t frame_type = get_frame_type((int)*dlcc->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing);
nr_prach_info_t prach_info = get_nr_prach_occasion_info_from_index(config_index, freq_range, frame_type);
nr_prach_info_t prach_info = get_nr_prach_occasion_info_from_index(config_index, band==96 ? FR2 : freq_range, frame_type);
AssertFatal(prach_info.start_symbol + prach_info.N_t_slot * prach_info.N_dur < 14,
"PRACH with configuration index %ld goes to the last symbol of the slot, for optimal performance pick another index. "
"PRACH with configuration index %ld goes to the last symbol of the slot, for optimal performance pick another index (start_symbold %d, N_t_slot %d, N_dur %d. "
"See Tables 6.3.3.2-2 to 6.3.3.2-4 in 38.211\n",
config_index);
config_index,prach_info.start_symbol, prach_info.N_t_slot, prach_info.N_dur);
// default value for msg3 precoder is NULL (0 means enabled)
if (*rach_ConfigCommon->msg3_transformPrecoder != 0) {
free(rach_ConfigCommon->msg3_transformPrecoder);

View File

@@ -430,6 +430,8 @@ struct openair0_device {
/*!brief Used in ECPRI split 8 to indicate the TX/RX timing offset*/
int txrx_offset;
/*!brief specifies affinity for tx_write_thread*/
int tx_write_thread_affinity;
/* Functions API, which are called by the application*/
/*! \brief Called to start the transceiver. Return 0 if OK, < 0 if error

View File

@@ -681,7 +681,7 @@ int trx_usrp_write_init(openair0_device_t *device)
trx_usrp_write_thread,
(void *)device,
(char*)"trx_usrp_write_thread",
-1,
device->tx_write_thread_affinity,
OAI_PRIORITY_RT_MAX);
return(0);
}
@@ -1165,13 +1165,12 @@ extern "C" {
}
if (device_adds[0].get(type_str) == "x4xx") {
printf("Found USRP x400\n");
printf("Found USRP x400 custom\n");
device->type = USRP_X400_DEV;
usrp_master_clock = 245.76e6;
usrp_master_clock = 491.52e6;
args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock);
// https://kb.ettus.com/USRP_Host_Performance_Tuning_Tips_and_Tricks
if (0 != system("sysctl -w net.core.rmem_max=62500000 net.core.wmem_max=62500000"))
if (0 != system("sysctl -w net.core.rmem_max=250000000 net.core.wmem_max=250000000"))
LOG_W(HW, "Can't set kernel parameters for X4x0\n");
}
@@ -1197,6 +1196,12 @@ extern "C" {
LOG_I(HW,"%s() sample_rate:%u\n", __FUNCTION__, (int)openair0_cfg[0].sample_rate);
switch ((int)openair0_cfg[0].sample_rate) {
case 491520000:
openair0_cfg[0].tx_sample_advance = 15;
openair0_cfg[0].tx_bw = 400e6;
openair0_cfg[0].rx_bw = 400e6;
break;
case 245760000:
// from usrp_time_offset
// openair0_cfg[0].samples_per_packet = 2048;
@@ -1232,6 +1237,7 @@ extern "C" {
case 61440000:
// from usrp_time_offset
//openair0_cfg[0].samples_per_packet = 2048;
printf("sample rate of 40 \n");
openair0_cfg[0].tx_sample_advance = 15;
openair0_cfg[0].tx_bw = 40e6;
openair0_cfg[0].rx_bw = 40e6;

View File

@@ -11,7 +11,7 @@ gNBs =
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1;
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1; }) });
plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1; }) });
nr_cellid = 12345678L;
@@ -19,7 +19,7 @@ gNBs =
do_CSIRS = 1;
do_SRS = 1;
min_rxtxtime = 6;
#uess_agg_levels = [0,1,2,2,1]
servingCellConfigCommon = (
{
@@ -155,13 +155,13 @@ gNBs =
////////// AMF parameters:
amf_ip_address = ({ ipv4 = "192.168.70.132"; });
amf_ip_address = ({ ipv4 = "172.21.6.5"; });
NETWORK_INTERFACES :
{
GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129/24";
GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129/24";
GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.51/24";
GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.51/24";
GNB_PORT_FOR_S1U = 2152; # Spec 2152
};