amarisoft_enb: add NR support

this patch adds the ability to configure NR cells with
Amarisoft eNB. It adds the new DRB-NR template and updates
the normal enb.cfg template to allow using it as LTE only
or with NR cells (5G NSA).

Change-Id: Ia27bbc6db5920ce14bacabe8043601aa2adaa5fe
This commit is contained in:
Andre Puschmann 2021-05-04 16:56:25 +02:00
parent 9b419f32ae
commit 6e081aa1dc
7 changed files with 943 additions and 14 deletions

View File

@ -12,6 +12,7 @@ enb:
mnc: 70 mnc: 70
transmission_mode: 1 transmission_mode: 1
num_cells: 1 num_cells: 1
num_nr_cells: 0
enable_measurements: false enable_measurements: false
a1_report_type: rsrp a1_report_type: rsrp
a1_report_value: -105 a1_report_value: -105

View File

@ -68,12 +68,18 @@ def on_register_schemas():
'cell_list[].ncell_list[].pci': schema.UINT, 'cell_list[].ncell_list[].pci': schema.UINT,
'cell_list[].ncell_list[].dl_earfcn': schema.UINT, 'cell_list[].ncell_list[].dl_earfcn': schema.UINT,
'cell_list[].scell_list[]': schema.UINT, 'cell_list[].scell_list[]': schema.UINT,
'cell_list[].nr_scell_list[]': schema.UINT,
'cell_list[].dl_earfcn': schema.UINT, 'cell_list[].dl_earfcn': schema.UINT,
'cell_list[].root_seq_idx': schema.UINT, 'cell_list[].root_seq_idx': schema.UINT,
'cell_list[].tac': schema.UINT, 'cell_list[].tac': schema.UINT,
'cell_list[].dl_rfemu.type': schema.STR, 'cell_list[].dl_rfemu.type': schema.STR,
'cell_list[].dl_rfemu.addr': schema.IPV4, 'cell_list[].dl_rfemu.addr': schema.IPV4,
'cell_list[].dl_rfemu.ports[]': schema.UINT, 'cell_list[].dl_rfemu.ports[]': schema.UINT,
'num_nr_cells': schema.UINT,
'nr_cell_list[].rf_port': schema.UINT,
'nr_cell_list[].cell_id': schema.UINT,
'nr_cell_list[].band': schema.UINT,
'nr_cell_list[].dl_nr_arfcn': schema.UINT,
} }
for key, val in run_node.RunNode.schema().items(): for key, val in run_node.RunNode.schema().items():
resource_schema['run_node.%s' % key] = val resource_schema['run_node.%s' % key] = val
@ -98,9 +104,11 @@ class eNodeB(log.Origin, metaclass=ABCMeta):
self.set_name('%s_%s' % (name, self._run_node.run_addr())) self.set_name('%s_%s' % (name, self._run_node.run_addr()))
self._txmode = 0 self._txmode = 0
self._id = None self._id = None
self._ran_config = "lte" # Used to determine whether we are in NSA
self._duplex = None self._duplex = None
self._num_prb = 0 self._num_prb = 0
self._num_cells = None self._num_cells = None
self._num_nr_cells = None
self._epc = None self._epc = None
self.gen_conf = None self.gen_conf = None
self.gr_broker = GrBroker.ref() self.gr_broker = GrBroker.ref()
@ -126,10 +134,11 @@ class eNodeB(log.Origin, metaclass=ABCMeta):
def calc_required_zmq_ports(self, cfg_values): def calc_required_zmq_ports(self, cfg_values):
cell_list = cfg_values['enb']['cell_list'] cell_list = cfg_values['enb']['cell_list']
return len(cell_list) * self.num_ports() # *2 if MIMO nr_cell_list = cfg_values['enb']['nr_cell_list']
return len(cell_list) * self.num_ports() + len(nr_cell_list) # *2 if LTE MIMO
def calc_required_zmq_ports_joined_earfcn(self, cfg_values): def calc_required_zmq_ports_joined_earfcn(self, cfg_values):
#gr_broker will join the earfcns, so we need to count uniqe earfcns: #gr_broker will join the earfcns, so we need to count unique earfcns (only implemented for LTE):
cell_list = cfg_values['enb']['cell_list'] cell_list = cfg_values['enb']['cell_list']
earfcn_li = [] earfcn_li = []
[earfcn_li.append(int(cell['dl_earfcn'])) for cell in cell_list if int(cell['dl_earfcn']) not in earfcn_li] [earfcn_li.append(int(cell['dl_earfcn'])) for cell in cell_list if int(cell['dl_earfcn']) not in earfcn_li]
@ -142,6 +151,10 @@ class eNodeB(log.Origin, metaclass=ABCMeta):
for cell in cell_list: for cell in cell_list:
cell[port_name] = base_port + port_offset cell[port_name] = base_port + port_offset
port_offset += self.num_ports() port_offset += self.num_ports()
nr_cell_list = cfg_values['enb']['nr_cell_list']
for nr_cell in nr_cell_list:
nr_cell[port_name] = base_port + port_offset
port_offset += 1
# TODO: do we need to assign cell_list back? # TODO: do we need to assign cell_list back?
def assign_enb_zmq_ports_joined_earfcn(self, cfg_values, port_name, base_port): def assign_enb_zmq_ports_joined_earfcn(self, cfg_values, port_name, base_port):
@ -176,7 +189,9 @@ class eNodeB(log.Origin, metaclass=ABCMeta):
config.overlay(values, dict(enb={ 'mme_addr': self._epc.addr() })) config.overlay(values, dict(enb={ 'mme_addr': self._epc.addr() }))
config.overlay(values, dict(enb={ 'gtp_bind_addr': self._gtp_bind_addr })) config.overlay(values, dict(enb={ 'gtp_bind_addr': self._gtp_bind_addr }))
self._num_cells = int(values['enb'].get('num_cells', None)) self._num_cells = int(values['enb'].get('num_cells', None))
assert self._num_cells self._num_nr_cells = int(values['enb'].get('num_nr_cells', None))
assert self._num_cells is not None
assert self._num_nr_cells is not None
# adjust cell_list to num_cells length: # adjust cell_list to num_cells length:
len_cell_list = len(values['enb']['cell_list']) len_cell_list = len(values['enb']['cell_list'])
@ -231,6 +246,9 @@ class eNodeB(log.Origin, metaclass=ABCMeta):
def num_cells(self): def num_cells(self):
return self._num_cells return self._num_cells
def num_nr_cells(self):
return self._num_nr_cells
######################## ########################
# PUBLIC - INTERNAL API # PUBLIC - INTERNAL API
######################## ########################
@ -280,6 +298,13 @@ class eNodeB(log.Origin, metaclass=ABCMeta):
rf_dev_args += ',rx_port%u=tcp://%s:%u' %(idx + 1, ul_rem_addr, cell['zmq_enb_peer_port'] + 1) rf_dev_args += ',rx_port%u=tcp://%s:%u' %(idx + 1, ul_rem_addr, cell['zmq_enb_peer_port'] + 1)
idx += self.num_ports() idx += self.num_ports()
# Only single antenna supported for NR cells
nr_cell_list = cfg_values['enb']['nr_cell_list']
for nr_cell in nr_cell_list:
rf_dev_args += ',tx_port%u=tcp://%s:%u' % (idx, self.addr(), nr_cell['zmq_enb_bind_port'] + 0)
rf_dev_args += ',rx_port%u=tcp://%s:%u' % (idx, ul_rem_addr, nr_cell['zmq_enb_peer_port'] + 0)
idx += 1
rf_dev_args += ',id=enb,base_srate=' + str(base_srate) rf_dev_args += ',id=enb,base_srate=' + str(base_srate)
return rf_dev_args return rf_dev_args
@ -300,6 +325,14 @@ class eNodeB(log.Origin, metaclass=ABCMeta):
if self.num_ports() > 1: if self.num_ports() > 1:
rf_dev_args += ',rx_port%u=tcp://%s:%u' %(idx + 1, self.addr(), cell['zmq_ue_peer_port'] + 1) rf_dev_args += ',rx_port%u=tcp://%s:%u' %(idx + 1, self.addr(), cell['zmq_ue_peer_port'] + 1)
idx += self.num_ports() idx += self.num_ports()
# NR cells again only with single antenna support
nr_cell_list = self.gen_conf['enb']['nr_cell_list']
for nr_cell in nr_cell_list:
rf_dev_args += ',tx_port%u=tcp://%s:%u' %(idx, ue.addr(), nr_cell['zmq_ue_bind_port'] + 0)
rf_dev_args += ',rx_port%u=tcp://%s:%u' %(idx, self.addr(), nr_cell['zmq_ue_peer_port'] + 0)
idx += 1
# remove trailing comma: # remove trailing comma:
if rf_dev_args[0] == ',': if rf_dev_args[0] == ',':
return rf_dev_args[1:] return rf_dev_args[1:]

View File

@ -22,6 +22,7 @@ import pprint
from ..core import log, util, config, template, process, remote from ..core import log, util, config, template, process, remote
from ..core import schema from ..core import schema
from ..core.event_loop import MainLoop
from . import enb from . import enb
from . import rfemu from . import rfemu
@ -33,12 +34,16 @@ def on_register_schemas():
config_schema = { config_schema = {
'log_options': schema.STR, 'log_options': schema.STR,
'nr_bandwidth': schema.INT,
} }
schema.register_config_schema('amarisoftenb', config_schema) schema.register_config_schema('amarisoftenb', config_schema)
def rf_type_valid(rf_type_str): def rf_type_valid(rf_type_str):
return rf_type_str in ('uhd', 'zmq', 'sdr') return rf_type_str in ('uhd', 'zmq', 'sdr')
def ran_type_valid(ran_type_str):
return ran_type_str in ('lte', '5g_nsa')
class AmarisoftENB(enb.eNodeB): class AmarisoftENB(enb.eNodeB):
REMOTE_DIR = '/osmo-gsm-tester-amarisoftenb' REMOTE_DIR = '/osmo-gsm-tester-amarisoftenb'
@ -48,6 +53,7 @@ class AmarisoftENB(enb.eNodeB):
CFGFILE_SIB23 = 'amarisoft_sib23.asn' CFGFILE_SIB23 = 'amarisoft_sib23.asn'
CFGFILE_RF = 'amarisoft_rf_driver.cfg' CFGFILE_RF = 'amarisoft_rf_driver.cfg'
CFGFILE_DRB = 'amarisoft_drb.cfg' CFGFILE_DRB = 'amarisoft_drb.cfg'
CFGFILE_DRB_NR = 'amarisoft_drb_nr.cfg'
LOGFILE = 'lteenb.log' LOGFILE = 'lteenb.log'
PHY_SIGNAL_FILE = 'lteenb.log.bin' PHY_SIGNAL_FILE = 'lteenb.log.bin'
@ -63,6 +69,7 @@ class AmarisoftENB(enb.eNodeB):
self.config_sib23_file = None self.config_sib23_file = None
self.config_rf_file = None self.config_rf_file = None
self.config_drb_file = None self.config_drb_file = None
self.config_drb_nr_file = None
self.log_file = None self.log_file = None
self.process = None self.process = None
self.rem_host = None self.rem_host = None
@ -72,8 +79,11 @@ class AmarisoftENB(enb.eNodeB):
self.remote_config_sib23_file = None self.remote_config_sib23_file = None
self.remote_config_rf_file = None self.remote_config_rf_file = None
self.remote_config_drb_file = None self.remote_config_drb_file = None
self.remote_config_drb_nr_file = None
self.remote_log_file = None self.remote_log_file = None
self.enable_measurements = False self.enable_measurements = False
self.nr_bandwidth = None
self.ran_type = None
self.testenv = testenv self.testenv = testenv
if not rf_type_valid(conf.get('rf_dev_type', None)): if not rf_type_valid(conf.get('rf_dev_type', None)):
raise log.Error('Invalid rf_dev_type=%s' % conf.get('rf_dev_type', None)) raise log.Error('Invalid rf_dev_type=%s' % conf.get('rf_dev_type', None))
@ -131,8 +141,8 @@ class AmarisoftENB(enb.eNodeB):
self.process.launch() self.process.launch()
def stop(self): def stop(self):
# Not implemented # Allow for some time to flush logs
pass MainLoop.sleep(5)
def gen_conf_file(self, path, filename, values): def gen_conf_file(self, path, filename, values):
self.dbg('AmarisoftENB ' + filename + ':\n' + pprint.pformat(values)) self.dbg('AmarisoftENB ' + filename + ':\n' + pprint.pformat(values))
@ -151,6 +161,7 @@ class AmarisoftENB(enb.eNodeB):
self.config_sib23_file = self.run_dir.child(AmarisoftENB.CFGFILE_SIB23) self.config_sib23_file = self.run_dir.child(AmarisoftENB.CFGFILE_SIB23)
self.config_rf_file = self.run_dir.child(AmarisoftENB.CFGFILE_RF) self.config_rf_file = self.run_dir.child(AmarisoftENB.CFGFILE_RF)
self.config_drb_file = self.run_dir.child(AmarisoftENB.CFGFILE_DRB) self.config_drb_file = self.run_dir.child(AmarisoftENB.CFGFILE_DRB)
self.config_drb_nr_file = self.run_dir.child(AmarisoftENB.CFGFILE_DRB_NR)
self.log_file = self.run_dir.child(AmarisoftENB.LOGFILE) self.log_file = self.run_dir.child(AmarisoftENB.LOGFILE)
self.phy_signal_file = self.run_dir.child(AmarisoftENB.PHY_SIGNAL_FILE) self.phy_signal_file = self.run_dir.child(AmarisoftENB.PHY_SIGNAL_FILE)
@ -165,6 +176,7 @@ class AmarisoftENB(enb.eNodeB):
self.remote_config_sib23_file = remote_run_dir.child(AmarisoftENB.CFGFILE_SIB23) self.remote_config_sib23_file = remote_run_dir.child(AmarisoftENB.CFGFILE_SIB23)
self.remote_config_rf_file = remote_run_dir.child(AmarisoftENB.CFGFILE_RF) self.remote_config_rf_file = remote_run_dir.child(AmarisoftENB.CFGFILE_RF)
self.remote_config_drb_file = remote_run_dir.child(AmarisoftENB.CFGFILE_DRB) self.remote_config_drb_file = remote_run_dir.child(AmarisoftENB.CFGFILE_DRB)
self.remote_config_drb_nr_file = remote_run_dir.child(AmarisoftENB.CFGFILE_DRB_NR)
self.remote_log_file = remote_run_dir.child(AmarisoftENB.LOGFILE) self.remote_log_file = remote_run_dir.child(AmarisoftENB.LOGFILE)
self.remote_phy_signal_file = remote_run_dir.child(AmarisoftENB.PHY_SIGNAL_FILE) self.remote_phy_signal_file = remote_run_dir.child(AmarisoftENB.PHY_SIGNAL_FILE)
@ -176,6 +188,17 @@ class AmarisoftENB(enb.eNodeB):
config.overlay(values, dict(enb={'enable_dl_awgn': util.str2bool(values['enb'].get('enable_dl_awgn', 'false'))})) config.overlay(values, dict(enb={'enable_dl_awgn': util.str2bool(values['enb'].get('enable_dl_awgn', 'false'))}))
self.nr_bandwidth = int(values['enb'].get('nr_bandwidth', 10))
config.overlay(values, dict(enb={'nr_bandwidth': self.nr_bandwidth}))
if (self._num_cells > 0):
if (self._num_nr_cells <= 0):
self.ran_type = "lte"
else:
self.ran_type = "nsa"
else:
raise log.Error('5G SA not supported yet')
# Remove EEA0 from cipher list, if specified, as it's always assumed as default # Remove EEA0 from cipher list, if specified, as it's always assumed as default
cipher_list = values['enb'].get('cipher_list', None) cipher_list = values['enb'].get('cipher_list', None)
if "eea0" in cipher_list: cipher_list.remove("eea0") if "eea0" in cipher_list: cipher_list.remove("eea0")
@ -237,6 +260,7 @@ class AmarisoftENB(enb.eNodeB):
self.gen_conf_file(self.config_sib23_file, AmarisoftENB.CFGFILE_SIB23, values) self.gen_conf_file(self.config_sib23_file, AmarisoftENB.CFGFILE_SIB23, values)
self.gen_conf_file(self.config_rf_file, AmarisoftENB.CFGFILE_RF, values) self.gen_conf_file(self.config_rf_file, AmarisoftENB.CFGFILE_RF, values)
self.gen_conf_file(self.config_drb_file, AmarisoftENB.CFGFILE_DRB, values) self.gen_conf_file(self.config_drb_file, AmarisoftENB.CFGFILE_DRB, values)
self.gen_conf_file(self.config_drb_nr_file, AmarisoftENB.CFGFILE_DRB_NR, values)
if not self._run_node.is_local(): if not self._run_node.is_local():
self.rem_host.recreate_remote_dir(self.remote_inst) self.rem_host.recreate_remote_dir(self.remote_inst)
@ -247,6 +271,7 @@ class AmarisoftENB(enb.eNodeB):
self.rem_host.scp('scp-cfg-sib23-to-remote', self.config_sib23_file, self.remote_config_sib23_file) self.rem_host.scp('scp-cfg-sib23-to-remote', self.config_sib23_file, self.remote_config_sib23_file)
self.rem_host.scp('scp-cfg-rr-to-remote', self.config_rf_file, self.remote_config_rf_file) self.rem_host.scp('scp-cfg-rr-to-remote', self.config_rf_file, self.remote_config_rf_file)
self.rem_host.scp('scp-cfg-drb-to-remote', self.config_drb_file, self.remote_config_drb_file) self.rem_host.scp('scp-cfg-drb-to-remote', self.config_drb_file, self.remote_config_drb_file)
self.rem_host.scp('scp-cfg-drb-nr-to-remote', self.config_drb_nr_file, self.remote_config_drb_nr_file)
def ue_add(self, ue): def ue_add(self, ue):
if self.ue is not None: if self.ue is not None:
@ -279,11 +304,17 @@ class AmarisoftENB(enb.eNodeB):
rfemu_obj = rfemu.get_instance_by_type(rfemu_cfg['type'], rfemu_cfg) rfemu_obj = rfemu.get_instance_by_type(rfemu_cfg['type'], rfemu_cfg)
return rfemu_obj return rfemu_obj
def get_nr_bandwidth(self):
return self.nr_bandwidth
def ue_max_rate(self, downlink=True, num_carriers=1): def ue_max_rate(self, downlink=True, num_carriers=1):
if self.ran_type == 'lte':
if self._duplex == 'fdd': if self._duplex == 'fdd':
return self.ue_max_rate_fdd(downlink, num_carriers) return self.ue_max_rate_fdd(downlink, num_carriers)
else: else:
return self.ue_max_rate_tdd(downlink, num_carriers) return self.ue_max_rate_tdd(downlink, num_carriers)
else:
return self.ue_max_rate_nsa_tdd(downlink)
def ue_max_rate_fdd(self, downlink, num_carriers): def ue_max_rate_fdd(self, downlink, num_carriers):
# The max rate for a single UE per PRB configuration in TM1 with MCS 28 QAM64 # The max rate for a single UE per PRB configuration in TM1 with MCS 28 QAM64
@ -323,7 +354,7 @@ class AmarisoftENB(enb.eNodeB):
return max_rate return max_rate
def ue_max_rate_tdd(self, downlink, num_carriers): def ue_max_rate_tdd(self, downlink, num_carriers):
# Max rate calculation for TDD depends on the acutal TDD configuration # Max rate calculation for TDD depends on the actual TDD configuration
# See: https://www.sharetechnote.com/html/Handbook_LTE_ThroughputCalculationExample_TDD.html # See: https://www.sharetechnote.com/html/Handbook_LTE_ThroughputCalculationExample_TDD.html
# and https://i0.wp.com/www.techtrained.com/wp-content/uploads/2017/09/Blog_Post_1_TDD_Max_Throughput_Theoretical.jpg # and https://i0.wp.com/www.techtrained.com/wp-content/uploads/2017/09/Blog_Post_1_TDD_Max_Throughput_Theoretical.jpg
max_phy_rate_tdd_uldl_config0_sp0 = { 6 : 1.5e6, max_phy_rate_tdd_uldl_config0_sp0 = { 6 : 1.5e6,
@ -333,8 +364,21 @@ class AmarisoftENB(enb.eNodeB):
75 : 18.4e6, 75 : 18.4e6,
100 : 54.5e6 } 100 : 54.5e6 }
if downlink: if downlink:
max_rate = max_phy_rate_tdd_uldl_config0_sp0[self.num_prb()] return max_phy_rate_tdd_uldl_config0_sp0[self.num_prb()]
else: else:
return 1e6 # dummy value, we need to replace that later return 1e6 # dummy value, we need to replace that later
def ue_max_rate_nsa_tdd(self, downlink):
# Max rate calculation based on https://5g-tools.com/5g-nr-throughput-calculator/
# Only FR1 15kHz SCS, QAM64, 6 DL slots, 3 UL slots
max_phy_rate_nsa_dl_fr1_15khz = { 10: 18.4e6,
20: 38.0e6 }
max_phy_rate_nsa_ul_fr1_15khz = { 10: 10.7e6,
20: 23.0e6 }
if downlink:
return max_phy_rate_nsa_dl_fr1_15khz[self.get_nr_bandwidth()]
else:
return max_phy_rate_nsa_ul_fr1_15khz[self.get_nr_bandwidth()]
# vim: expandtab tabstop=4 shiftwidth=4 # vim: expandtab tabstop=4 shiftwidth=4

View File

@ -0,0 +1,423 @@
/* DRB configuration for each QCI value.
QCI characteristics in TS 23.203 table 6.1.7 */
[
/**************************************** GBR */
{
qci: 1, /* UM - real time (RTP for VOIP) */
use_for_en_dc: false,
pdcp_config: {
discardTimer: 100, /* in ms, 0 means infinity */
pdcp_SN_SizeUL: 12,
pdcp_SN_SizeDL: 12,
statusReportRequired: false,
outOfOrderDelivery: false,
t_Reordering: 0,
/* ROHC header compression */
/*
headerCompression: {
maxCID: 15,
profile0x0001: true, // RTP profile
profile0x0002: true, // UDP profile
profile0x0004: false, // IP profile
},
*/
},
rlc_config: {
ul_um: {
sn_FieldLength: 6,
},
dl_um: {
sn_FieldLength: 6,
t_Reassembly: 50,
},
},
logical_channel_config: {
priority: 7,
prioritisedBitRate: 0, /* in kb/s, -1 means infinity */
bucketSizeDuration: 100, /* in ms */
logicalChannelGroup: 1,
},
},
{
qci: 2, /* UM - real time (video) */
pdcp_config: {
discardTimer: 150, /* in ms, 0 means infinity */
pdcp_SN_SizeUL: 18,
pdcp_SN_SizeDL: 18,
statusReportRequired: false,
outOfOrderDelivery: false,
t_Reordering: 0,
},
rlc_config: {
ul_um: {
sn_FieldLength: 12,
},
dl_um: {
sn_FieldLength: 12,
t_Reassembly: 50,
},
},
logical_channel_config: {
priority: 8,
prioritisedBitRate: 0, /* in kb/s, -1 means infinity */
bucketSizeDuration: 100, /* in ms */
logicalChannelGroup: 1,
},
},
{
qci: 3, /* UM - real time (gaming) */
pdcp_config: {
discardTimer: 100, /* in ms, 0 means infinity */
pdcp_SN_SizeUL: 18,
pdcp_SN_SizeDL: 18,
statusReportRequired: false,
outOfOrderDelivery: false,
t_Reordering: 0,
},
rlc_config: {
ul_um: {
sn_FieldLength: 12,
},
dl_um: {
sn_FieldLength: 12,
t_Reassembly: 50,
},
},
logical_channel_config: {
priority: 7,
prioritisedBitRate: 0, /* in kb/s, -1 means infinity */
bucketSizeDuration: 100, /* in ms */
logicalChannelGroup: 2,
},
},
{
qci: 4, /* AM - Non-Conversational Video (Buffered Streaming) */
pdcp_config: {
discardTimer: 0, /* in ms, 0 means infinity */
pdcp_SN_SizeUL: 18,
pdcp_SN_SizeDL: 18,
statusReportRequired: true,
outOfOrderDelivery: false,
},
rlc_config: {
ul_am: {
sn_FieldLength: 18,
t_PollRetransmit: 80, /* in ms */
pollPDU: 64,
pollByte: 125, /* in kBytes, 0 means infinity */
maxRetxThreshold: 4,
},
dl_am: {
sn_FieldLength: 18,
t_Reassembly: 80, /* in ms */
t_StatusProhibit: 10, /* in ms */
},
},
logical_channel_config: {
priority: 9,
prioritisedBitRate: 8, /* in kb/s, -1 means infinity */
bucketSizeDuration: 100, /* in ms */
logicalChannelGroup: 3,
},
},
{
qci: 65, /* UM - real time (MC-PTT voice) */
use_for_en_dc: false,
pdcp_config: {
discardTimer: 100, /* in ms, 0 means infinity */
pdcp_SN_SizeUL: 12,
pdcp_SN_SizeDL: 12,
statusReportRequired: false,
outOfOrderDelivery: false,
t_Reordering: 0,
/* ROHC header compression */
/*
headerCompression: {
maxCID: 15,
profile0x0001: true, // RTP profile
profile0x0002: true, // UDP profile
profile0x0004: false, // IP profile
},
*/
},
rlc_config: {
ul_um: {
sn_FieldLength: 6,
},
dl_um: {
sn_FieldLength: 6,
t_Reassembly: 50,
},
},
logical_channel_config: {
priority: 5,
prioritisedBitRate: 0, /* in kb/s, -1 means infinity */
bucketSizeDuration: 100, /* in ms */
logicalChannelGroup: 4,
},
},
{
qci: 66, /* UM - real time (non MC-PTT voice) */
use_for_en_dc: false,
pdcp_config: {
discardTimer: 150, /* in ms, 0 means infinity */
pdcp_SN_SizeUL: 18,
pdcp_SN_SizeDL: 18,
statusReportRequired: false,
outOfOrderDelivery: false,
t_Reordering: 0,
},
rlc_config: {
ul_um: {
sn_FieldLength: 12,
},
dl_um: {
sn_FieldLength: 12,
t_Reassembly: 50,
},
},
logical_channel_config: {
priority: 7,
prioritisedBitRate: 0, /* in kb/s, -1 means infinity */
bucketSizeDuration: 100, /* in ms */
logicalChannelGroup: 4,
},
},
{
qci: 67, /* UM - Mission Critical Video user plane */
use_for_en_dc: false,
pdcp_config: {
discardTimer: 100, /* in ms, 0 means infinity */
pdcp_SN_SizeUL: 18,
pdcp_SN_SizeDL: 18,
statusReportRequired: false,
outOfOrderDelivery: false,
t_Reordering: 0,
},
rlc_config: {
ul_um: {
sn_FieldLength: 12,
},
dl_um: {
sn_FieldLength: 12,
t_Reassembly: 50,
},
},
logical_channel_config: {
priority: 6,
prioritisedBitRate: 0, /* in kb/s, -1 means infinity */
bucketSizeDuration: 100, /* in ms */
logicalChannelGroup: 5,
},
},
/**************************************** non GBR */
{
qci: 5, /* AM - high priority (SIP) */
use_for_en_dc: false,
pdcp_config: {
discardTimer: 0, /* in ms, 0 means infinity */
pdcp_SN_SizeUL: 18,
pdcp_SN_SizeDL: 18,
statusReportRequired: true,
outOfOrderDelivery: false,
},
rlc_config: {
ul_am: {
sn_FieldLength: 18,
t_PollRetransmit: 80, /* in ms */
pollPDU: 64,
pollByte: 125, /* in kBytes, 0 means infinity */
maxRetxThreshold: 4,
},
dl_am: {
sn_FieldLength: 18,
t_Reassembly: 80, /* in ms */
t_StatusProhibit: 10, /* in ms */
},
},
logical_channel_config: {
priority: 6,
prioritisedBitRate: 8, /* in kb/s, -1 means infinity */
bucketSizeDuration: 100, /* in ms */
logicalChannelGroup: 4,
},
},
{
qci: 6, /* AM - Video (buffered streaming) */
pdcp_config: {
discardTimer: 0, /* in ms, 0 means infinity */
pdcp_SN_SizeUL: 18,
pdcp_SN_SizeDL: 18,
statusReportRequired: true,
outOfOrderDelivery: false,
},
rlc_config: {
ul_am: {
sn_FieldLength: 18,
t_PollRetransmit: 80, /* in ms */
pollPDU: 64,
pollByte: 125, /* in kBytes, 0 means infinity */
maxRetxThreshold: 4,
},
dl_am: {
sn_FieldLength: 18,
t_Reassembly: 80, /* in ms */
t_StatusProhibit: 10, /* in ms */
},
},
logical_channel_config: {
priority: 10,
prioritisedBitRate: 8, /* in kb/s, -1 means infinity */
bucketSizeDuration: 100, /* in ms */
logicalChannelGroup: 5,
},
},
{
qci: 7, /* UM - voice, video (live streaming), interactive gaming */
pdcp_config: {
discardTimer: 100, /* in ms, 0 means infinity */
pdcp_SN_SizeUL: 18,
pdcp_SN_SizeDL: 18,
statusReportRequired: false,
outOfOrderDelivery: false,
t_Reordering: 0,
},
rlc_config: {
ul_um: {
sn_FieldLength: 12,
},
dl_um: {
sn_FieldLength: 12,
t_Reassembly: 50,
},
},
logical_channel_config: {
priority: 11,
prioritisedBitRate: 0, /* in kb/s, -1 means infinity */
bucketSizeDuration: 100, /* in ms */
logicalChannelGroup: 6,
},
},
{
qci: 8, /* AM - best effort (Internet traffic) */
pdcp_config: {
discardTimer: 0, /* in ms, 0 means infinity */
pdcp_SN_SizeUL: 18,
pdcp_SN_SizeDL: 18,
statusReportRequired: true,
outOfOrderDelivery: false,
},
rlc_config: {
ul_am: {
sn_FieldLength: 18,
t_PollRetransmit: 80, /* in ms */
pollPDU: 64,
pollByte: 125, /* in kBytes, 0 means infinity */
maxRetxThreshold: 4,
},
dl_am: {
sn_FieldLength: 18,
t_Reassembly: 80, /* in ms */
t_StatusProhibit: 10, /* in ms */
},
},
logical_channel_config: {
priority: 12,
prioritisedBitRate: 8, /* in kb/s, -1 means infinity */
bucketSizeDuration: 100, /* in ms */
logicalChannelGroup: 7,
},
},
{
qci: 9, /* AM - best effort (Internet traffic) */
pdcp_config: {
discardTimer: 0, /* in ms, 0 means infinity */
pdcp_SN_SizeUL: 18,
pdcp_SN_SizeDL: 18,
statusReportRequired: true,
outOfOrderDelivery: false,
},
rlc_config: {
ul_am: {
sn_FieldLength: 18,
t_PollRetransmit: 80, /* in ms */
pollPDU: 64,
pollByte: 125, /* in kBytes, 0 means infinity */
maxRetxThreshold: 4,
},
dl_am: {
sn_FieldLength: 18,
t_Reassembly: 80, /* in ms */
t_StatusProhibit: 10, /* in ms */
},
},
logical_channel_config: {
priority: 13,
prioritisedBitRate: 8, /* in kb/s, -1 means infinity */
bucketSizeDuration: 100, /* in ms */
logicalChannelGroup: 7,
},
},
{
qci: 69, /* AM - high priority (MC-PTT signalling) */
use_for_en_dc: false,
pdcp_config: {
discardTimer: 0, /* in ms, 0 means infinity */
pdcp_SN_SizeUL: 18,
pdcp_SN_SizeDL: 18,
statusReportRequired: true,
outOfOrderDelivery: false,
},
rlc_config: {
ul_am: {
sn_FieldLength: 18,
t_PollRetransmit: 80, /* in ms */
pollPDU: 64,
pollByte: 125, /* in kBytes, 0 means infinity */
maxRetxThreshold: 4,
},
dl_am: {
sn_FieldLength: 18,
t_Reassembly: 80, /* in ms */
t_StatusProhibit: 10, /* in ms */
},
},
logical_channel_config: {
priority: 4,
prioritisedBitRate: 8, /* in kb/s, -1 means infinity */
bucketSizeDuration: 100, /* in ms */
logicalChannelGroup: 4,
},
},
{
qci: 70, /* AM - MC data */
use_for_en_dc: false,
pdcp_config: {
discardTimer: 0, /* in ms, 0 means infinity */
pdcp_SN_SizeUL: 18,
pdcp_SN_SizeDL: 18,
statusReportRequired: true,
outOfOrderDelivery: false,
},
rlc_config: {
ul_am: {
sn_FieldLength: 18,
t_PollRetransmit: 80, /* in ms */
pollPDU: 64,
pollByte: 125, /* in kBytes, 0 means infinity */
maxRetxThreshold: 4,
},
dl_am: {
sn_FieldLength: 18,
t_Reassembly: 80, /* in ms */
t_StatusProhibit: 10, /* in ms */
},
},
logical_channel_config: {
priority: 11,
prioritisedBitRate: 8, /* in kb/s, -1 means infinity */
bucketSizeDuration: 100, /* in ms */
logicalChannelGroup: 5,
},
},
]

View File

@ -1,6 +1,5 @@
/* lteenb configuration file version 2018-10-18 /* OGT templated version of the lteenb configuration file for 4G and 5G NSA */
* Copyright (C) 2015-2018 Amarisoft
*/
{ {
%if enb.license_server_addr != '0.0.0.0': %if enb.license_server_addr != '0.0.0.0':
@ -64,10 +63,15 @@
/* high 20 bits of SIB1.cellIdentifier */ /* high 20 bits of SIB1.cellIdentifier */
enb_id: ${enb.id}, enb_id: ${enb.id},
% if int(enb.num_nr_cells) > 0:
nr_support: true,
% endif
/* list of cells */ /* list of cells */
cell_list: [ cell_list: [
%for cell in enb.cell_list: %for cell in enb.cell_list:
%if loop.index == 0:
{ {
dl_earfcn: ${cell.dl_earfcn}, dl_earfcn: ${cell.dl_earfcn},
rf_port: ${cell.rf_port}, rf_port: ${cell.rf_port},
@ -85,12 +89,38 @@
scell_list: [ scell_list: [
%for scell_id in cell.scell_list: %for scell_id in cell.scell_list:
{ cell_id: ${scell_id}, cross_carrier_scheduling: false, scheduling_cell_id: ${cell.cell_id}, ul_allowed: true}, { cell_id: ${scell_id}, cross_carrier_scheduling: false, scheduling_cell_id: ${cell.cell_id}, ul_allowed: true},
%endfor
],
nr_scell_list: [
%for nr_scell_id in cell.nr_scell_list:
{ cell_id: ${nr_scell_id} },
%endfor %endfor
], ],
}, },
%endif
%endfor %endfor
], /* cell_list */ ], /* cell_list */
% if int(enb.num_nr_cells) > 0:
nr_cell_list: [
%for nr_cell in enb.nr_cell_list:
%if loop.index == 0:
{
rf_port: ${nr_cell.rf_port},
cell_id: ${nr_cell.cell_id},
band: ${nr_cell.band},
dl_nr_arfcn: ${nr_cell.dl_nr_arfcn},
},
%endif
%endfor
], /* nr_cell_list */
% endif
/* default cell parameters */ /* default cell parameters */
cell_default: { cell_default: {
/* Broadcasted PLMN identities */ /* Broadcasted PLMN identities */
@ -123,7 +153,11 @@
/* other SIBs, in same order as the scheduling list in SIB 1 */ /* other SIBs, in same order as the scheduling list in SIB 1 */
sib_sched_list: [ "amarisoft_sib23.asn" ], sib_sched_list: [ "amarisoft_sib23.asn" ],
% if int(enb.num_prb) == 6:
si_coderate: 0.30, /* maximum code rate for SI/RA/P-RNTI messages */ si_coderate: 0.30, /* maximum code rate for SI/RA/P-RNTI messages */
% else:
si_coderate: 0.20, /* maximum code rate for SI/RA/P-RNTI messages */
% endif
si_pdcch_format: 2, /* 2 or 3. Log2 of the number of CCEs for PDCCH si_pdcch_format: 2, /* 2 or 3. Log2 of the number of CCEs for PDCCH
for SI/RA/P-RNTI */ for SI/RA/P-RNTI */
@ -154,7 +188,11 @@
pusch_msg3_mcs: 0, pusch_msg3_mcs: 0,
/* this CQI value is assumed when none is received from the UE */ /* this CQI value is assumed when none is received from the UE */
% if int(enb.num_prb) == 6:
initial_cqi: 5, initial_cqi: 5,
% else:
initial_cqi: 3,
% endif
/* if defined, force the PUSCH MCS for all UEs. Otherwise it is /* if defined, force the PUSCH MCS for all UEs. Otherwise it is
computed from the last received SRS/PUSCH. */ computed from the last received SRS/PUSCH. */
@ -162,6 +200,9 @@
transmission_mode: ${enb.transmission_mode}, transmission_mode: ${enb.transmission_mode},
dl_256qam: true,
ul_64qam: true,
/* Scheduling request period (ms). Must be >= 40 for HD-FDD */ /* Scheduling request period (ms). Must be >= 40 for HD-FDD */
sr_period: 20, sr_period: 20,
@ -188,6 +229,9 @@
// tdd_ack_nack_feedback_mode_r10: "cs", // tdd_ack_nack_feedback_mode_r10: "cs",
% endif % endif
n1_pucch_sr_count: 11, /* increase if more UEs are needed */
cqi_pucch_n_rb: 1, /* increase if more UEs are needed */
/* number of PUCCH 1b CS resources. It determines /* number of PUCCH 1b CS resources. It determines
the maximum number of UEs that can be scheduled in one TTI the maximum number of UEs that can be scheduled in one TTI
using carrier aggregation with PUCCH 1b CS ack/nack feedback. */ using carrier aggregation with PUCCH 1b CS ack/nack feedback. */
@ -266,6 +310,14 @@
a3_offset: ${enb.a3_report_value}, a3_offset: ${enb.a3_report_value},
a3_hysteresis: ${enb.a3_hysteresis}, a3_hysteresis: ${enb.a3_hysteresis},
a3_time_to_trigger: ${enb.a3_time_to_trigger}, a3_time_to_trigger: ${enb.a3_time_to_trigger},
% if int(enb.num_nr_cells) > 0:
// NR events hard-coded
nr_b1_report_type: "rsrp",
nr_b1_rsrp: -100,
nr_b1_hysteresis: 0,
nr_b1_time_to_trigger: 100,
nr_rsrp_filter_coeff: 3
% endif
}, },
/* measurement gap configuration */ /* measurement gap configuration */
@ -276,4 +328,357 @@
ho_from_meas: true, ho_from_meas: true,
% endif % endif
}, },
% if int(enb.num_nr_cells) > 0:
nr_cell_default: {
subcarrier_spacing: 15, /* kHz */
ssb_subcarrier_spacing: 30,
bandwidth: ${enb.nr_bandwidth}, /* MHz */
n_antenna_dl: 1,
n_antenna_ul: 1,
/* force the timing TA offset (optional) */
n_timing_advance_offset: 0,
tdd_ul_dl_config: {
pattern1: {
period: 10,
dl_slots: 6,
dl_symbols: 0,
ul_slots: 3,
ul_symbols: 0,
},
},
ssb_pos_bitmap: "10000000",
ssb_period: 20, /* in ms */
n_id_cell: 500,
root_sequence_index: 1, /* PRACH root sequence index */
/* Scheduling request period (slots). */
sr_period: 40,
dmrs_type_a_pos: 2,
/* to limit the number of HARQ feedback in UL, use pdsch_harq_ack_max;
allows to workaround issues with SM-G977N for example */
//pdsch_harq_ack_max: 2,
prach: {
prach_config_index: 0,
msg1_subcarrier_spacing: 15, /* kHz */
msg1_fdm: 1,
% if int(enb.nr_bandwidth) == 10:
msg1_frequency_start: 1,
% else:
msg1_frequency_start: 3,
% endif
zero_correlation_zone_config: 0,
preamble_received_target_power: -110, /* in dBm */
preamble_trans_max: 7,
power_ramping_step: 4, /* in dB */
ra_response_window: 10, /* in slots */
restricted_set_config: "unrestricted_set",
ra_contention_resolution_timer: 64, /* in ms */
ssb_per_prach_occasion: 1,
cb_preambles_per_ssb: 8,
},
pdcch: {
common_coreset: {
rb_start: -1, /* -1 to have the maximum bandwidth */
l_crb: -1, /* -1 means all the bandwidth */
duration: 1,
precoder_granularity: "sameAsREG_bundle",
//dmrs_scid: 0,
},
dedicated_coreset: {
rb_start: -1, /* -1 to have the maximum bandwidth */
l_crb: -1, /* -1 means all the bandwidth */
duration: 1,
precoder_granularity: "sameAsREG_bundle",
//dmrs_scid: 0,
},
css: {
n_candidates: [ 1, 1, 1, 0, 0 ],
},
rar_al_index: 2,
uss: {
n_candidates: [ 0, 2, 1, 0, 0 ],
dci_0_1_and_1_1: false,
force_dci_0_0: true, // Forces DCI format 0_0 for Uplink
force_dci_1_0: true, // Forces DCI format 1_0 for Downlink
},
al_index: 1,
},
pdsch: {
mapping_type: "typeA",
start_symb: 1,
n_symb: 13,
dmrs_add_pos: 1,
dmrs_type: 1,
dmrs_max_len: 1,
k0: 0, /* delay in slots from DCI to PDSCH */
/* delay in slots from PDSCH to PUCCH/PUSCH ACK/NACK */
k1: [ 8, 7, 6, 6, 5, 4],
mcs_table: "qam64",
rar_mcs: 2,
/* If defined, force the PDSCH MCS for all UEs. Otherwise it is computed
* based on DL channel quality estimation */
/* mcs: 24, */
},
csi_rs: {
nzp_csi_rs_resource: [
{
csi_rs_id: 0,
n_ports: 1,
frequency_domain_allocation: "row2",
bitmap: "100000000000",
cdm_type: "no_cdm",
density: 1,
first_symb: 4,
rb_start: 0,
l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
power_control_offset: 0, /* dB */
power_control_offset_ss: 0, /* dB */
scrambling_id: 0,
period: 80,
offset: 1, /* != 0 to avoid collision with SSB */
qcl_info_periodic_csi_rs: 0,
},
#define USE_TRS
#ifdef USE_TRS
/* TRS : period of 40 ms, slots 1 & 2, symbols 4 and 8 */
{
csi_rs_id: 1,
n_ports: 1,
frequency_domain_allocation: "row1",
bitmap: "0001",
cdm_type: "no_cdm",
density: 3,
first_symb: 4,
rb_start: 0,
l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
power_control_offset: 0, /* dB */
power_control_offset_ss: 0, /* dB */
scrambling_id: 0,
period: 40,
offset: 11,
qcl_info_periodic_csi_rs: 0,
},
{
csi_rs_id: 2,
n_ports: 1,
frequency_domain_allocation: "row1",
bitmap: "0001",
cdm_type: "no_cdm",
density: 3,
first_symb: 8,
rb_start: 0,
l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
power_control_offset: 0, /* dB */
power_control_offset_ss: 0, /* dB */
scrambling_id: 0,
period: 40,
offset: 11,
qcl_info_periodic_csi_rs: 0,
},
{
csi_rs_id: 3,
n_ports: 1,
frequency_domain_allocation: "row1",
bitmap: "0001",
cdm_type: "no_cdm",
density: 3,
first_symb: 4,
rb_start: 0,
l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
power_control_offset: 0, /* dB */
power_control_offset_ss: 0, /* dB */
scrambling_id: 0,
period: 40,
offset: 12,
qcl_info_periodic_csi_rs: 0,
},
{
csi_rs_id: 4,
n_ports: 1,
frequency_domain_allocation: "row1",
bitmap: "0001",
cdm_type: "no_cdm",
density: 3,
first_symb: 8,
rb_start: 0,
l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
power_control_offset: 0, /* dB */
power_control_offset_ss: 0, /* dB */
scrambling_id: 0,
period: 40,
offset: 12,
qcl_info_periodic_csi_rs: 0,
},
#endif
],
nzp_csi_rs_resource_set: [
{
csi_rs_set_id: 0,
nzp_csi_rs_resources: [ 0 ],
repetition: false,
},
#ifdef USE_TRS
{
csi_rs_set_id: 1,
nzp_csi_rs_resources: [ 1, 2, 3, 4 ],
repetition: false,
trs_info: true,
},
#endif
],
csi_im_resource: [
{
csi_im_id: 0,
pattern: 1,
subcarrier_location: 8,
symbol_location: 8,
rb_start: 0,
l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
period: 80,
offset: 1, /* != 0 to avoid collision with SSB */
},
],
csi_im_resource_set: [
{
csi_im_set_id: 0,
csi_im_resources: [ 0 ],
}
],
/* ZP CSI-RS to set the CSI-IM REs to zero */
zp_csi_rs_resource: [
{
csi_rs_id: 0,
frequency_domain_allocation: "row4",
bitmap: "100",
n_ports: 4,
cdm_type: "fd_cdm2",
first_symb: 8,
density: 1,
rb_start: 0,
l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
period: 80,
offset: 1,
},
],
p_zp_csi_rs_resource_set: [
{
zp_csi_rs_resources: [ 0 ],
},
],
csi_resource_config: [
{
csi_rsc_config_id: 0,
nzp_csi_rs_resource_set_list: [ 0 ],
resource_type: "periodic",
},
{
csi_rsc_config_id: 1,
csi_im_resource_set_list: [ 0 ],
resource_type: "periodic",
},
#ifdef USE_TRS
{
csi_rsc_config_id: 2,
nzp_csi_rs_resource_set_list: [ 1 ],
resource_type: "periodic",
},
#endif
],
csi_report_config: [
{
resources_for_channel_measurement: 0,
csi_im_resources_for_interference: 1,
report_config_type: "periodic",
period: 80,
report_quantity: "CRI_RI_PMI_CQI",
cqi_table: 2,
subband_size: "value1",
},
],
},
pucch: {
pucch_group_hopping: "neither",
hopping_id: -1, /* -1 = n_cell_id */
p0_nominal: -90,
pucch1: {
n_cs: 3,
n_occ: 3,
freq_hopping: false,
},
pucch2: {
n_symb: 2,
n_prb: 1,
freq_hopping: false,
simultaneous_harq_ack_csi: false,
max_code_rate: 0.25,
},
},
pusch: {
mapping_type: "typeA",
n_symb: 14,
dmrs_add_pos: 1,
dmrs_type: 1,
dmrs_max_len: 1,
tf_precoding: false,
mcs_table: "qam64", /* without transform precoding */
mcs_table_tp: "qam64", /* with transform precoding */
ldpc_max_its: 5,
k2: 4, /* delay in slots from DCI to PUSCH */
p0_nominal_with_grant: -90,
msg3_k2: 5,
msg3_mcs: 4,
msg3_delta_power: 0, /* in dB */
beta_offset_ack_index: 9,
/* hardcoded scheduling parameters */
n_dmrs_cdm_groups: 1,
n_layer: 1,
/* if defined, force the PUSCH MCS for all UEs. Otherwise it is
computed from the last received PUSCH. */
//mcs: 16,
//max_mcs: 16,
},
/* MAC configuration */
mac_config: {
msg3_max_harq_tx: 5,
ul_max_harq_tx: 5, /* max number of HARQ transmissions for uplink */
dl_max_harq_tx: 5, /* max number of HARQ transmissions for downlink */
ul_max_consecutive_retx: 30, /* disconnect UE if reached */
dl_max_consecutive_retx: 30, /* disconnect UE if reached */
periodic_bsr_timer: 20,
retx_bsr_timer: 320,
periodic_phr_timer: 500,
prohibit_phr_timer: 200,
phr_tx_power_factor_change: "dB3",
sr_prohibit_timer: 0, /* in ms, 0 to disable the timer */
sr_trans_max: 64,
},
cipher_algo_pref: [${', '.join(list(dict.fromkeys(enb.cipher_list))).split("eea")[1] if len(list(dict.fromkeys(enb.cipher_list))) > 0 else ''}],
integ_algo_pref: [${', '.join(list(dict.fromkeys(enb.integrity_list))).split("eia")[1]}],
inactivity_timer: ${enb.inactivity_timer},
drb_config: "amarisoft_drb_nr.cfg",
},
% endif
} }

View File

@ -15,6 +15,26 @@ rf_driver: {
tx_gain: ${trx.tx_gain}, /* TX gain (in dB) B2x0: 0 to 89.8 dB */ tx_gain: ${trx.tx_gain}, /* TX gain (in dB) B2x0: 0 to 89.8 dB */
rx_gain: ${trx.rx_gain}, /* RX gain (in dB) B2x0: 0 to 73 dB */ rx_gain: ${trx.rx_gain}, /* RX gain (in dB) B2x0: 0 to 73 dB */
rf_ports: [
% if trx.rf_dev_type == 'sdr':
{
sample_rate: 23.04,
},
{
sample_rate: 61.44,
dl_freq: 3502.8, // Moves NR DL LO frequency -5.76 MHz
ul_freq: 3502.8, // Moves NR UL LO frequency -5.76 MHz
}
% else:
{
sample_rate: ${enb.sample_rate},
},
{
sample_rate: ${enb.sample_rate},
}
% endif
],
// only the B210 requires a sample offset // only the B210 requires a sample offset
% if "b200" in trx.rf_dev_args: % if "b200" in trx.rf_dev_args:
tx_time_offset: -150, tx_time_offset: -150,

View File

@ -114,6 +114,7 @@ enb:
duplex: fdd duplex: fdd
transmission_mode: 1 transmission_mode: 1
num_cells: 1 num_cells: 1
num_nr_cells: 0
inactivity_timer: 20000 inactivity_timer: 20000
enable_measurements: false enable_measurements: false
enable_dl_awgn: false enable_dl_awgn: false
@ -147,6 +148,8 @@ enb:
root_seq_idx: 205 root_seq_idx: 205
scell_list: [] scell_list: []
ncell_list: [] ncell_list: []
nr_scell_list: []
nr_cell_list: []
cipher_list: cipher_list:
- eea0 - eea0
- eea2 - eea2