Merge branch 'sim-channels' of https://gitlab.eurecom.fr/oai/openairinterface5g into sim-channels
This commit is contained in:
@@ -164,6 +164,9 @@ function build_on_vm {
|
||||
echo "cd tmp" >> $VM_CMDS
|
||||
echo "echo \"unzip -qq -DD ../localZip.zip\"" >> $VM_CMDS
|
||||
echo "unzip -qq -DD ../localZip.zip" >> $VM_CMDS
|
||||
# Trying to make some room on filesystem before building
|
||||
echo "rm ../localZip.zip" >> $VM_CMDS
|
||||
echo "export CI_ENV=True" >> $VM_CMDS
|
||||
if [[ "$VM_NAME" == *"-cppcheck"* ]]
|
||||
then
|
||||
echo "mkdir cmake_targets/log" >> $VM_CMDS
|
||||
|
||||
@@ -0,0 +1,292 @@
|
||||
Active_gNBs = ( "gNB-Eurecom-5GNRBox");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
gNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
gNB_ID = 0xe00;
|
||||
|
||||
cell_type = "CELL_MACRO_GNB";
|
||||
|
||||
gNB_name = "gNB-Eurecom-5GNRBox";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
|
||||
plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;});
|
||||
|
||||
tr_s_preference = "local_mac"
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
ssb_SubcarrierOffset = 0;
|
||||
pdsch_AntennaPorts = 1;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
#spCellConfigCommon
|
||||
|
||||
physCellId = 0;
|
||||
|
||||
# downlinkConfigCommon
|
||||
#frequencyInfoDL
|
||||
# this is 2150 MHz + 43 PRBs@30kHz SCS (same as initial BWP)
|
||||
absoluteFrequencySSB = 433096;
|
||||
dl_frequencyBand = 66;
|
||||
# this is 2150 MHz
|
||||
dl_absoluteFrequencyPointA = 430000;
|
||||
#scs-SpecificCarrierList
|
||||
dl_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
dl_subcarrierSpacing = 1;
|
||||
dl_carrierBandwidth = 106;
|
||||
#initialDownlinkBWP
|
||||
#genericParameters
|
||||
# this is RBstart=0,L=50 (275*(L-1))+RBstart
|
||||
initialDLBWPlocationAndBandwidth = 13475;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing = 1;
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 12;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
#pdsch-ConfigCommon
|
||||
#pdschTimeDomainAllocationList (up to 16 entries)
|
||||
initialDLBWPk0_0 = 0;
|
||||
#initialULBWPmappingType
|
||||
#0=typeA,1=typeB
|
||||
initialDLBWPmappingType_0 = 0;
|
||||
#this is SS=1,L=13
|
||||
initialDLBWPstartSymbolAndLength_0 = 40;
|
||||
|
||||
initialDLBWPk0_1 = 0;
|
||||
initialDLBWPmappingType_1 = 0;
|
||||
#this is SS=2,L=12
|
||||
initialDLBWPstartSymbolAndLength_1 = 53;
|
||||
|
||||
initialDLBWPk0_2 = 0;
|
||||
initialDLBWPmappingType_2 = 0;
|
||||
#this is SS=1,L=12
|
||||
initialDLBWPstartSymbolAndLength_2 = 54;
|
||||
|
||||
initialDLBWPk0_3 = 0;
|
||||
initialDLBWPmappingType_3 = 0;
|
||||
#this is SS=1,L=4
|
||||
initialDLBWPstartSymbolAndLength_3 = 57;
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
ul_frequencyBand = 66;
|
||||
ul_absoluteFrequencyPointA = 350000;
|
||||
#scs-SpecificCarrierList
|
||||
ul_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
ul_subcarrierSpacing = 1;
|
||||
ul_carrierBandwidth = 106;
|
||||
pMax = 20;
|
||||
#initialUplinkBWP
|
||||
#genericParameters
|
||||
initialULBWPlocationAndBandwidth = 13475;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialULBWPsubcarrierSpacing = 1;
|
||||
#rach-ConfigCommon
|
||||
#rach-ConfigGeneric
|
||||
prach_ConfigurationIndex = 98;
|
||||
#prach_msg1_FDM
|
||||
#0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM = 0;
|
||||
prach_msg1_FrequencyStart = 0;
|
||||
zeroCorrelationZoneConfig = 13;
|
||||
preambleReceivedTargetPower = -118;
|
||||
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
|
||||
preambleTransMax = 6;
|
||||
#powerRampingStep
|
||||
# 0=dB0,1=dB2,2=dB4,3=dB6
|
||||
powerRampingStep = 1;
|
||||
#ra_ReponseWindow
|
||||
#1,2,4,8,10,20,40,80
|
||||
ra_ResponseWindow = 4;
|
||||
#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 = 4;
|
||||
#oneHalf (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 = 1,
|
||||
|
||||
# restrictedSetConfig
|
||||
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||
restrictedSetConfig = 0,
|
||||
# pusch-ConfigCommon (up to 16 elements)
|
||||
initialULBWPk2_0 = 6;
|
||||
initialULBWPmappingType_0 = 1
|
||||
# this is SS=0 L=11
|
||||
initialULBWPstartSymbolAndLength_0 = 55;
|
||||
|
||||
initialULBWPk2_1 = 6;
|
||||
initialULBWPmappingType_1 = 1;
|
||||
# this is SS=0 L=12
|
||||
initialULBWPstartSymbolAndLength_1 = 69;
|
||||
|
||||
initialULBWPk2_2 = 7;
|
||||
initialULBWPmappingType_2 = 1;
|
||||
# this is SS=10 L=4
|
||||
initialULBWPstartSymbolAndLength_2 = 52;
|
||||
msg3_DeltaPreamble = 1;
|
||||
p0_NominalWithGrant =-90;
|
||||
|
||||
# pucch-ConfigCommon setup :
|
||||
# pucchGroupHopping
|
||||
# 0 = neither, 1= group hopping, 2=sequence hopping
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
ssb_periodicityServingCell = 2;
|
||||
|
||||
# dmrs_TypeA_position
|
||||
# 0 = pos2, 1 = pos3
|
||||
dmrs_TypeA_Position = 0;
|
||||
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
subcarrierSpacing = 1;
|
||||
|
||||
|
||||
#tdd-UL-DL-ConfigurationCommon
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
referenceSubcarrierSpacing = 1;
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity = 6;
|
||||
nrofDownlinkSlots = 7;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
ssPBCH_BlockPower = 10;
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
|
||||
|
||||
////////// MME parameters:
|
||||
mme_ip_address = ( { ipv4 = "192.168.12.26";
|
||||
ipv6 = "192:168:30::17";
|
||||
active = "yes";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
|
||||
GNB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
||||
GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24";
|
||||
GNB_INTERFACE_NAME_FOR_S1U = "eth0";
|
||||
GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
MACRLCs = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
}
|
||||
);
|
||||
|
||||
L1s = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
pusch_proc_threads = 8;
|
||||
}
|
||||
);
|
||||
|
||||
RUs = (
|
||||
{
|
||||
local_rf = "yes"
|
||||
nb_tx = 1;
|
||||
nb_rx = 1;
|
||||
att_tx = 0;
|
||||
att_rx = 0;
|
||||
bands = [7];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 75;
|
||||
eNB_instances = [0];
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
##beamforming 1x4 matrix: 1 layer x 4 antennas
|
||||
#bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
|
||||
## beamforming 2x2 matrix:
|
||||
# bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
|
||||
## beamforming 4x4 matrix:
|
||||
#bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
|
||||
|
||||
sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2";
|
||||
clock_src = "external";
|
||||
# if_freq = 3700000000L;
|
||||
# if_offset = 1000000;
|
||||
}
|
||||
);
|
||||
|
||||
THREAD_STRUCT = (
|
||||
{
|
||||
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
|
||||
parallel_config = "PARALLEL_RU_L1_TRX_SPLIT";
|
||||
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
|
||||
worker_config = "WORKER_ENABLE";
|
||||
}
|
||||
);
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level ="info";
|
||||
global_log_verbosity ="medium";
|
||||
hw_log_level ="info";
|
||||
hw_log_verbosity ="medium";
|
||||
phy_log_level ="info";
|
||||
phy_log_verbosity ="medium";
|
||||
mac_log_level ="info";
|
||||
mac_log_verbosity ="high";
|
||||
rlc_log_level ="info";
|
||||
rlc_log_verbosity ="medium";
|
||||
pdcp_log_level ="info";
|
||||
pdcp_log_verbosity ="medium";
|
||||
rrc_log_level ="info";
|
||||
rrc_log_verbosity ="medium";
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@ gNBs =
|
||||
|
||||
ssb_SubcarrierOffset = 0;
|
||||
pdsch_AntennaPorts = 1;
|
||||
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
#spCellConfigCommon
|
||||
@@ -227,14 +227,15 @@ MACRLCs = (
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
L1s = (
|
||||
{
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
}
|
||||
pusch_proc_threads = 8;
|
||||
}
|
||||
);
|
||||
|
||||
RUs = (
|
||||
@@ -248,8 +249,15 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 75;
|
||||
eNB_instances = [0];
|
||||
#beamforming 1x4 matrix:
|
||||
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
##beamforming 1x4 matrix: 1 layer x 4 antennas
|
||||
#bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
|
||||
## beamforming 2x2 matrix:
|
||||
# bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
|
||||
## beamforming 4x4 matrix:
|
||||
#bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
|
||||
|
||||
sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2";
|
||||
clock_src = "external";
|
||||
}
|
||||
|
||||
@@ -172,6 +172,7 @@ function setvar_usage {
|
||||
function variant__v1__enb_usrp {
|
||||
NB_PATTERN_FILES=9
|
||||
BUILD_OPTIONS="--eNB -w USRP --mu"
|
||||
VM_MEMORY=3072
|
||||
}
|
||||
|
||||
function variant__v2__basic_sim {
|
||||
|
||||
@@ -749,7 +749,7 @@ function report_test {
|
||||
echo " </tr>" >> ./test_simulator_results.html
|
||||
|
||||
EPC_CONFIGS=("noS1")
|
||||
TRANS_MODES=("tdd")
|
||||
TRANS_MODES=("fdd" "tdd")
|
||||
BW_CASES=(106)
|
||||
for CN_CONFIG in ${EPC_CONFIGS[@]}
|
||||
do
|
||||
|
||||
+57
-33
@@ -379,7 +379,7 @@ function check_iperf {
|
||||
local LOC_IS_DL=`echo $LOC_BASE_LOG | grep -c _dl`
|
||||
local LOC_IS_BASIC_SIM=`echo $LOC_BASE_LOG | grep -c basic_sim`
|
||||
local LOC_IS_RF_SIM=`echo $LOC_BASE_LOG | grep -c rf_sim`
|
||||
local LOC_IS_NR=`echo $LOC_BASE_LOG | grep -c tdd_106prb`
|
||||
local LOC_IS_NR=`echo $LOC_BASE_LOG | grep -c _106prb`
|
||||
if [ -f ${LOC_BASE_LOG}_client.txt ]
|
||||
then
|
||||
local FILE_COMPLETE=`egrep -c "Server Report" ${LOC_BASE_LOG}_client.txt`
|
||||
@@ -2189,39 +2189,50 @@ function run_test_on_vm {
|
||||
|
||||
if [[ "$RUN_OPTIONS" == "complex" ]] && [[ $VM_NAME =~ .*-rf-sim.* ]]
|
||||
then
|
||||
CN_CONFIG="noS1"
|
||||
CONF_FILE=gnb.band78.tm1.106PRB.usrpn300.conf
|
||||
S1_NOS1_CFG=0
|
||||
PRB=106
|
||||
FREQUENCY=3510
|
||||
|
||||
if [ ! -d $ARCHIVES_LOC ]
|
||||
then
|
||||
mkdir --parents $ARCHIVES_LOC
|
||||
fi
|
||||
|
||||
local try_cnt=0
|
||||
NR_STATUS=0
|
||||
CN_CONFIG="noS1"
|
||||
S1_NOS1_CFG=0
|
||||
|
||||
######### start of RA TEST loop
|
||||
while [ $try_cnt -lt 5 ] #5 because it hardly succeed within CI
|
||||
# for the moment only TDD
|
||||
TRANS_MODES=("tdd")
|
||||
for TMODE in ${TRANS_MODES[@]}
|
||||
do
|
||||
if [[ $TMODE =~ .*fdd.* ]]
|
||||
then
|
||||
CONF_FILE=gnb.band66.tm1.106PRB.usrpn300.conf
|
||||
PRB=106
|
||||
FREQUENCY=37000
|
||||
else
|
||||
CONF_FILE=gnb.band78.tm1.106PRB.usrpn300.conf
|
||||
PRB=106
|
||||
FREQUENCY=3510
|
||||
fi
|
||||
|
||||
local try_cnt=0
|
||||
NR_STATUS=0
|
||||
while [ $try_cnt -lt 5 ] #5 because it hardly succeed within CI
|
||||
|
||||
do
|
||||
SYNC_STATUS=0
|
||||
RA_STATUS=0
|
||||
rm -f $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}*ra_test.log
|
||||
rm -f $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}*ra_test.log
|
||||
|
||||
echo "############################################################"
|
||||
echo "${CN_CONFIG} : Starting the gNB"
|
||||
echo "${CN_CONFIG} : Starting the gNB in ${TMODE} mode (RA TEST)"
|
||||
echo "############################################################"
|
||||
CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb_ra_test.log
|
||||
CURRENT_GNB_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_gnb_ra_test.log
|
||||
#last argument = 1 is to enable --do-ra for RA test
|
||||
start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG 1
|
||||
|
||||
echo "############################################################"
|
||||
echo "${CN_CONFIG} : Starting the NR-UE"
|
||||
echo "${CN_CONFIG} : Starting the NR-UE in ${TMODE} mode (RA TEST)"
|
||||
echo "############################################################"
|
||||
CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue_ra_test.log
|
||||
CURRENT_NR_UE_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_ue_ra_test.log
|
||||
#last argument = 1 is to enable --do-ra for RA test
|
||||
start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG 1
|
||||
if [ $NR_UE_SYNC -eq 0 ]
|
||||
@@ -2260,35 +2271,47 @@ function run_test_on_vm {
|
||||
else
|
||||
try_cnt=$((try_cnt+10))
|
||||
fi
|
||||
done
|
||||
done
|
||||
########### end RA test
|
||||
|
||||
sleep 30
|
||||
|
||||
|
||||
######### start of PHY TEST loop
|
||||
try_cnt=0
|
||||
while [ $try_cnt -lt 4 ]
|
||||
SYNC_STATUS=0
|
||||
PING_STATUS=0
|
||||
IPERF_STATUS=0
|
||||
TRANS_MODES=("fdd tdd")
|
||||
for TMODE in ${TRANS_MODES[@]}
|
||||
do
|
||||
if [[ $TMODE =~ .*fdd.* ]]
|
||||
then
|
||||
CONF_FILE=gnb.band66.tm1.106PRB.usrpn300.conf
|
||||
PRB=106
|
||||
FREQUENCY=37000
|
||||
else
|
||||
CONF_FILE=gnb.band78.tm1.106PRB.usrpn300.conf
|
||||
PRB=106
|
||||
FREQUENCY=3510
|
||||
fi
|
||||
|
||||
|
||||
SYNC_STATUS=0
|
||||
PING_STATUS=0
|
||||
IPERF_STATUS=0
|
||||
rm -f $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_gnb.log $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_ue.log
|
||||
rm -f $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log
|
||||
rm -f $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_iperf_dl*txt $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_iperf_ul*txt
|
||||
try_cnt=0
|
||||
while [ $try_cnt -lt 4 ]
|
||||
do
|
||||
rm -f $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_gnb.log $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_ue.log
|
||||
rm -f $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log
|
||||
rm -f $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_iperf_dl*txt $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_iperf_ul*txt
|
||||
|
||||
echo "############################################################"
|
||||
echo "${CN_CONFIG} : Starting the gNB"
|
||||
echo "${CN_CONFIG} : Starting the gNB in ${TMODE} mode (PHY TEST)"
|
||||
echo "############################################################"
|
||||
CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb.log
|
||||
CURRENT_GNB_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_gnb.log
|
||||
start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG 0
|
||||
|
||||
echo "############################################################"
|
||||
echo "${CN_CONFIG} : Starting the NR-UE"
|
||||
echo "${CN_CONFIG} : Starting the NR-UE in ${TMODE} mode (PHY TEST)"
|
||||
echo "############################################################"
|
||||
CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue.log
|
||||
CURRENT_NR_UE_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_ue.log
|
||||
start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG 0
|
||||
if [ $NR_UE_SYNC -eq 0 ]
|
||||
then
|
||||
@@ -2306,7 +2329,7 @@ function run_test_on_vm {
|
||||
echo "${CN_CONFIG} : Pinging the gNB from NR-UE"
|
||||
echo "############################################################"
|
||||
get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR
|
||||
PING_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log
|
||||
PING_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log
|
||||
ping_epc_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $ENB_IP_ADDR $PING_LOG_FILE 1 0
|
||||
scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/$PING_LOG_FILE $ARCHIVES_LOC
|
||||
check_ping_result $ARCHIVES_LOC/$PING_LOG_FILE 20
|
||||
@@ -2315,7 +2338,7 @@ function run_test_on_vm {
|
||||
echo "${CN_CONFIG} : Pinging the NR-UE from gNB"
|
||||
echo "############################################################"
|
||||
get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1
|
||||
PING_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log
|
||||
PING_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log
|
||||
ping_enb_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR $UE_IP_ADDR $PING_LOG_FILE 0
|
||||
scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/$PING_LOG_FILE $ARCHIVES_LOC
|
||||
check_ping_result $ARCHIVES_LOC/$PING_LOG_FILE 20
|
||||
@@ -2324,7 +2347,7 @@ function run_test_on_vm {
|
||||
echo "${CN_CONFIG} : iperf DL -- NR-UE is server and gNB is client"
|
||||
echo "############################################################"
|
||||
THROUGHPUT="30K"
|
||||
CURR_IPERF_LOG_BASE=tdd_${PRB}prb_${CN_CONFIG}_iperf_dl
|
||||
CURR_IPERF_LOG_BASE=${TMODE}_${PRB}prb_${CN_CONFIG}_iperf_dl
|
||||
get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR
|
||||
get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1
|
||||
generic_iperf $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $UE_IP_ADDR $GNB_VM_CMDS $GNB_VM_IP_ADDR $ENB_IP_ADDR $THROUGHPUT $CURR_IPERF_LOG_BASE 1 0
|
||||
@@ -2346,7 +2369,7 @@ function run_test_on_vm {
|
||||
echo "${CN_CONFIG} : iperf UL -- gNB is server and NR-UE is client"
|
||||
echo "############################################################"
|
||||
THROUGHPUT="30K"
|
||||
CURR_IPERF_LOG_BASE=tdd_${PRB}prb_${CN_CONFIG}_iperf_ul
|
||||
CURR_IPERF_LOG_BASE=${TMODE}_${PRB}prb_${CN_CONFIG}_iperf_ul
|
||||
get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR
|
||||
get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1
|
||||
generic_iperf $GNB_VM_CMDS $GNB_VM_IP_ADDR $ENB_IP_ADDR $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $UE_IP_ADDR $THROUGHPUT $CURR_IPERF_LOG_BASE 1 0
|
||||
@@ -2368,6 +2391,7 @@ function run_test_on_vm {
|
||||
else
|
||||
try_cnt=$((try_cnt+10))
|
||||
fi
|
||||
done
|
||||
done
|
||||
######### end of loop
|
||||
full_l2_sim_destroy
|
||||
|
||||
@@ -1967,7 +1967,8 @@ set(NR_PDCP_SRC
|
||||
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
|
||||
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c
|
||||
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity.c
|
||||
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c
|
||||
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_sdu.c
|
||||
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c
|
||||
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c
|
||||
${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c
|
||||
)
|
||||
@@ -3141,7 +3142,7 @@ target_link_libraries (nr-uesoftmodem
|
||||
RRC_LIB NR_RRC_LIB NGAP_LIB NGAP_GNB SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB
|
||||
PHY_COMMON PHY_NR_COMMON PHY_UE PHY_NR_UE PHY_RU LFDS NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB
|
||||
NFAPI_USER_LIB MISC_NFAPI_NR_LIB S1AP_LIB S1AP_ENB
|
||||
${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES}
|
||||
${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES}
|
||||
NFAPI_USER_LIB S1AP_LIB S1AP_ENB
|
||||
${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} LIB_5GNAS_GNB
|
||||
-Wl,--end-group z dl)
|
||||
|
||||
@@ -273,6 +273,10 @@ install_protobuf_from_source(){
|
||||
make -j`nproc`
|
||||
$SUDO make install
|
||||
$SUDO ldconfig
|
||||
if [[ -v CI_ENV ]]; then
|
||||
cd /tmp
|
||||
$SUDO rm -rf protobuf*
|
||||
fi
|
||||
) >& $protobuf_install_log
|
||||
}
|
||||
|
||||
@@ -295,6 +299,10 @@ install_protobuf_c_from_source(){
|
||||
make -j`nproc`
|
||||
$SUDO make install
|
||||
$SUDO ldconfig
|
||||
if [[ -v CI_ENV ]]; then
|
||||
cd /tmp
|
||||
$SUDO rm -rf protobuf*
|
||||
fi
|
||||
) >& $protobuf_c_install_log
|
||||
}
|
||||
|
||||
@@ -831,6 +839,9 @@ install_asn1c_from_source(){
|
||||
$SUDO make install
|
||||
cd -
|
||||
$SUDO ldconfig
|
||||
if [[ -v CI_ENV ]]; then
|
||||
$SUDO rm -rf /tmp/asn1c
|
||||
fi
|
||||
) > $asn1_install_log 2>&1
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,8 @@ int write_file_matlab(const char *fname,
|
||||
void *data,
|
||||
int length,
|
||||
int dec,
|
||||
unsigned int format)
|
||||
unsigned int format,
|
||||
int multiVec)
|
||||
{
|
||||
FILE *fp=NULL;
|
||||
int i;
|
||||
@@ -100,8 +101,7 @@ int write_file_matlab(const char *fname,
|
||||
|
||||
//printf("Writing %d elements of type %d to %s\n",length,format,fname);
|
||||
|
||||
|
||||
if (format == 10 || format ==11 || format == 12 || format == 13 || format == 14) {
|
||||
if (format == 10 || format ==11 || format == 12 || format == 13 || format == 14 || multiVec) {
|
||||
fp = fopen(fname,"a+");
|
||||
} else if (format != 10 && format !=11 && format != 12 && format != 13 && format != 14) {
|
||||
fp = fopen(fname,"w+");
|
||||
@@ -137,8 +137,7 @@ int write_file_matlab(const char *fname,
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
if (format != 10 && format !=11 && format != 12 && format != 13 && format != 14)
|
||||
if ((format != 10 && format !=11 && format != 12 && format != 13 && format != 14) || multiVec)
|
||||
fprintf(fp,"%s = [",vname);
|
||||
|
||||
switch (format) {
|
||||
@@ -247,7 +246,7 @@ int write_file_matlab(const char *fname,
|
||||
AssertFatal(false, "unknown dump format: %d\n", format);
|
||||
}
|
||||
|
||||
if (format != 10 && format !=11 && format !=12 && format != 13 && format != 15) {
|
||||
if ((format != 10 && format !=11 && format !=12 && format != 13 && format != 15) || multiVec) {
|
||||
fprintf(fp,"];\n");
|
||||
fclose(fp);
|
||||
return(0);
|
||||
|
||||
@@ -335,6 +335,7 @@ typedef struct {
|
||||
@param length length of data vector to output
|
||||
@param dec decimation level
|
||||
@param format data format (0 = real 16-bit, 1 = complex 16-bit,2 real 32-bit, 3 complex 32-bit,4 = real 8-bit, 5 = complex 8-bit)
|
||||
@param multiVec create new file or append to existing (useful for writing multiple vectors to same file. Just call the function multiple times with same file name and with this parameter set to 1)
|
||||
*/
|
||||
#define MATLAB_RAW (1<<31)
|
||||
#define MATLAB_SHORT 0
|
||||
@@ -354,7 +355,7 @@ typedef struct {
|
||||
#define MATLAB_CSHORT_BRACKET2 14
|
||||
#define MATLAB_CSHORT_BRACKET3 15
|
||||
|
||||
int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, unsigned int format);
|
||||
int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, unsigned int format, int multiVec);
|
||||
|
||||
/*----------------macro definitions for reading log configuration from the config module */
|
||||
#define CONFIG_STRING_LOG_PREFIX "log_config"
|
||||
@@ -414,7 +415,7 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int
|
||||
|
||||
/* bitmask dependent macros, to generate debug file such as matlab file or message dump */
|
||||
# define LOG_DUMPFLAG(D) (g_log->dump_mask & D)
|
||||
# define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0)/* */
|
||||
# define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format, 0);} while(0)/* */
|
||||
/* define variable only used in LOG macro's */
|
||||
# define LOG_VAR(A,B) A B
|
||||
# else /* T_TRACER: remove all debugging and tracing messages, except errors */
|
||||
@@ -431,7 +432,7 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int
|
||||
# define LOG_DUMPFLAG(D) (g_log->debug_mask & D)
|
||||
# define LOG_DUMPMSG(c, f, b, s, x...) do { if(g_log->dump_mask & f) log_dump(c, b, s, LOG_DUMP_CHAR, x) ;} while (0) /* */
|
||||
|
||||
# define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0)
|
||||
# define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format, 0);} while(0)
|
||||
# define LOG_VAR(A,B) A B
|
||||
# endif /* T_TRACER */
|
||||
/* avoid warnings for variables only used in LOG macro's but set outside debug section */
|
||||
@@ -439,9 +440,10 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int
|
||||
#define LOG_USEDINLOG_VAR(A,B) GCC_NOTUSED A B
|
||||
|
||||
/* unfiltered macros, useful for simulators or messages at init time, before log is configured */
|
||||
#define LOG_UM(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0)
|
||||
#define LOG_UM(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format, 0);} while(0)
|
||||
#define LOG_UI(c, x...) do {logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_INFO, x) ; } while(0)
|
||||
#define LOG_UDUMPMSG(c, b, s, f, x...) do { log_dump(c, b, s, f, x) ;} while (0) /* */
|
||||
# define LOG_MM(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format, 1);} while(0)
|
||||
/* @}*/
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ T_IDs.h
|
||||
T_messages.txt.h
|
||||
genids
|
||||
tracer/enb
|
||||
tracer/gnb
|
||||
tracer/extract_config
|
||||
tracer/record
|
||||
tracer/replay
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
ID = BENETEL
|
||||
GROUP = ALL
|
||||
FORMAT = int,frame : int,slot : buffer,rxdataF
|
||||
|
||||
#general logs
|
||||
ID = ENB_MASTER_TICK
|
||||
DESC = eNodeB master tick - one tick per ms, to be used as "reference clock", mostly for ticktime view
|
||||
@@ -93,6 +89,10 @@ ID = GNB_PHY_MIB
|
||||
DESC = NR MIB data
|
||||
GROUP = ALL:PHY:GNB:WIRESHARK
|
||||
FORMAT = int,gNB_ID : int,frame : int,slot : buffer,data
|
||||
ID = GNB_PHY_PUCCH_PUSCH_IQ
|
||||
DESC = gNodeB input data in the frequency domain for a slot where some PUCCH or PUSCH detection was done
|
||||
GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB
|
||||
FORMAT = int,frame : int,slot : buffer,rxdataF
|
||||
|
||||
#MAC logs
|
||||
ID = ENB_MAC_UE_DL_SDU
|
||||
|
||||
@@ -7,7 +7,8 @@ LIBS=-lm
|
||||
XLIBS=-lX11 -lpng -lXft
|
||||
|
||||
all: record replay extract_config textlog enb ue vcd macpdu2wireshark \
|
||||
extract_input_subframe extract_output_subframe to_vcd extract multi
|
||||
extract_input_subframe extract_output_subframe to_vcd extract multi \
|
||||
gnb
|
||||
|
||||
record: utils.o record.o database.o config.o
|
||||
$(CC) $(CFLAGS) -o record $^ $(LIBS)
|
||||
@@ -60,6 +61,11 @@ macpdu2wireshark: macpdu2wireshark.o database.o utils.o handler.o event.o \
|
||||
multi: multi.o utils.o database.o config.o
|
||||
$(CC) $(CFLAGS) -o multi $^ $(LIBS)
|
||||
|
||||
gnb: utils.o gnb.o database.o event.o handler.o config.o \
|
||||
view/view.a gui/gui.a logger/logger.a \
|
||||
filter/filter.a
|
||||
$(CC) $(CFLAGS) -o gnb $^ $(LIBS) $(XLIBS)
|
||||
|
||||
multi.o: ../T_IDs.h
|
||||
|
||||
../T_IDs.h:
|
||||
@@ -85,7 +91,7 @@ filter/filter.a:
|
||||
clean:
|
||||
rm -f *.o core tracer_remote textlog enb ue vcd record replay
|
||||
rm -f extract_config macpdu2wireshark extract_input_subframe
|
||||
rm -f extract_output_subframe to_vcd extract multi
|
||||
rm -f extract_output_subframe to_vcd extract multi gnb
|
||||
cd gui && $(MAKE) clean
|
||||
cd view && $(MAKE) clean
|
||||
cd logger && $(MAKE) clean
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include "database.h"
|
||||
#include "handler.h"
|
||||
#include "config.h"
|
||||
#include "logger/logger.h"
|
||||
#include "view/view.h"
|
||||
#include "gui/gui.h"
|
||||
|
||||
typedef struct {
|
||||
widget *pucch_pusch_iq_plot;
|
||||
logger *pucch_pusch_iq_logger;
|
||||
} gnb_gui;
|
||||
|
||||
typedef struct {
|
||||
int socket;
|
||||
int *is_on;
|
||||
int nevents;
|
||||
pthread_mutex_t lock;
|
||||
gnb_gui *e;
|
||||
void *database;
|
||||
} gnb_data;
|
||||
|
||||
void is_on_changed(void *_d)
|
||||
{
|
||||
gnb_data *d = _d;
|
||||
char t;
|
||||
|
||||
if (pthread_mutex_lock(&d->lock)) abort();
|
||||
|
||||
if (d->socket == -1) goto no_connection;
|
||||
|
||||
t = 1;
|
||||
if (socket_send(d->socket, &t, 1) == -1 ||
|
||||
socket_send(d->socket, &d->nevents, sizeof(int)) == -1 ||
|
||||
socket_send(d->socket, d->is_on, d->nevents * sizeof(int)) == -1)
|
||||
goto connection_dies;
|
||||
|
||||
no_connection:
|
||||
if (pthread_mutex_unlock(&d->lock)) abort();
|
||||
return;
|
||||
|
||||
connection_dies:
|
||||
close(d->socket);
|
||||
d->socket = -1;
|
||||
if (pthread_mutex_unlock(&d->lock)) abort();
|
||||
}
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
printf(
|
||||
"options:\n"
|
||||
" -d <database file> this option is mandatory\n"
|
||||
" -ip <host> connect to given IP address (default %s)\n"
|
||||
" -p <port> connect to given port (default %d)\n",
|
||||
DEFAULT_REMOTE_IP,
|
||||
DEFAULT_REMOTE_PORT
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void *gui_thread(void *_g)
|
||||
{
|
||||
gui *g = _g;
|
||||
gui_loop(g);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void gnb_main_gui(gnb_gui *e, gui *g, event_handler *h, void *database,
|
||||
gnb_data *ed)
|
||||
{
|
||||
widget *main_window;
|
||||
widget *top_container;
|
||||
widget *line;
|
||||
widget *w;
|
||||
logger *l;
|
||||
view *v;
|
||||
|
||||
main_window = new_toplevel_window(g, 500, 300, "gNB tracer");
|
||||
|
||||
top_container = new_container(g, VERTICAL);
|
||||
widget_add_child(g, main_window, top_container, -1);
|
||||
|
||||
line = new_container(g, HORIZONTAL);
|
||||
widget_add_child(g, top_container, line, -1);
|
||||
|
||||
/* PUCCH/PUSCH IQ data */
|
||||
w = new_xy_plot(g, 55, 55, "", 50);
|
||||
e->pucch_pusch_iq_plot = w;
|
||||
widget_add_child(g, line, w, -1);
|
||||
xy_plot_set_range(g, w, -1000, 1000, -1000, 1000);
|
||||
xy_plot_set_title(g, w, "rxdataF");
|
||||
l = new_iqlog_full(h, database, "GNB_PHY_PUCCH_PUSCH_IQ", "rxdataF");
|
||||
v = new_view_xy(300*12*14,10,g,w,new_color(g,"#000"),XY_FORCED_MODE);
|
||||
logger_add_view(l, v);
|
||||
e->pucch_pusch_iq_logger = l;
|
||||
}
|
||||
|
||||
int main(int n, char **v)
|
||||
{
|
||||
char *database_filename = NULL;
|
||||
void *database;
|
||||
char *ip = DEFAULT_REMOTE_IP;
|
||||
int port = DEFAULT_REMOTE_PORT;
|
||||
int *is_on;
|
||||
int number_of_events;
|
||||
int i;
|
||||
event_handler *h;
|
||||
gnb_data gnb_data;
|
||||
gui *g;
|
||||
gnb_gui eg;
|
||||
|
||||
for (i = 1; i < n; i++) {
|
||||
if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
|
||||
if (!strcmp(v[i], "-d"))
|
||||
{ if (i > n-2) usage(); database_filename = v[++i]; continue; }
|
||||
usage();
|
||||
}
|
||||
|
||||
if (database_filename == NULL) {
|
||||
printf("ERROR: provide a database file (-d)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
database = parse_database(database_filename);
|
||||
|
||||
load_config_file(database_filename);
|
||||
|
||||
number_of_events = number_of_ids(database);
|
||||
is_on = calloc(number_of_events, sizeof(int));
|
||||
if (is_on == NULL) abort();
|
||||
|
||||
h = new_handler(database);
|
||||
|
||||
on_off(database, "GNB_PHY_PUCCH_PUSCH_IQ", is_on, 1);
|
||||
|
||||
gnb_data.database = database;
|
||||
gnb_data.socket = -1;
|
||||
gnb_data.is_on = is_on;
|
||||
gnb_data.nevents = number_of_events;
|
||||
if (pthread_mutex_init(&gnb_data.lock, NULL)) abort();
|
||||
|
||||
g = gui_init();
|
||||
new_thread(gui_thread, g);
|
||||
|
||||
gnb_main_gui(&eg, g, h, database, &gnb_data);
|
||||
|
||||
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
|
||||
|
||||
restart:
|
||||
clear_remote_config();
|
||||
if (gnb_data.socket != -1) close(gnb_data.socket);
|
||||
gnb_data.socket = connect_to(ip, port);
|
||||
|
||||
/* send the first message - activate selected traces */
|
||||
is_on_changed(&gnb_data);
|
||||
|
||||
/* read messages */
|
||||
while (1) {
|
||||
event e;
|
||||
e = get_event(gnb_data.socket, &ebuf, database);
|
||||
if (e.type == -1) goto restart;
|
||||
if (pthread_mutex_lock(&gnb_data.lock)) abort();
|
||||
handle_event(h, e);
|
||||
if (pthread_mutex_unlock(&gnb_data.lock)) abort();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -74,6 +74,44 @@ static void _event(void *p, event e)
|
||||
l->common.v[i]->append(l->common.v[i], l->i, l->q, count);
|
||||
}
|
||||
|
||||
static void _event_full(void *p, event e)
|
||||
{
|
||||
struct iqlog *l = p;
|
||||
int i;
|
||||
void *buffer;
|
||||
int bsize;
|
||||
int nsamples;
|
||||
float *idst, *qdst;
|
||||
|
||||
if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0)
|
||||
return;
|
||||
|
||||
buffer = e.e[l->buffer_arg].b;
|
||||
bsize = e.e[l->buffer_arg].bsize;
|
||||
|
||||
nsamples = bsize / 4;
|
||||
|
||||
if (nsamples > l->max_length) {
|
||||
l->i = realloc(l->i, nsamples * sizeof(float));
|
||||
if (l->i == NULL) abort();
|
||||
l->q = realloc(l->q, nsamples * sizeof(float));
|
||||
if (l->q == NULL) abort();
|
||||
l->max_length = nsamples;
|
||||
}
|
||||
|
||||
idst = l->i;
|
||||
qdst = l->q;
|
||||
for (i = 0; i < nsamples; i++) {
|
||||
*idst = ((int16_t *)buffer)[i * 2];
|
||||
*qdst = ((int16_t *)buffer)[i * 2 + 1];
|
||||
idst++;
|
||||
qdst++;
|
||||
}
|
||||
|
||||
for (i = 0; i < l->common.vsize; i++)
|
||||
l->common.v[i]->append(l->common.v[i], l->i, l->q, nsamples);
|
||||
}
|
||||
|
||||
logger *new_iqlog(event_handler *h, void *database,
|
||||
char *event_name, char *nb_rb, char *N_RB_UL, char *symbols_per_tti,
|
||||
char *buffer_varname)
|
||||
@@ -149,3 +187,43 @@ logger *new_iqlog(event_handler *h, void *database,
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
logger *new_iqlog_full(event_handler *h, void *database, char *event_name,
|
||||
char *buffer_varname)
|
||||
{
|
||||
struct iqlog *ret;
|
||||
int event_id;
|
||||
database_event_format f;
|
||||
int i;
|
||||
|
||||
ret = calloc(1, sizeof(struct iqlog)); if (ret == NULL) abort();
|
||||
|
||||
ret->common.event_name = strdup(event_name);
|
||||
if (ret->common.event_name == NULL) abort();
|
||||
ret->database = database;
|
||||
|
||||
event_id = event_id_from_name(database, event_name);
|
||||
|
||||
ret->common.handler_id = register_handler_function(h, event_id, _event_full,
|
||||
ret);
|
||||
|
||||
f = get_format(database, event_id);
|
||||
|
||||
/* look for args */
|
||||
ret->buffer_arg = -1;
|
||||
for (i = 0; i < f.count; i++) {
|
||||
if (!strcmp(f.name[i], buffer_varname)) ret->buffer_arg = i;
|
||||
}
|
||||
if (ret->buffer_arg == -1) {
|
||||
printf("%s:%d: buffer argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, buffer_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->buffer_arg], "buffer") != 0) {
|
||||
printf("%s:%d: argument '%s' has wrong type (should be 'buffer')\n",
|
||||
__FILE__, __LINE__, buffer_varname);
|
||||
abort();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ logger *new_ticklog(void *event_handler, void *database,
|
||||
logger *new_iqlog(void *event_handler, void *database,
|
||||
char *event_name, char *nb_rb, char *N_RB_UL, char *symbols_per_tti,
|
||||
char *buffer_varname);
|
||||
logger *new_iqlog_full(void *event_handler, void *database, char *event_name,
|
||||
char *buffer_varname);
|
||||
logger *new_iqdotlog(void *event_handler, void *database,
|
||||
char *event_name, char *I, char *Q);
|
||||
|
||||
|
||||
@@ -32,6 +32,81 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include "assertions.h"
|
||||
#include "nr_common.h"
|
||||
|
||||
// Table 5.2-1 NR operating bands in FR1 & FR2 (3GPP TS 38.101)
|
||||
// Table 5.4.2.3-1 Applicable NR-ARFCN per operating band in FR1 & FR2 (3GPP TS 38.101)
|
||||
// Notes:
|
||||
// - N_OFFs for bands from 80 to 89 and band 95 is referred to UL
|
||||
// - Frequencies are expressed in KHz
|
||||
// - col: NR_band ul_min ul_max dl_min dl_max step N_OFFs_DL deltaf_raster
|
||||
nr_bandentry_t nr_bandtable[] = {
|
||||
{1, 1920000, 1980000, 2110000, 2170000, 20, 422000, 100},
|
||||
{2, 1850000, 1910000, 1930000, 1990000, 20, 386000, 100},
|
||||
{3, 1710000, 1785000, 1805000, 1880000, 20, 361000, 100},
|
||||
{5, 824000, 849000, 869000, 894000, 20, 173800, 100},
|
||||
{7, 2500000, 2570000, 2620000, 2690000, 20, 524000, 100},
|
||||
{8, 880000, 915000, 925000, 960000, 20, 185000, 100},
|
||||
{12, 698000, 716000, 729000, 746000, 20, 145800, 100},
|
||||
{14, 788000, 798000, 758000, 768000, 20, 151600, 100},
|
||||
{18, 815000, 830000, 860000, 875000, 20, 172000, 100},
|
||||
{20, 832000, 862000, 791000, 821000, 20, 158200, 100},
|
||||
{25, 1850000, 1915000, 1930000, 1995000, 20, 386000, 100},
|
||||
{26, 814000, 849000, 859000, 894000, 20, 171800, 100},
|
||||
{28, 703000, 758000, 758000, 813000, 20, 151600, 100},
|
||||
{29, 000, 000, 717000, 728000, 20, 143400, 100},
|
||||
{30, 2305000, 2315000, 2350000, 2360000, 20, 470000, 100},
|
||||
{34, 2010000, 2025000, 2010000, 2025000, 20, 402000, 100},
|
||||
{38, 2570000, 2620000, 2570000, 2630000, 20, 514000, 100},
|
||||
{39, 1880000, 1920000, 1880000, 1920000, 20, 376000, 100},
|
||||
{40, 2300000, 2400000, 2300000, 2400000, 20, 460000, 100},
|
||||
{41, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15},
|
||||
{41, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30},
|
||||
{47, 5855000, 5925000, 5855000, 5925000, 1, 790334, 15},
|
||||
//{48, 3550000, 3700000, 3550000, 3700000, 1, 636667, 15},
|
||||
//{48, 3550000, 3700000, 3550000, 3700000, 2, 636668, 30},
|
||||
{50, 1432000, 1517000, 1432000, 1517000, 20, 286400, 100},
|
||||
{51, 1427000, 1432000, 1427000, 1432000, 20, 285400, 100},
|
||||
{53, 2483500, 2495000, 2483500, 2495000, 20, 496700, 100},
|
||||
{65, 1920000, 2010000, 2110000, 2200000, 20, 422000, 100},
|
||||
{66, 1710000, 1780000, 2110000, 2200000, 20, 422000, 100},
|
||||
{70, 1695000, 1710000, 1995000, 2020000, 20, 399000, 100},
|
||||
{71, 663000, 698000, 617000, 652000, 20, 123400, 100},
|
||||
{74, 1427000, 1470000, 1475000, 1518000, 20, 295000, 100},
|
||||
{75, 000, 000, 1432000, 1517000, 20, 286400, 100},
|
||||
{76, 000, 000, 1427000, 1432000, 20, 285400, 100},
|
||||
{77, 3300000, 4200000, 3300000, 4200000, 1, 620000, 15},
|
||||
{77, 3300000, 4200000, 3300000, 4200000, 2, 620000, 30},
|
||||
{78, 3300000, 3800000, 3300000, 3800000, 1, 620000, 15},
|
||||
{78, 3300000, 3800000, 3300000, 3800000, 2, 620000, 30},
|
||||
{79, 4400010, 5000000, 4400010, 5000000, 1, 693334, 15},
|
||||
{79, 4400010, 5000000, 4400010, 5000000, 2, 693334, 30},
|
||||
{80, 1710000, 1785000, 000, 000, 20, 342000, 100},
|
||||
{81, 880000, 915000, 000, 000, 20, 176000, 100},
|
||||
{82, 832000, 862000, 000, 000, 20, 166400, 100},
|
||||
{83, 703000, 748000, 000, 000, 20, 140600, 100},
|
||||
{84, 1920000, 1980000, 000, 000, 20, 384000, 100},
|
||||
{86, 1710000, 1785000, 000, 000, 20, 342000, 100},
|
||||
{89, 824000, 849000, 000, 000, 20, 342000, 100},
|
||||
{90, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15},
|
||||
{90, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30},
|
||||
{90, 2496000, 2690000, 2496000, 2690000, 20, 499200, 100},
|
||||
{91, 832000, 862000, 1427000, 1432000, 20, 285400, 100},
|
||||
{92, 832000, 862000, 1432000, 1517000, 20, 286400, 100},
|
||||
{93, 880000, 915000, 1427000, 1432000, 20, 285400, 100},
|
||||
{94, 880000, 915000, 1432000, 1517000, 20, 286400, 100},
|
||||
{95, 2010000, 2025000, 000, 000, 20, 402000, 100},
|
||||
{257,26500020,29500000,26500020,29500000, 1,2054166, 60},
|
||||
{257,26500080,29500000,26500080,29500000, 2,2054167, 120},
|
||||
{258,24250080,27500000,24250080,27500000, 1,2016667, 60},
|
||||
{258,24250080,27500000,24250080,27500000, 2,2016667, 120},
|
||||
{260,37000020,40000000,37000020,40000000, 1,2229166, 60},
|
||||
{260,37000080,40000000,37000080,40000000, 2,2229167, 120},
|
||||
{261,27500040,28350000,27500040,28350000, 1,2070833, 60},
|
||||
{261,27500040,28350000,27500040,28350000, 2,2070833, 120}
|
||||
};
|
||||
|
||||
const size_t nr_bandtable_size = sizeof(nr_bandtable) / sizeof(nr_bandentry_t);
|
||||
|
||||
int NRRIV2BW(int locationAndBandwidth,int N_RB) {
|
||||
int tmp = locationAndBandwidth/N_RB;
|
||||
|
||||
@@ -36,6 +36,20 @@
|
||||
#include <stdint.h>
|
||||
#include "assertions.h"
|
||||
|
||||
typedef struct nr_bandentry_s {
|
||||
int16_t band;
|
||||
uint64_t ul_min;
|
||||
uint64_t ul_max;
|
||||
uint64_t dl_min;
|
||||
uint64_t dl_max;
|
||||
uint64_t step_size;
|
||||
uint64_t N_OFFs_DL;
|
||||
uint8_t deltaf_raster;
|
||||
} nr_bandentry_t;
|
||||
|
||||
extern const size_t nr_bandtable_size;
|
||||
extern nr_bandentry_t nr_bandtable[];
|
||||
|
||||
int NRRIV2BW(int locationAndBandwidth,int N_RB);
|
||||
int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB);
|
||||
int PRBalloc_to_locationandbandwidth0(int NPRB,int RBstart,int BWPsize);
|
||||
|
||||
+10
-7
@@ -132,9 +132,9 @@ With the RF simulator (on the same machine):
|
||||
|
||||
`sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --do-ra --rfsim --parallel-config PARALLEL_SINGLE_THREAD`
|
||||
|
||||
## sa setup with OAI
|
||||
## SA setup with OAI
|
||||
|
||||
The sa flag is used to run gNB in standalone mode. Currently OAI in NR standalone mode transmits and receives SIB1.
|
||||
The sa flag is used to run gNB in standalone mode. Currently OAI in NR standalone mode transmits and receives SIB1 and triggers the RA procedure for initial access.
|
||||
|
||||
In order to run gNB in standalone mode, the following flag is needed at gNB:
|
||||
|
||||
@@ -147,8 +147,9 @@ At the gNB the --sa flag does the following
|
||||
- it encodes the RRCConfiguration and the RBconfig message and stores them in the binary files rbconfig.raw and reconfig.raw
|
||||
- the RRC encodes SIB1 according the configuration file and transmits it through PDSCH
|
||||
|
||||
At the UE the --sa flag will
|
||||
- read the binary files rbconfig.raw and reconfig.raw from the current directory (a different directory can be specified with the flag --rrc_config_path) and process them.
|
||||
At the UE the --sa flag will:
|
||||
- Read the binary files rbconfig.raw and reconfig.raw from the current directory (a different directory can be specified with the flag --rrc_config_path) and process them
|
||||
- After the successful decoding of a SIB1 at RRC, the UE will start the 5G NR Initial Access Procedure by triggering the RA procedure.
|
||||
|
||||
From the `cmake_targets/ran_build/build` folder:
|
||||
|
||||
@@ -168,7 +169,7 @@ With the RF simulator (on the same machine):
|
||||
|
||||
## IF setup with OAI
|
||||
|
||||
The -C and -CO flags can be used together at UE side to set custom downlink and uplink FR1 intermediate frequencies for the IF equipment.
|
||||
The -C and --CO flags can be used together at UE side to set custom downlink and uplink FR1 arbitrary frequencies for the IF equipment.
|
||||
|
||||
In order to run this setup, the following flags are needed at the UE side:
|
||||
|
||||
@@ -182,9 +183,11 @@ and the following parameters must be configured in the RUs section of the gNB co
|
||||
|
||||
`if_offset`
|
||||
|
||||
### Run OAI with custom DL/UL intermediate frequencies
|
||||
The values must be given in Hz.
|
||||
|
||||
The following example uses DL frequency 2169.080 MHz and UL frequency offset -400 MHz, with a configuration file for band 66 at gNB side.
|
||||
### Run OAI with custom DL/UL arbitrary frequencies
|
||||
|
||||
The following example uses DL frequency 2169.080 MHz and UL frequency offset -400 MHz, with a configuration file for band 66 (FDD) at gNB side.
|
||||
|
||||
From the `cmake_targets/ran_build/build` folder:
|
||||
|
||||
|
||||
+68
-633
@@ -81,10 +81,11 @@
|
||||
|
||||
#include "s1ap_eNB.h"
|
||||
#include "SIMULATION/ETH_TRANSPORT/proto.h"
|
||||
|
||||
#include <executables/softmodem-common.h>
|
||||
|
||||
#include "T.h"
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
#include <nfapi/oai_integration/nfapi_pnf.h>
|
||||
//#define DEBUG_THREADS 1
|
||||
|
||||
//#define USRP_DEBUG 1
|
||||
@@ -92,17 +93,6 @@
|
||||
// extern openair0_device openair0;
|
||||
|
||||
|
||||
extern volatile int start_gNB;
|
||||
extern volatile int start_UE;
|
||||
extern volatile int oai_exit;
|
||||
|
||||
extern openair0_config_t openair0_cfg[MAX_CARDS];
|
||||
|
||||
extern int transmission_mode;
|
||||
|
||||
extern uint16_t sf_ahead;
|
||||
extern uint16_t sl_ahead;
|
||||
|
||||
//pthread_t main_gNB_thread;
|
||||
|
||||
time_stats_t softmodem_stats_mt; // main thread
|
||||
@@ -111,40 +101,43 @@ time_stats_t softmodem_stats_rxtx_sf; // total tx time
|
||||
time_stats_t nfapi_meas; // total tx time
|
||||
time_stats_t softmodem_stats_rx_sf; // total rx time
|
||||
|
||||
/* mutex, cond and variable to serialize phy proc TX calls
|
||||
* (this mechanism may be relaxed in the future for better
|
||||
* performances)
|
||||
*/
|
||||
static struct {
|
||||
pthread_mutex_t mutex_phy_proc_tx;
|
||||
pthread_cond_t cond_phy_proc_tx;
|
||||
volatile uint8_t phy_proc_CC_id;
|
||||
} sync_phy_proc;
|
||||
|
||||
extern double cpuf;
|
||||
|
||||
void init_gNB(int,int);
|
||||
void stop_gNB(int nb_inst);
|
||||
|
||||
int wakeup_txfh(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc, int frame_tx, int slot_tx, uint64_t timestamp_tx);
|
||||
int wakeup_tx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_tx, int slot_tx, uint64_t timestamp_tx);
|
||||
#include "executables/thread-common.h"
|
||||
//extern PARALLEL_CONF_t get_thread_parallel_conf(void);
|
||||
//extern WORKER_CONF_t get_thread_worker_conf(void);
|
||||
|
||||
|
||||
void wakeup_prach_gNB(PHY_VARS_gNB *gNB, RU_t *ru, int frame, int subframe);
|
||||
|
||||
extern uint8_t nfapi_mode;
|
||||
extern void oai_subframe_ind(uint16_t sfn, uint16_t sf);
|
||||
extern void oai_slot_ind(uint16_t sfn, uint16_t slot);
|
||||
extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset);
|
||||
|
||||
//#define TICK_TO_US(ts) (ts.diff)
|
||||
#define TICK_TO_US(ts) (ts.trials==0?0:ts.diff/ts.trials)
|
||||
|
||||
static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_tx, int slot_tx, char *thread_name) {
|
||||
|
||||
void tx_func(void *param) {
|
||||
|
||||
processingData_L1_t *info = (processingData_L1_t *) param;
|
||||
PHY_VARS_gNB *gNB = info->gNB;
|
||||
int frame_tx = info->frame_tx;
|
||||
int slot_tx = info->slot_tx;
|
||||
|
||||
phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1);
|
||||
|
||||
// start FH TX processing
|
||||
notifiedFIFO_elt_t *res;
|
||||
res = pullTpool(gNB->resp_RU_tx, gNB->threadPool);
|
||||
processingData_RU_t *syncMsg = (processingData_RU_t *)NotifiedFifoData(res);
|
||||
syncMsg->frame_tx = frame_tx;
|
||||
syncMsg->slot_tx = slot_tx;
|
||||
syncMsg->timestamp_tx = info->timestamp_tx;
|
||||
syncMsg->ru = gNB->RU_list[0];
|
||||
res->key = slot_tx;
|
||||
pushTpool(gNB->threadPool, res);
|
||||
}
|
||||
|
||||
void rx_func(void *param) {
|
||||
|
||||
processingData_L1_t *info = (processingData_L1_t *) param;
|
||||
PHY_VARS_gNB *gNB = info->gNB;
|
||||
int frame_rx = info->frame_rx;
|
||||
int slot_rx = info->slot_rx;
|
||||
int frame_tx = info->frame_tx;
|
||||
int slot_tx = info->slot_tx;
|
||||
sl_ahead = sf_ahead*gNB->frame_parms.slots_per_subframe;
|
||||
nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
|
||||
|
||||
@@ -235,12 +228,6 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t
|
||||
rnti_to_remove_count = 0;
|
||||
if (pthread_mutex_unlock(&rnti_to_remove_mutex)) exit(1);
|
||||
|
||||
/*
|
||||
// if this is IF5 or 3GPP_gNB
|
||||
if (gNB && gNB->RU_list && gNB->RU_list[0] && gNB->RU_list[0]->function < NGFI_RAU_IF4p5) {
|
||||
wakeup_prach_gNB(gNB,NULL,proc->frame_rx,proc->slot_rx);
|
||||
}
|
||||
*/
|
||||
// Call the scheduler
|
||||
|
||||
pthread_mutex_lock(&gNB->UL_INFO_mutex);
|
||||
@@ -273,23 +260,24 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t
|
||||
phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx);
|
||||
}
|
||||
|
||||
if (oai_exit) return(-1);
|
||||
|
||||
// *****************************************
|
||||
// TX processing for subframe n+sf_ahead
|
||||
// run PHY TX procedures the one after the other for all CCs to avoid race conditions
|
||||
// (may be relaxed in the future for performance reasons)
|
||||
// *****************************************
|
||||
|
||||
if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) {
|
||||
|
||||
if(get_thread_parallel_conf() != PARALLEL_RU_L1_TRX_SPLIT) {
|
||||
phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1);
|
||||
}
|
||||
}
|
||||
|
||||
stop_meas( &softmodem_stats_rxtx_sf );
|
||||
LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, frame_rx, slot_rx, frame_tx, slot_tx);
|
||||
|
||||
notifiedFIFO_elt_t *res;
|
||||
|
||||
if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) {
|
||||
res = pullTpool(gNB->resp_L1_tx, gNB->threadPool);
|
||||
processingData_L1_t *syncMsg = (processingData_L1_t *)NotifiedFifoData(res);
|
||||
syncMsg->gNB = gNB;
|
||||
syncMsg->frame_rx = frame_rx;
|
||||
syncMsg->slot_rx = slot_rx;
|
||||
syncMsg->frame_tx = frame_tx;
|
||||
syncMsg->slot_tx = slot_tx;
|
||||
syncMsg->timestamp_tx = info->timestamp_tx;
|
||||
res->key = slot_tx;
|
||||
pushTpool(gNB->threadPool, res);
|
||||
}
|
||||
|
||||
#if 0
|
||||
LOG_D(PHY, "rxtx:%lld nfapi:%lld phy:%lld tx:%lld rx:%lld prach:%lld ofdm:%lld ",
|
||||
softmodem_stats_rxtx_sf.diff_now, nfapi_meas.diff_now,
|
||||
@@ -329,466 +317,7 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t
|
||||
TICK_TO_US(gNB->ulsch_tc_intl2_stats)
|
||||
);
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void *gNB_L1_thread_tx(void *param) {
|
||||
PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param;
|
||||
gNB_L1_proc_t *gNB_proc = &gNB->proc;
|
||||
gNB_L1_rxtx_proc_t *L1_proc_tx = &gNB_proc->L1_proc_tx;
|
||||
//PHY_VARS_gNB *gNB = RC.gNB[0][proc->CC_id];
|
||||
char thread_name[100];
|
||||
|
||||
sprintf(thread_name,"gNB_L1_thread_tx\n");
|
||||
|
||||
while (!oai_exit) {
|
||||
if (wait_on_condition(&L1_proc_tx->mutex,&L1_proc_tx->cond,&L1_proc_tx->instance_cnt,thread_name)<0) break;
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 1 );
|
||||
|
||||
if (oai_exit) break;
|
||||
|
||||
// *****************************************
|
||||
// TX processing for subframe n+4
|
||||
// run PHY TX procedures the one after the other for all CCs to avoid race conditions
|
||||
// (may be relaxed in the future for performance reasons)
|
||||
// *****************************************
|
||||
int frame_tx = L1_proc_tx->frame_tx;
|
||||
int slot_tx = L1_proc_tx->slot_tx;
|
||||
uint64_t timestamp_tx = L1_proc_tx->timestamp_tx;
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX1_GNB,slot_tx);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_GNB,frame_tx);
|
||||
phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_WAKEUP_TXFH, 1 );
|
||||
pthread_mutex_lock( &L1_proc_tx->mutex );
|
||||
L1_proc_tx->instance_cnt = -1;
|
||||
|
||||
// the thread can now be woken up
|
||||
if (pthread_cond_signal(&L1_proc_tx->cond) != 0) {
|
||||
LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n");
|
||||
exit_fun( "ERROR pthread_cond_signal" );
|
||||
}
|
||||
pthread_mutex_unlock(&L1_proc_tx->mutex);
|
||||
|
||||
wakeup_txfh(gNB,L1_proc_tx,frame_tx,slot_tx,timestamp_tx);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_WAKEUP_TXFH, 0 );
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 0 );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief The RX UE-specific and TX thread of gNB.
|
||||
* \param param is a \ref gNB_L1_proc_t structure which contains the info what to process.
|
||||
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
|
||||
*/
|
||||
|
||||
static void *gNB_L1_thread( void *param ) {
|
||||
static int gNB_thread_rxtx_status;
|
||||
PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param;
|
||||
gNB_L1_proc_t *gNB_proc = &gNB->proc;
|
||||
gNB_L1_rxtx_proc_t *L1_proc = &gNB_proc->L1_proc;
|
||||
//PHY_VARS_gNB *gNB = RC.gNB[0][proc->CC_id];
|
||||
char thread_name[100];
|
||||
// set default return value
|
||||
// set default return value
|
||||
gNB_thread_rxtx_status = 0;
|
||||
|
||||
sprintf(thread_name,"gNB_L1_thread");
|
||||
|
||||
|
||||
while (!oai_exit) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 0 );
|
||||
if (wait_on_condition(&L1_proc->mutex,&L1_proc->cond,&L1_proc->instance_cnt,thread_name)<0) break;
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 1 );
|
||||
|
||||
int frame_rx = L1_proc->frame_rx;
|
||||
int slot_rx = L1_proc->slot_rx;
|
||||
int frame_tx = L1_proc->frame_tx;
|
||||
int slot_tx = L1_proc->slot_tx;
|
||||
uint64_t timestamp_tx = L1_proc->timestamp_tx;
|
||||
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX0_GNB,slot_tx);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_RX0_GNB,slot_rx);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_GNB,frame_tx);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_GNB,frame_rx);
|
||||
|
||||
if (oai_exit) break;
|
||||
|
||||
if (gNB->CC_id==0) {
|
||||
if (rxtx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,thread_name) < 0) break;
|
||||
}
|
||||
|
||||
if (release_thread(&L1_proc->mutex,&L1_proc->instance_cnt,thread_name)<0) break;
|
||||
|
||||
if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) wakeup_tx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,timestamp_tx);
|
||||
else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) wakeup_txfh(gNB,L1_proc,frame_tx,slot_tx,timestamp_tx);
|
||||
} // while !oai_exit
|
||||
|
||||
LOG_D(PHY, " *** Exiting gNB thread RXn_TXnp4\n");
|
||||
gNB_thread_rxtx_status = 0;
|
||||
return &gNB_thread_rxtx_status;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
// Wait for gNB application initialization to be complete (gNB registration to MME)
|
||||
static void wait_system_ready (char *message, volatile int *start_flag) {
|
||||
static char *indicator[] = {". ", ".. ", "... ", ".... ", ".....",
|
||||
" ....", " ...", " ..", " .", " "
|
||||
};
|
||||
int i = 0;
|
||||
|
||||
while ((!oai_exit) && (*start_flag == 0)) {
|
||||
LOG_N(EMU, message, indicator[i]);
|
||||
fflush(stdout);
|
||||
i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0]));
|
||||
usleep(200000);
|
||||
}
|
||||
|
||||
LOG_D(EMU,"\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void gNB_top(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, char *string, struct RU_t_s *ru) {
|
||||
gNB_L1_proc_t *proc = &gNB->proc;
|
||||
gNB_L1_rxtx_proc_t *L1_proc = &proc->L1_proc;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
RU_proc_t *ru_proc=&ru->proc;
|
||||
proc->frame_rx = frame_rx;
|
||||
proc->slot_rx = slot_rx;
|
||||
sl_ahead = sf_ahead*fp->slots_per_subframe;
|
||||
|
||||
if (!oai_exit) {
|
||||
T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->slot_rx));
|
||||
L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe);
|
||||
L1_proc->frame_rx = ru_proc->frame_rx;
|
||||
L1_proc->slot_rx = ru_proc->tti_rx;
|
||||
L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
|
||||
L1_proc->slot_tx = (L1_proc->slot_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame;
|
||||
|
||||
if (rxtx(gNB,L1_proc->frame_rx,L1_proc->slot_rx,L1_proc->frame_tx,L1_proc->slot_tx,string) < 0) LOG_E(PHY,"gNB %d CC_id %d failed during execution\n",gNB->Mod_id,gNB->CC_id);
|
||||
|
||||
ru_proc->timestamp_tx = L1_proc->timestamp_tx;
|
||||
ru_proc->tti_tx = L1_proc->slot_tx;
|
||||
ru_proc->frame_tx = L1_proc->frame_tx;
|
||||
}
|
||||
}
|
||||
|
||||
int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot_tx,uint64_t timestamp_tx) {
|
||||
|
||||
RU_t *ru;
|
||||
RU_proc_t *ru_proc;
|
||||
|
||||
int waitret = 0, ret = 0, time_ns = 1000*1000;
|
||||
struct timespec now, abstime;
|
||||
// note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time
|
||||
// note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,1);
|
||||
time_ns = time_ns/gNB->frame_parms.slots_per_subframe;
|
||||
AssertFatal((ret = pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret);
|
||||
while (proc->instance_cnt_RUs < 0) {
|
||||
clock_gettime(CLOCK_REALTIME, &now);
|
||||
abstime.tv_sec = now.tv_sec;
|
||||
abstime.tv_nsec = now.tv_nsec + time_ns;
|
||||
|
||||
if (abstime.tv_nsec >= 1000*1000*1000) {
|
||||
abstime.tv_nsec -= 1000*1000*1000;
|
||||
abstime.tv_sec += 1;
|
||||
}
|
||||
if((waitret = pthread_cond_timedwait(&proc->cond_RUs,&proc->mutex_RUs_tx,&abstime)) == 0) break; // this unlocks mutex_rxtx while waiting and then locks it again
|
||||
}
|
||||
proc->instance_cnt_RUs = -1;
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs);
|
||||
AssertFatal((ret = pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,0);
|
||||
|
||||
if (waitret == ETIMEDOUT) {
|
||||
LOG_W(PHY,"Dropping TX slot (%d.%d) because FH is blocked more than 1 slot times (500us)\n",frame_tx,slot_tx);
|
||||
|
||||
AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret);
|
||||
gNB->proc.RU_mask_tx = 0;
|
||||
AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
|
||||
AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret);
|
||||
proc->instance_cnt_RUs = 0;
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs);
|
||||
AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,1);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,0);
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
for(int i=0; i<gNB->num_RU; i++)
|
||||
{
|
||||
ru = gNB->RU_list[i];
|
||||
ru_proc = &ru->proc;
|
||||
|
||||
|
||||
if (ru_proc->instance_cnt_gNBs == 0) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 1);
|
||||
LOG_E(PHY,"Frame %d, subframe %d: TX FH thread busy, dropping Frame %d, subframe %d\n", ru_proc->frame_tx, ru_proc->tti_tx, proc->frame_rx, proc->slot_rx);
|
||||
AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret);
|
||||
gNB->proc.RU_mask_tx = 0;
|
||||
AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 0);
|
||||
return(-1);
|
||||
}
|
||||
AssertFatal((ret = pthread_mutex_lock(&ru_proc->mutex_gNBs))==0,"ERROR pthread_mutex_lock failed on mutex_gNBs L1_thread_tx with ret=%d\n",ret);
|
||||
|
||||
ru_proc->instance_cnt_gNBs = 0;
|
||||
ru_proc->timestamp_tx = timestamp_tx;
|
||||
ru_proc->tti_tx = slot_tx;
|
||||
ru_proc->frame_tx = frame_tx;
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, ru_proc->instance_cnt_gNBs);
|
||||
|
||||
LOG_D(PHY,"Signaling tx_thread_fh for %d.%d\n",frame_tx,slot_tx);
|
||||
// the thread can now be woken up
|
||||
AssertFatal(pthread_cond_signal(&ru_proc->cond_gNBs) == 0,
|
||||
"[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n");
|
||||
AssertFatal((ret=pthread_mutex_unlock(&ru_proc->mutex_gNBs))==0,"mutex_unlock returned %d\n",ret);
|
||||
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int wakeup_tx(PHY_VARS_gNB *gNB,int frame_rx,int slot_rx,int frame_tx,int slot_tx,uint64_t timestamp_tx) {
|
||||
|
||||
|
||||
gNB_L1_rxtx_proc_t *L1_proc_tx = &gNB->proc.L1_proc_tx;
|
||||
|
||||
int ret;
|
||||
|
||||
|
||||
AssertFatal((ret = pthread_mutex_lock(&L1_proc_tx->mutex))==0,"mutex_lock returns %d\n",ret);
|
||||
|
||||
|
||||
while(L1_proc_tx->instance_cnt == 0) {
|
||||
pthread_cond_wait(&L1_proc_tx->cond,&L1_proc_tx->mutex);
|
||||
}
|
||||
|
||||
L1_proc_tx->instance_cnt = 0;
|
||||
|
||||
|
||||
L1_proc_tx->slot_rx = slot_rx;
|
||||
L1_proc_tx->frame_rx = frame_rx;
|
||||
L1_proc_tx->slot_tx = slot_tx;
|
||||
L1_proc_tx->frame_tx = frame_tx;
|
||||
L1_proc_tx->timestamp_tx = timestamp_tx;
|
||||
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,1);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,0);
|
||||
// the thread can now be woken up
|
||||
// the thread can now be woken up
|
||||
AssertFatal(pthread_cond_signal(&L1_proc_tx->cond) == 0, "ERROR pthread_cond_signal for gNB L1 thread\n");
|
||||
|
||||
AssertFatal((ret=pthread_mutex_unlock(&L1_proc_tx->mutex))==0,"mutex_unlock returns %d\n",ret);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
|
||||
gNB_L1_proc_t *proc=&gNB->proc;
|
||||
gNB_L1_rxtx_proc_t *L1_proc=&proc->L1_proc;
|
||||
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
|
||||
RU_proc_t *ru_proc=&ru->proc;
|
||||
int ret;
|
||||
int i;
|
||||
struct timespec abstime;
|
||||
int time_ns = 50000;
|
||||
int wait_timer = 0;
|
||||
bool do_last_check = 1;
|
||||
|
||||
AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU))==0,"mutex_lock returns %d\n",ret);
|
||||
for (i=0; i<gNB->num_RU; i++) {
|
||||
if (ru == gNB->RU_list[i]) {
|
||||
if ((proc->RU_mask&(1<<i)) > 0)
|
||||
LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n",
|
||||
gNB->Mod_id,proc->frame_rx,proc->slot_rx,ru->idx,gNB->num_RU,proc->RU_mask);
|
||||
proc->RU_mask |= (1<<i);
|
||||
}
|
||||
}
|
||||
if (proc->RU_mask != (1<<gNB->num_RU)-1) { // not all RUs have provided their information so return
|
||||
LOG_E(PHY,"Not all RUs have provided their info\n");
|
||||
AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"mutex_unlock returns %d\n",ret);
|
||||
return(0);
|
||||
}
|
||||
else { // all RUs have provided their information so continue on and wakeup gNB processing
|
||||
proc->RU_mask = 0;
|
||||
AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"muex_unlock returns %d\n",ret);
|
||||
}
|
||||
|
||||
// wake up TX for subframe n+sf_ahead
|
||||
// lock the TX mutex and make sure the thread is ready
|
||||
while (wait_timer < 200) {
|
||||
clock_gettime(CLOCK_REALTIME, &abstime);
|
||||
abstime.tv_nsec = abstime.tv_nsec + time_ns;
|
||||
|
||||
if (abstime.tv_nsec >= 1000*1000*1000) {
|
||||
abstime.tv_nsec -= 1000*1000*1000;
|
||||
abstime.tv_sec += 1;
|
||||
}
|
||||
|
||||
AssertFatal((ret=pthread_mutex_timedlock(&L1_proc->mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret);
|
||||
|
||||
if (L1_proc->instance_cnt == 0) { // L1_thread is busy so wait for a bit
|
||||
AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret);
|
||||
wait_timer += 50;
|
||||
usleep(50);
|
||||
}
|
||||
else {
|
||||
do_last_check = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (do_last_check) {
|
||||
AssertFatal((ret=pthread_mutex_timedlock(&L1_proc->mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret);
|
||||
if (L1_proc->instance_cnt == 0) { // L1_thread is busy so abort the subframe
|
||||
AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret);
|
||||
LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->tti_rx);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
++L1_proc->instance_cnt;
|
||||
// We have just received and processed the common part of a subframe, say n.
|
||||
// TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired
|
||||
// transmitted timestamp of the next TX slot (first).
|
||||
|
||||
// The last (TS_rx mod samples_per_frame) was n*samples_per_tti,
|
||||
// we want to generate subframe (n+sf_ahead), so TS_tx = TX_rx+sf_ahead*samples_per_tti,
|
||||
// and proc->slot_tx = proc->slot_rx+sf_ahead
|
||||
L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe);
|
||||
L1_proc->frame_rx = ru_proc->frame_rx;
|
||||
L1_proc->slot_rx = ru_proc->tti_rx;
|
||||
L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
|
||||
L1_proc->slot_tx = (L1_proc->slot_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame;
|
||||
|
||||
LOG_D(PHY,"wakeupL1: passing parameter IC = %d, RX: %d.%d, TX: %d.%d to L1 sf_ahead = %d\n", L1_proc->instance_cnt, L1_proc->frame_rx, L1_proc->slot_rx, L1_proc->frame_tx, L1_proc->slot_tx, sf_ahead);
|
||||
|
||||
pthread_mutex_unlock( &L1_proc->mutex );
|
||||
|
||||
// the thread can now be woken up
|
||||
if (pthread_cond_signal(&L1_proc->cond) != 0) {
|
||||
LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB RXn-TXnp4 thread\n");
|
||||
exit_fun( "ERROR pthread_cond_signal" );
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
/*
|
||||
void wakeup_prach_gNB(PHY_VARS_gNB *gNB,RU_t *ru,int frame,int subframe) {
|
||||
|
||||
gNB_L1_proc_t *proc = &gNB->proc;
|
||||
LTE_DL_FRAME_PARMS *fp=&gNB->frame_parms;
|
||||
int i;
|
||||
|
||||
if (ru!=NULL) {
|
||||
pthread_mutex_lock(&proc->mutex_RU_PRACH);
|
||||
for (i=0;i<gNB->num_RU;i++) {
|
||||
if (ru == gNB->RU_list[i]) {
|
||||
LOG_D(PHY,"frame %d, subframe %d: RU %d for gNB %d signals PRACH (mask %x, num_RU %d)\n",frame,subframe,i,gNB->Mod_id,proc->RU_mask_prach,gNB->num_RU);
|
||||
if ((proc->RU_mask_prach&(1<<i)) > 0)
|
||||
LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information (PRACH) from RU %d (num_RU %d, mask %x) has not been served yet!\n",
|
||||
gNB->Mod_id,frame,subframe,ru->idx,gNB->num_RU,proc->RU_mask_prach);
|
||||
proc->RU_mask_prach |= (1<<i);
|
||||
}
|
||||
}
|
||||
if (proc->RU_mask_prach != (1<<gNB->num_RU)-1) { // not all RUs have provided their information so return
|
||||
pthread_mutex_unlock(&proc->mutex_RU_PRACH);
|
||||
return;
|
||||
}
|
||||
else { // all RUs have provided their information so continue on and wakeup gNB processing
|
||||
proc->RU_mask_prach = 0;
|
||||
pthread_mutex_unlock(&proc->mutex_RU_PRACH);
|
||||
}
|
||||
}
|
||||
|
||||
// check if we have to detect PRACH first
|
||||
if (is_prach_subframe(fp,frame,subframe)>0) {
|
||||
LOG_D(PHY,"Triggering prach processing, frame %d, subframe %d\n",frame,subframe);
|
||||
if (proc->instance_cnt_prach == 0) {
|
||||
LOG_W(PHY,"[gNB] Frame %d Subframe %d, dropping PRACH\n", frame,subframe);
|
||||
return;
|
||||
}
|
||||
|
||||
// wake up thread for PRACH RX
|
||||
if (pthread_mutex_lock(&proc->mutex_prach) != 0) {
|
||||
LOG_E( PHY, "[gNB] ERROR pthread_mutex_lock for gNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach);
|
||||
exit_fun( "error locking mutex_prach" );
|
||||
return;
|
||||
}
|
||||
|
||||
++proc->instance_cnt_prach;
|
||||
// set timing for prach thread
|
||||
proc->frame_prach = frame;
|
||||
proc->subframe_prach = subframe;
|
||||
|
||||
// the thread can now be woken up
|
||||
if (pthread_cond_signal(&proc->cond_prach) != 0) {
|
||||
LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB PRACH thread %d\n", proc->thread_index);
|
||||
exit_fun( "ERROR pthread_cond_signal" );
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock( &proc->mutex_prach );
|
||||
}
|
||||
|
||||
}*/
|
||||
|
||||
/*!
|
||||
* \brief The prach receive thread of gNB.
|
||||
* \param param is a \ref gNB_L1_proc_t structure which contains the info what to process.
|
||||
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
|
||||
*/
|
||||
/*
|
||||
static void* gNB_thread_prach( void* param ) {
|
||||
static int gNB_thread_prach_status;
|
||||
|
||||
|
||||
PHY_VARS_gNB *gNB= (PHY_VARS_gNB *)param;
|
||||
gNB_L1_proc_t *proc = &gNB->proc;
|
||||
|
||||
// set default return value
|
||||
gNB_thread_prach_status = 0;
|
||||
|
||||
|
||||
|
||||
while (!oai_exit) {
|
||||
|
||||
if (oai_exit) break;
|
||||
|
||||
|
||||
if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"gNB_prach_thread") < 0) break;
|
||||
|
||||
LOG_D(PHY,"Running gNB prach procedures\n");
|
||||
prach_procedures(gNB ,0);
|
||||
|
||||
if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"gNB_prach_thread") < 0) break;
|
||||
}
|
||||
|
||||
LOG_I(PHY, "Exiting gNB thread PRACH\n");
|
||||
|
||||
gNB_thread_prach_status = 0;
|
||||
return &gNB_thread_prach_status;
|
||||
}
|
||||
*/
|
||||
|
||||
extern void init_td_thread(PHY_VARS_gNB *);
|
||||
extern void init_te_thread(PHY_VARS_gNB *);
|
||||
|
||||
static void *process_stats_thread(void *param) {
|
||||
|
||||
PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param;
|
||||
@@ -809,71 +338,13 @@ static void *process_stats_thread(void *param) {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
void init_gNB_proc(int inst) {
|
||||
int i=0;
|
||||
int CC_id = 0;
|
||||
void init_gNB_Tpool(int inst) {
|
||||
PHY_VARS_gNB *gNB;
|
||||
gNB_L1_proc_t *proc;
|
||||
gNB_L1_rxtx_proc_t *L1_proc,*L1_proc_tx;
|
||||
// LOG_I(PHY,"%s(inst:%d) RC.nb_nr_CC[inst]:%d \n",__FUNCTION__,inst,RC.nb_nr_CC[inst]);
|
||||
gNB = RC.gNB[inst];
|
||||
LOG_I(PHY,"Initializing gNB processes instance:%d CC_id %d \n",inst,CC_id);
|
||||
|
||||
proc = &gNB->proc;
|
||||
L1_proc = &proc->L1_proc;
|
||||
L1_proc_tx = &proc->L1_proc_tx;
|
||||
L1_proc->instance_cnt = -1;
|
||||
L1_proc_tx->instance_cnt = -1;
|
||||
L1_proc->instance_cnt_RUs = 0;
|
||||
L1_proc_tx->instance_cnt_RUs = 0;
|
||||
proc->instance_cnt_prach = -1;
|
||||
proc->instance_cnt_asynch_rxtx = -1;
|
||||
proc->CC_id = CC_id;
|
||||
proc->first_rx =1;
|
||||
proc->first_tx =1;
|
||||
proc->RU_mask =0;
|
||||
proc->RU_mask_tx = (1<<gNB->num_RU)-1;
|
||||
proc->RU_mask_prach =0;
|
||||
pthread_mutex_init( &gNB->UL_INFO_mutex, NULL);
|
||||
pthread_mutex_init( &L1_proc->mutex, NULL);
|
||||
pthread_mutex_init( &L1_proc_tx->mutex, NULL);
|
||||
pthread_cond_init( &L1_proc->cond, NULL);
|
||||
pthread_cond_init( &L1_proc_tx->cond, NULL);
|
||||
pthread_mutex_init( &proc->mutex_prach, NULL);
|
||||
pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL);
|
||||
pthread_mutex_init( &proc->mutex_RU,NULL);
|
||||
pthread_mutex_init( &proc->mutex_RU_tx,NULL);
|
||||
pthread_mutex_init( &proc->mutex_RU_PRACH,NULL);
|
||||
pthread_cond_init( &proc->cond_prach, NULL);
|
||||
pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
|
||||
LOG_I(PHY,"gNB->single_thread_flag:%d\n", gNB->single_thread_flag);
|
||||
|
||||
if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
|
||||
threadCreate( &L1_proc->pthread, gNB_L1_thread, gNB, "L1_proc", -1, OAI_PRIORITY_RT );
|
||||
threadCreate( &L1_proc_tx->pthread, gNB_L1_thread_tx, gNB,"L1_proc_tx", -1, OAI_PRIORITY_RT);
|
||||
}
|
||||
|
||||
if(opp_enabled == 1) threadCreate(&proc->L1_stats_thread, process_stats_thread,(void *)gNB, "time_meas", -1, OAI_PRIORITY_RT_LOW);
|
||||
//pthread_create( &proc->pthread_prach, attr_prach, gNB_thread_prach, gNB );
|
||||
char name[16];
|
||||
|
||||
if (gNB->single_thread_flag==0) {
|
||||
snprintf( name, sizeof(name), "L1 %d", i );
|
||||
pthread_setname_np( L1_proc->pthread, name );
|
||||
snprintf( name, sizeof(name), "L1TX %d", i );
|
||||
pthread_setname_np( L1_proc_tx->pthread, name );
|
||||
}
|
||||
|
||||
AssertFatal(proc->instance_cnt_prach == -1,"instance_cnt_prach = %d\n",proc->instance_cnt_prach);
|
||||
|
||||
/* setup PHY proc TX sync mechanism */
|
||||
pthread_mutex_init(&sync_phy_proc.mutex_phy_proc_tx, NULL);
|
||||
pthread_cond_init(&sync_phy_proc.cond_phy_proc_tx, NULL);
|
||||
sync_phy_proc.phy_proc_CC_id = 0;
|
||||
gNB_L1_proc_t *proc = &gNB->proc;
|
||||
|
||||
// ULSCH decoding threadpool
|
||||
gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t));
|
||||
gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
|
||||
int numCPU = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
int threadCnt = min(numCPU, gNB->pusch_proc_threads);
|
||||
char ul_pool[80];
|
||||
@@ -884,70 +355,40 @@ void init_gNB_proc(int inst) {
|
||||
s_offset += 3;
|
||||
}
|
||||
initTpool(ul_pool, gNB->threadPool, false);
|
||||
// ULSCH decoder result FIFO
|
||||
gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
|
||||
initNotifiedFIFO(gNB->respDecode);
|
||||
}
|
||||
|
||||
// L1 RX result FIFO
|
||||
gNB->resp_L1 = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
|
||||
initNotifiedFIFO(gNB->resp_L1);
|
||||
|
||||
// L1 TX result FIFO
|
||||
gNB->resp_L1_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
|
||||
initNotifiedFIFO(gNB->resp_L1_tx);
|
||||
|
||||
// RU TX result FIFO
|
||||
gNB->resp_RU_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
|
||||
initNotifiedFIFO(gNB->resp_RU_tx);
|
||||
|
||||
// Stats measurement thread
|
||||
if(opp_enabled == 1) threadCreate(&proc->L1_stats_thread, process_stats_thread,(void *)gNB, "time_meas", -1, OAI_PRIORITY_RT_LOW);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Terminate gNB TX and RX threads.
|
||||
*/
|
||||
void kill_gNB_proc(int inst) {
|
||||
int *status;
|
||||
PHY_VARS_gNB *gNB;
|
||||
gNB_L1_proc_t *proc;
|
||||
gNB_L1_rxtx_proc_t *L1_proc, *L1_proc_tx;
|
||||
|
||||
gNB=RC.gNB[inst];
|
||||
proc = &gNB->proc;
|
||||
L1_proc = &proc->L1_proc;
|
||||
L1_proc_tx = &proc->L1_proc_tx;
|
||||
LOG_I(PHY, "Killing TX inst %d\n",inst );
|
||||
|
||||
if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
|
||||
pthread_mutex_lock(&L1_proc->mutex);
|
||||
L1_proc->instance_cnt = 0;
|
||||
pthread_cond_signal(&L1_proc->cond);
|
||||
pthread_mutex_unlock(&L1_proc->mutex);
|
||||
pthread_mutex_lock(&L1_proc_tx->mutex);
|
||||
L1_proc_tx->instance_cnt = 0;
|
||||
pthread_cond_signal(&L1_proc_tx->cond);
|
||||
pthread_mutex_unlock(&L1_proc_tx->mutex);
|
||||
}
|
||||
|
||||
proc->instance_cnt_prach = 0;
|
||||
pthread_cond_signal( &proc->cond_prach );
|
||||
pthread_cond_signal( &proc->cond_asynch_rxtx );
|
||||
pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
|
||||
// LOG_D(PHY, "joining pthread_prach\n");
|
||||
// pthread_join( proc->pthread_prach, (void**)&status );
|
||||
LOG_I(PHY, "Destroying prach mutex/cond\n");
|
||||
pthread_mutex_destroy( &proc->mutex_prach );
|
||||
pthread_cond_destroy( &proc->cond_prach );
|
||||
LOG_I(PHY, "Destroying UL_INFO mutex\n");
|
||||
pthread_mutex_destroy(&gNB->UL_INFO_mutex);
|
||||
|
||||
if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
|
||||
LOG_I(PHY, "Joining L1_proc mutex/cond\n");
|
||||
pthread_join( L1_proc->pthread, (void **)&status );
|
||||
LOG_I(PHY, "Joining L1_proc_tx mutex/cond\n");
|
||||
pthread_join( L1_proc_tx->pthread, (void **)&status );
|
||||
}
|
||||
|
||||
LOG_I(PHY, "Destroying L1_proc mutex/cond\n");
|
||||
pthread_mutex_destroy( &L1_proc->mutex );
|
||||
pthread_cond_destroy( &L1_proc->cond );
|
||||
LOG_I(PHY, "Destroying L1_proc_tx mutex/cond\n");
|
||||
pthread_mutex_destroy( &L1_proc_tx->mutex );
|
||||
pthread_cond_destroy( &L1_proc_tx->cond );
|
||||
pthread_mutex_destroy( &proc->mutex_RU );
|
||||
pthread_mutex_destroy( &proc->mutex_RU_tx );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void reset_opp_meas(void) {
|
||||
int sfn;
|
||||
reset_meas(&softmodem_stats_mt);
|
||||
@@ -1015,15 +456,9 @@ printf("after %p\n", gNB->common_vars.rxdataF[aa]);
|
||||
* (not tested in other modes).
|
||||
*/
|
||||
//init_precoding_weights(RC.gNB[inst]);
|
||||
init_gNB_proc(inst);
|
||||
init_gNB_Tpool(inst);
|
||||
}
|
||||
|
||||
for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
|
||||
AssertFatal(RC.ru[ru_id]!=NULL,"ru_id %d is null\n",ru_id);
|
||||
RC.ru[ru_id]->nr_wakeup_rxtx = wakeup_rxtx;
|
||||
// RC.ru[ru_id]->wakeup_prach_eNB = wakeup_prach_gNB;
|
||||
RC.ru[ru_id]->gNB_top = gNB_top;
|
||||
}
|
||||
}
|
||||
|
||||
void init_gNB(int single_thread_flag,int wait_for_sync) {
|
||||
|
||||
+73
-610
@@ -788,259 +788,6 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* \brief The Asynchronous RX/TX FH thread of RAU/RCC/gNB/RRU.
|
||||
* This handles the RX FH for an asynchronous RRU/UE
|
||||
* \param param is a \ref gNB_L1_proc_t structure which contains the info what to process.
|
||||
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
|
||||
*/
|
||||
void *ru_thread_asynch_rxtx( void *param ) {
|
||||
static int ru_thread_asynch_rxtx_status;
|
||||
RU_t *ru = (RU_t *)param;
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->config;
|
||||
int slot=0, frame=0;
|
||||
// wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe
|
||||
wait_sync("ru_thread_asynch_rxtx");
|
||||
// wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe
|
||||
printf( "waiting for devices (ru_thread_asynch_rx)\n");
|
||||
wait_on_condition(&proc->mutex_asynch_rxtx,&proc->cond_asynch_rxtx,&proc->instance_cnt_asynch_rxtx,"thread_asynch");
|
||||
printf( "devices ok (ru_thread_asynch_rx)\n");
|
||||
|
||||
while (!oai_exit) {
|
||||
|
||||
if (slot==ru->nr_frame_parms->slots_per_frame) {
|
||||
slot=0;
|
||||
frame++;
|
||||
frame&=1023;
|
||||
} else {
|
||||
slot++;
|
||||
}
|
||||
|
||||
LOG_D(PHY,"ru_thread_asynch_rxtx: Waiting on incoming fronthaul\n");
|
||||
|
||||
// asynchronous receive from north (RRU IF4/IF5)
|
||||
if (ru->fh_north_asynch_in) {
|
||||
if ((nr_slot_select(cfg,frame,slot) & NR_DOWNLINK_SLOT)>0)
|
||||
ru->fh_north_asynch_in(ru,&frame,&slot);
|
||||
} else AssertFatal(1==0,"Unknown function in ru_thread_asynch_rxtx\n");
|
||||
}
|
||||
|
||||
ru_thread_asynch_rxtx_status=0;
|
||||
return(&ru_thread_asynch_rxtx_status);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* \brief The prach receive thread of RU.
|
||||
* \param param is a \ref RU_proc_t structure which contains the info what to process.
|
||||
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
|
||||
*/
|
||||
void *ru_thread_prach( void *param ) {
|
||||
static int ru_thread_prach_status;
|
||||
RU_t *ru = (RU_t *)param;
|
||||
RU_proc_t *proc = (RU_proc_t *)&ru->proc;
|
||||
// set default return value
|
||||
ru_thread_prach_status = 0;
|
||||
|
||||
while (RC.ru_mask>0) {
|
||||
usleep(1e6);
|
||||
LOG_I(PHY,"%s() RACH waiting for RU to be configured\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
LOG_I(PHY,"%s() RU configured - RACH processing thread running\n", __FUNCTION__);
|
||||
|
||||
while (!oai_exit) {
|
||||
|
||||
|
||||
if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break;
|
||||
|
||||
/*VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 );
|
||||
|
||||
if (ru->gNB_list[0]){
|
||||
prach_procedures(
|
||||
ru->gNB_list[0],0
|
||||
);
|
||||
}
|
||||
else {
|
||||
rx_prach(NULL,
|
||||
ru,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
proc->frame_prach,
|
||||
0,0
|
||||
);
|
||||
}
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );*/
|
||||
if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break;
|
||||
}
|
||||
|
||||
LOG_I(PHY, "Exiting RU thread PRACH\n");
|
||||
ru_thread_prach_status = 0;
|
||||
return &ru_thread_prach_status;
|
||||
}
|
||||
|
||||
|
||||
int wakeup_synch(RU_t *ru) {
|
||||
struct timespec wait;
|
||||
wait.tv_sec=0;
|
||||
wait.tv_nsec=5000000L;
|
||||
|
||||
// wake up synch thread
|
||||
// lock the synch mutex and make sure the thread is ready
|
||||
if (pthread_mutex_timedlock(&ru->proc.mutex_synch,&wait) != 0) {
|
||||
LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU synch thread (IC %d)\n", ru->proc.instance_cnt_synch );
|
||||
exit_fun( "error locking mutex_synch" );
|
||||
return(-1);
|
||||
}
|
||||
|
||||
++ru->proc.instance_cnt_synch;
|
||||
|
||||
// the thread can now be woken up
|
||||
if (pthread_cond_signal(&ru->proc.cond_synch) != 0) {
|
||||
LOG_E( PHY, "[RU] ERROR pthread_cond_signal for RU synch thread\n");
|
||||
exit_fun( "ERROR pthread_cond_signal" );
|
||||
return(-1);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock( &ru->proc.mutex_synch );
|
||||
return(0);
|
||||
}
|
||||
|
||||
void do_ru_synch(RU_t *ru) {
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
int i;
|
||||
void *rxp[2],*rxp2[2];
|
||||
int32_t dummy_rx[ru->nb_rx][fp->samples_per_subframe] __attribute__((aligned(32)));
|
||||
int rxs;
|
||||
int ic;
|
||||
|
||||
// initialize the synchronization buffer to the common_vars.rxdata
|
||||
for (int i=0; i<ru->nb_rx; i++)
|
||||
rxp[i] = &ru->common.rxdata[i][0];
|
||||
|
||||
double temp_freq1 = ru->rfdevice.openair0_cfg->rx_freq[0];
|
||||
double temp_freq2 = ru->rfdevice.openair0_cfg->tx_freq[0];
|
||||
|
||||
for (i=0; i<4; i++) {
|
||||
ru->rfdevice.openair0_cfg->rx_freq[i] = ru->rfdevice.openair0_cfg->tx_freq[i];
|
||||
ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq1;
|
||||
}
|
||||
|
||||
ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0);
|
||||
|
||||
while ((ru->in_synch ==0)&&(!oai_exit)) {
|
||||
// read in frame
|
||||
rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
|
||||
&(proc->timestamp_rx),
|
||||
rxp,
|
||||
fp->samples_per_subframe*10,
|
||||
ru->nb_rx);
|
||||
|
||||
if (rxs != fp->samples_per_subframe*10) LOG_E(PHY,"requested %d samples, got %d\n",fp->samples_per_subframe*10,rxs);
|
||||
|
||||
// wakeup synchronization processing thread
|
||||
wakeup_synch(ru);
|
||||
ic=0;
|
||||
|
||||
while ((ic>=0)&&(!oai_exit)) {
|
||||
// continuously read in frames, 1ms at a time,
|
||||
// until we are done with the synchronization procedure
|
||||
for (i=0; i<ru->nb_rx; i++)
|
||||
rxp2[i] = (void *)&dummy_rx[i][0];
|
||||
|
||||
for (i=0; i<10; i++)
|
||||
rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
|
||||
&(proc->timestamp_rx),
|
||||
rxp2,
|
||||
fp->samples_per_subframe,
|
||||
ru->nb_rx);
|
||||
|
||||
pthread_mutex_lock(&ru->proc.mutex_synch);
|
||||
ic = ru->proc.instance_cnt_synch;
|
||||
pthread_mutex_unlock(&ru->proc.mutex_synch);
|
||||
} // ic>=0
|
||||
} // in_synch==0
|
||||
|
||||
// read in rx_offset samples
|
||||
LOG_I(PHY,"Resynchronizing by %d samples\n",ru->rx_offset);
|
||||
rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
|
||||
&(proc->timestamp_rx),
|
||||
rxp,
|
||||
ru->rx_offset,
|
||||
ru->nb_rx);
|
||||
|
||||
for (i=0; i<4; i++) {
|
||||
ru->rfdevice.openair0_cfg->rx_freq[i] = temp_freq1;
|
||||
ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq2;
|
||||
}
|
||||
|
||||
ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void wakeup_gNB_L1s(RU_t *ru) {
|
||||
int i;
|
||||
PHY_VARS_gNB **gNB_list = ru->gNB_list;
|
||||
LOG_D(PHY,"wakeup_gNB_L1s (num %d) for RU %d ru->gNB_top:%p\n",ru->num_gNB,ru->idx, ru->gNB_top);
|
||||
|
||||
if (ru->num_gNB==1 && ru->gNB_top!=0 && get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) {
|
||||
// call gNB function directly
|
||||
char string[20];
|
||||
sprintf(string,"Incoming RU %u",ru->idx);
|
||||
LOG_D(PHY,"RU %d Call gNB_top\n",ru->idx);
|
||||
ru->gNB_top(gNB_list[0],ru->proc.frame_rx,ru->proc.tti_rx,string,ru);
|
||||
} else {
|
||||
LOG_D(PHY,"ru->num_gNB:%d\n", ru->num_gNB);
|
||||
|
||||
for (i=0; i<ru->num_gNB; i++) {
|
||||
LOG_D(PHY,"ru->wakeup_rxtx:%p\n", ru->nr_wakeup_rxtx);
|
||||
|
||||
if (ru->nr_wakeup_rxtx!=0 && ru->nr_wakeup_rxtx(gNB_list[i],ru) < 0) {
|
||||
LOG_E(PHY,"could not wakeup gNB rxtx process for subframe %d\n", ru->proc.tti_rx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int wakeup_prach_ru(RU_t *ru) {
|
||||
struct timespec wait;
|
||||
wait.tv_sec=0;
|
||||
wait.tv_nsec=5000000L;
|
||||
|
||||
if (pthread_mutex_timedlock(&ru->proc.mutex_prach,&wait) !=0) {
|
||||
LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU prach thread (IC %d)\n", ru->proc.instance_cnt_prach);
|
||||
exit_fun( "error locking mutex_rxtx" );
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (ru->proc.instance_cnt_prach==-1) {
|
||||
++ru->proc.instance_cnt_prach;
|
||||
ru->proc.frame_prach = ru->proc.frame_rx;
|
||||
ru->proc.subframe_prach = ru->proc.tti_rx;
|
||||
|
||||
// DJP - think prach_procedures() is looking at gNB frame_prach
|
||||
if (ru->gNB_list[0]) {
|
||||
ru->gNB_list[0]->proc.frame_prach = ru->proc.frame_rx;
|
||||
ru->gNB_list[0]->proc.slot_prach = ru->proc.tti_rx;
|
||||
}
|
||||
|
||||
LOG_I(PHY,"RU %d: waking up PRACH thread\n",ru->idx);
|
||||
// the thread can now be woken up
|
||||
AssertFatal(pthread_cond_signal(&ru->proc.cond_prach) == 0, "ERROR pthread_cond_signal for RU prach thread\n");
|
||||
} else LOG_W(PHY,"RU prach thread busy, skipping\n");
|
||||
|
||||
pthread_mutex_unlock( &ru->proc.mutex_prach );
|
||||
return(0);
|
||||
}
|
||||
|
||||
// this is for RU with local RF unit
|
||||
void fill_rf_config(RU_t *ru, char *rf_config_file) {
|
||||
int i;
|
||||
@@ -1299,136 +1046,61 @@ void *ru_stats_thread(void *param) {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
void *ru_thread_tx( void *param ) {
|
||||
RU_t *ru = (RU_t *)param;
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
PHY_VARS_gNB *gNB;
|
||||
gNB_L1_proc_t *gNB_proc;
|
||||
gNB_L1_rxtx_proc_t *L1_proc;
|
||||
char filename[40];
|
||||
int print_frame = 8;
|
||||
int i = 0;
|
||||
int ret;
|
||||
|
||||
void ru_tx_func(void *param) {
|
||||
|
||||
wait_on_condition(&proc->mutex_FH1,&proc->cond_FH1,&proc->instance_cnt_FH1,"ru_thread_tx");
|
||||
printf( "ru_thread_tx ready\n");
|
||||
processingData_RU_t *info = (processingData_RU_t *) param;
|
||||
RU_t *ru = info->ru;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
int frame_tx = info->frame_tx;
|
||||
int slot_tx = info->slot_tx;
|
||||
int print_frame = 8;
|
||||
char filename[40];
|
||||
|
||||
while (!oai_exit) {
|
||||
// do TX front-end processing if needed (precoding and/or IDFTs)
|
||||
if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,slot_tx);
|
||||
|
||||
LOG_D(PHY,"ru_thread_tx: Waiting for TX processing\n");
|
||||
// wait until eNBs are finished subframe RX n and TX n+4
|
||||
// do OFDM with/without TX front-end processing if needed
|
||||
if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,slot_tx);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 1 );
|
||||
wait_on_condition(&proc->mutex_gNBs,&proc->cond_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx");
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 0 );
|
||||
if(!emulate_rf) {
|
||||
// do outgoing fronthaul (south) if needed
|
||||
if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,frame_tx,slot_tx,info->timestamp_tx);
|
||||
|
||||
ret = pthread_mutex_lock(&proc->mutex_gNBs);
|
||||
AssertFatal(ret == 0,"mutex_lock return %d\n",ret);
|
||||
int frame_tx=proc->frame_tx;
|
||||
int tti_tx =proc->tti_tx;
|
||||
uint64_t timestamp_tx = proc->timestamp_tx;
|
||||
if (ru->fh_north_out) ru->fh_north_out(ru);
|
||||
} else {
|
||||
if(frame_tx == print_frame) {
|
||||
for (int i=0; i<ru->nb_tx; i++) {
|
||||
|
||||
ret = pthread_mutex_unlock(&proc->mutex_gNBs);
|
||||
AssertFatal(ret == 0,"mutex_lock returns %d\n",ret);
|
||||
if(slot_tx == 0) {
|
||||
sprintf(filename,"gNBdataF_frame%d_sl%d.m", print_frame, slot_tx);
|
||||
LOG_M(filename,"txdataF_frame",&ru->gNB_list[0]->common_vars.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1);
|
||||
|
||||
if (oai_exit) break;
|
||||
sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, slot_tx);
|
||||
LOG_M(filename,"txdataF_frame",&ru->common.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, tti_tx );
|
||||
|
||||
// do TX front-end processing if needed (precoding and/or IDFTs)
|
||||
if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,tti_tx);
|
||||
|
||||
// do OFDM with/without TX front-end processing if needed
|
||||
if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,tti_tx);
|
||||
|
||||
if(!emulate_rf) {
|
||||
// do outgoing fronthaul (south) if needed
|
||||
if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,frame_tx,tti_tx,timestamp_tx);
|
||||
|
||||
if (ru->fh_north_out) ru->fh_north_out(ru);
|
||||
} else {
|
||||
if(proc->frame_tx == print_frame) {
|
||||
for (i=0; i<ru->nb_tx; i++) {
|
||||
|
||||
if(proc->tti_tx == 0) {
|
||||
sprintf(filename,"gNBdataF_frame%d_sl%d.m", print_frame, proc->tti_tx);
|
||||
LOG_M(filename,"txdataF_frame",&ru->gNB_list[0]->common_vars.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1);
|
||||
|
||||
sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx);
|
||||
LOG_M(filename,"txdataF_frame",&ru->common.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1);
|
||||
|
||||
sprintf(filename,"tx%ddataF_BF_frame%d_sl%d.m", i, print_frame, proc->tti_tx);
|
||||
LOG_M(filename,"txdataF_BF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1);
|
||||
}
|
||||
|
||||
if(proc->tti_tx == 9) {
|
||||
sprintf(filename,"tx%ddata_frame%d.m", i, print_frame);
|
||||
LOG_M(filename,"txdata_frame",&ru->common.txdata[i][0],fp->samples_per_frame, 1, 1);
|
||||
sprintf(filename,"tx%ddata_frame%d.dat", i, print_frame);
|
||||
FILE *output_fd = fopen(filename,"w");
|
||||
|
||||
if (output_fd) {
|
||||
fwrite(&ru->common.txdata[i][0],
|
||||
sizeof(int32_t),
|
||||
fp->samples_per_frame,
|
||||
output_fd);
|
||||
fclose(output_fd);
|
||||
} else {
|
||||
LOG_E(PHY,"Cannot write to file %s\n",filename);
|
||||
}
|
||||
}//if(proc->tti_tx == 9)
|
||||
}//for (i=0; i<ru->nb_tx; i++)
|
||||
}//if(proc->frame_tx == print_frame)
|
||||
}//else emulate_rf
|
||||
|
||||
release_thread(&proc->mutex_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx");
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, proc->instance_cnt_gNBs);
|
||||
|
||||
for(i = 0; i<ru->num_gNB; i++) {
|
||||
gNB = ru->gNB_list[i];
|
||||
gNB_proc = &gNB->proc;
|
||||
L1_proc = (get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)? &gNB_proc->L1_proc_tx : &gNB_proc->L1_proc;
|
||||
ret = pthread_mutex_lock(&gNB_proc->mutex_RU_tx);
|
||||
AssertFatal(ret == 0,"mutex_lock returns %d\n",ret);
|
||||
|
||||
for (int j=0; j<gNB->num_RU; j++) {
|
||||
if (ru == gNB->RU_list[j]) {
|
||||
if ((gNB_proc->RU_mask_tx&(1<<j)) > 0)
|
||||
LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU tx %d (num_RU %d,mask %x) has not been served yet!\n",
|
||||
gNB->Mod_id,gNB_proc->frame_rx,gNB_proc->slot_rx,ru->idx,gNB->num_RU,gNB_proc->RU_mask_tx);
|
||||
|
||||
gNB_proc->RU_mask_tx |= (1<<j);
|
||||
sprintf(filename,"tx%ddataF_BF_frame%d_sl%d.m", i, print_frame, slot_tx);
|
||||
LOG_M(filename,"txdataF_BF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (gNB_proc->RU_mask_tx != (1<<gNB->num_RU)-1) { // not all RUs have provided their information so return
|
||||
ret = pthread_mutex_unlock(&gNB_proc->mutex_RU_tx);
|
||||
AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret);
|
||||
} else { // all RUs TX are finished so send the ready signal to gNB processing
|
||||
gNB_proc->RU_mask_tx = 0;
|
||||
ret = pthread_mutex_unlock(&gNB_proc->mutex_RU_tx);
|
||||
AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret);
|
||||
if(slot_tx == 9) {
|
||||
sprintf(filename,"tx%ddata_frame%d.m", i, print_frame);
|
||||
LOG_M(filename,"txdata_frame",&ru->common.txdata[i][0],fp->samples_per_frame, 1, 1);
|
||||
sprintf(filename,"tx%ddata_frame%d.dat", i, print_frame);
|
||||
FILE *output_fd = fopen(filename,"w");
|
||||
|
||||
ret = pthread_mutex_lock(&L1_proc->mutex_RUs_tx);
|
||||
AssertFatal(ret == 0,"mutex_lock returns %d\n",ret);
|
||||
// the thread can now be woken up
|
||||
if (L1_proc->instance_cnt_RUs == -1) {
|
||||
L1_proc->instance_cnt_RUs = 0;
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs);
|
||||
AssertFatal(pthread_cond_signal(&L1_proc->cond_RUs) == 0,
|
||||
"ERROR pthread_cond_signal for gNB_L1_thread\n");
|
||||
} //else AssertFatal(1==0,"gNB TX thread is not ready\n");
|
||||
ret = pthread_mutex_unlock(&L1_proc->mutex_RUs_tx);
|
||||
AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
release_thread(&proc->mutex_FH1,&proc->instance_cnt_FH1,"ru_thread_tx");
|
||||
return 0;
|
||||
if (output_fd) {
|
||||
fwrite(&ru->common.txdata[i][0],
|
||||
sizeof(int32_t),
|
||||
fp->samples_per_frame,
|
||||
output_fd);
|
||||
fclose(output_fd);
|
||||
} else {
|
||||
LOG_E(PHY,"Cannot write to file %s\n",filename);
|
||||
}
|
||||
}//if(slot_tx == 9)
|
||||
}//for (i=0; i<ru->nb_tx; i++)
|
||||
}//if(frame_tx == print_frame)
|
||||
}//else emulate_rf
|
||||
}
|
||||
|
||||
void *ru_thread( void *param ) {
|
||||
@@ -1436,12 +1108,11 @@ void *ru_thread( void *param ) {
|
||||
RU_t *ru = (RU_t *)param;
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
PHY_VARS_gNB *gNB = RC.gNB[0];
|
||||
int ret;
|
||||
int slot = fp->slots_per_frame-1;
|
||||
int frame = 1023;
|
||||
char filename[40], threadname[40];
|
||||
int print_frame = 8;
|
||||
int i = 0;
|
||||
char threadname[40];
|
||||
int aa;
|
||||
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->config;
|
||||
@@ -1501,6 +1172,15 @@ void *ru_thread( void *param ) {
|
||||
pthread_mutex_unlock(&RC.ru_mutex);
|
||||
wait_sync("ru_thread");
|
||||
|
||||
notifiedFIFO_elt_t *msg = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1,rx_func);
|
||||
notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1_tx,tx_func);
|
||||
notifiedFIFO_elt_t *msgRUTx = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_RU_tx,ru_tx_func);
|
||||
processingData_L1_t *syncMsg;
|
||||
notifiedFIFO_elt_t *res;
|
||||
pushNotifiedFIFO(gNB->resp_L1,msg); // to unblock the process in the beginning
|
||||
pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning
|
||||
pushNotifiedFIFO(gNB->resp_RU_tx,msgRUTx); // to unblock the process in the beginning
|
||||
|
||||
if(!emulate_rf) {
|
||||
// Start RF device if any
|
||||
if (ru->start_rf) {
|
||||
@@ -1509,19 +1189,6 @@ void *ru_thread( void *param ) {
|
||||
else LOG_I(PHY,"RU %d rf device ready\n",ru->idx);
|
||||
} else LOG_I(PHY,"RU %d no rf device\n",ru->idx);
|
||||
|
||||
// if an asnych_rxtx thread exists
|
||||
// wakeup the thread because the devices are ready at this point
|
||||
|
||||
if ((ru->fh_south_asynch_in)||(ru->fh_north_asynch_in)) {
|
||||
pthread_mutex_lock(&proc->mutex_asynch_rxtx);
|
||||
proc->instance_cnt_asynch_rxtx=0;
|
||||
pthread_mutex_unlock(&proc->mutex_asynch_rxtx);
|
||||
pthread_cond_signal(&proc->cond_asynch_rxtx);
|
||||
} else LOG_I(PHY,"RU %d no asynch_south interface\n",ru->idx);
|
||||
|
||||
// if this is a slave RRU, try to synchronize on the DL frequency
|
||||
if ((ru->is_slave) && (ru->if_south == LOCAL_RF)) do_ru_synch(ru);
|
||||
|
||||
// start trx write thread
|
||||
if(usrp_tx_thread == 1){
|
||||
if (ru->start_write_thread){
|
||||
@@ -1535,11 +1202,6 @@ void *ru_thread( void *param ) {
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&proc->mutex_FH1);
|
||||
proc->instance_cnt_FH1 = 0;
|
||||
pthread_mutex_unlock(&proc->mutex_FH1);
|
||||
pthread_cond_signal(&proc->cond_FH1);
|
||||
|
||||
// This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices
|
||||
while (!oai_exit) {
|
||||
// these are local subframe/frame counters to check that we are in synch with the fronthaul timing.
|
||||
@@ -1557,31 +1219,23 @@ void *ru_thread( void *param ) {
|
||||
if (ru->fh_south_in) ru->fh_south_in(ru,&frame,&slot);
|
||||
else AssertFatal(1==0, "No fronthaul interface at south port");
|
||||
|
||||
proc->timestamp_tx = proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe);
|
||||
proc->frame_tx = (proc->tti_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (proc->frame_rx+1)&1023 : proc->frame_rx;
|
||||
proc->tti_tx = (proc->tti_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame;
|
||||
|
||||
LOG_D(PHY,"AFTER fh_south_in - SFN/SL:%d%d RU->proc[RX:%d.%d TX:%d.%d] RC.gNB[0]:[RX:%d%d TX(SFN):%d]\n",
|
||||
frame,slot,
|
||||
proc->frame_rx,proc->tti_rx,
|
||||
proc->frame_tx,proc->tti_tx,
|
||||
RC.gNB[0]->proc.frame_rx,RC.gNB[0]->proc.slot_rx,
|
||||
RC.gNB[0]->proc.frame_tx);
|
||||
/*
|
||||
LOG_D(PHY,"RU thread (do_prach %d, is_prach_subframe %d), received frame %d, subframe %d\n",
|
||||
ru->do_prach,
|
||||
is_prach_subframe(fp, proc->frame_rx, proc->tti_rx),
|
||||
proc->frame_rx,proc->tti_rx);
|
||||
|
||||
if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->tti_rx)==1)) {
|
||||
wakeup_prach_ru(ru);
|
||||
}*/
|
||||
|
||||
// adjust for timing offset between RU
|
||||
//printf("~~~~~~~~~~~~~~~~~~~~~~~~~~%d.%d in ru_thread is in process\n", proc->frame_rx, proc->tti_rx);
|
||||
if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023;
|
||||
|
||||
// do RX front-end processing (frequency-shift, dft) if needed
|
||||
|
||||
int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx);
|
||||
if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) {
|
||||
//if (proc->tti_rx==8) {
|
||||
|
||||
if (ru->feprx) {
|
||||
ru->feprx(ru,proc->tti_rx);
|
||||
@@ -1631,50 +1285,17 @@ void *ru_thread( void *param ) {
|
||||
}
|
||||
|
||||
// At this point, all information for subframe has been received on FH interface
|
||||
res = pullTpool(gNB->resp_L1, gNB->threadPool);
|
||||
syncMsg = (processingData_L1_t *)NotifiedFifoData(res);
|
||||
syncMsg->gNB = gNB;
|
||||
syncMsg->frame_rx = proc->frame_rx;
|
||||
syncMsg->slot_rx = proc->tti_rx;
|
||||
syncMsg->frame_tx = proc->frame_tx;
|
||||
syncMsg->slot_tx = proc->tti_tx;
|
||||
syncMsg->timestamp_tx = proc->timestamp_tx;
|
||||
res->key = proc->tti_rx;
|
||||
pushTpool(gNB->threadPool, res);
|
||||
|
||||
// wakeup all gNB processes waiting for this RU
|
||||
if (ru->num_gNB>0) wakeup_gNB_L1s(ru);
|
||||
|
||||
if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD || ru->num_gNB==0) {
|
||||
// do TX front-end processing if needed (precoding and/or IDFTs)
|
||||
if (ru->feptx_prec) ru->feptx_prec(ru,proc->frame_tx,proc->tti_tx);
|
||||
|
||||
// do OFDM with/without TX front-end processing if needed
|
||||
if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,proc->frame_tx,proc->tti_tx);
|
||||
|
||||
if(!emulate_rf) {
|
||||
// do outgoing fronthaul (south) if needed
|
||||
if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,proc->frame_tx,proc->tti_tx,proc->timestamp_tx);
|
||||
|
||||
if (ru->fh_north_out) ru->fh_north_out(ru);
|
||||
} else {
|
||||
if(proc->frame_tx == print_frame) {
|
||||
for (i=0; i<ru->nb_tx; i++) {
|
||||
sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx);
|
||||
LOG_M(filename,"txdataF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_slot_wCP, 1, 1);
|
||||
|
||||
if(proc->tti_tx == 9) {
|
||||
sprintf(filename,"tx%ddata_frame%d.m", i, print_frame);
|
||||
LOG_M(filename,"txdata_frame",&ru->common.txdata[i][0],fp->samples_per_frame, 1, 1);
|
||||
sprintf(filename,"tx%ddata_frame%d.dat", i, print_frame);
|
||||
FILE *output_fd = fopen(filename,"w");
|
||||
|
||||
if (output_fd) {
|
||||
fwrite(&ru->common.txdata[i][0],
|
||||
sizeof(int32_t),
|
||||
fp->samples_per_frame,
|
||||
output_fd);
|
||||
fclose(output_fd);
|
||||
} else {
|
||||
LOG_E(PHY,"Cannot write to file %s\n",filename);
|
||||
}
|
||||
}//if(proc->tti_tx == 9)
|
||||
}//for (i=0; i<ru->nb_tx; i++)
|
||||
}//if(proc->frame_tx == print_frame)
|
||||
}//else emulate_rf
|
||||
|
||||
proc->emulate_rf_busy = 0;
|
||||
}//if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD)
|
||||
}
|
||||
|
||||
printf( "Exiting ru_thread \n");
|
||||
@@ -1685,85 +1306,13 @@ void *ru_thread( void *param ) {
|
||||
else LOG_I(PHY,"RU %d rf device stopped\n",ru->idx);
|
||||
}
|
||||
|
||||
delNotifiedFIFO_elt(msg);
|
||||
delNotifiedFIFO_elt(msgL1Tx);
|
||||
delNotifiedFIFO_elt(msgRUTx);
|
||||
|
||||
ru_thread_status = 0;
|
||||
return &ru_thread_status;
|
||||
}
|
||||
/*
|
||||
// This thread run the initial synchronization like a UE
|
||||
void *ru_thread_synch(void *arg) {
|
||||
|
||||
RU_t *ru = (RU_t*)arg;
|
||||
NR_DL_FRAME_PARMS *fp=ru->nr_frame_parms;
|
||||
int32_t sync_pos,sync_pos2;
|
||||
uint32_t peak_val;
|
||||
uint32_t sync_corr[307200] __attribute__((aligned(32)));
|
||||
static int ru_thread_synch_status;
|
||||
|
||||
|
||||
|
||||
wait_sync("ru_thread_synch");
|
||||
|
||||
// initialize variables for PSS detection
|
||||
lte_sync_time_init(ru->nr_frame_parms);
|
||||
|
||||
while (!oai_exit) {
|
||||
|
||||
// wait to be woken up
|
||||
if (wait_on_condition(&ru->proc.mutex_synch,&ru->proc.cond_synch,&ru->proc.instance_cnt_synch,"ru_thread_synch")<0) break;
|
||||
|
||||
// if we're not in synch, then run initial synch
|
||||
if (ru->in_synch == 0) {
|
||||
// run intial synch like UE
|
||||
LOG_I(PHY,"Running initial synchronization\n");
|
||||
|
||||
sync_pos = lte_sync_time_gNB(ru->common.rxdata,
|
||||
fp,
|
||||
fp->samples_per_subframe*5,
|
||||
&peak_val,
|
||||
sync_corr);
|
||||
LOG_I(PHY,"RU synch: %d, val %d\n",sync_pos,peak_val);
|
||||
|
||||
if (sync_pos >= 0) {
|
||||
if (sync_pos >= fp->nb_prefix_samples)
|
||||
sync_pos2 = sync_pos - fp->nb_prefix_samples;
|
||||
else
|
||||
sync_pos2 = sync_pos + (fp->samples_per_subframe*10) - fp->nb_prefix_samples;
|
||||
|
||||
if (fp->frame_type == FDD) {
|
||||
|
||||
// PSS is hypothesized in last symbol of first slot in Frame
|
||||
int sync_pos_slot = (fp->samples_per_subframe>>1) - fp->ofdm_symbol_size - fp->nb_prefix_samples;
|
||||
|
||||
if (sync_pos2 >= sync_pos_slot)
|
||||
ru->rx_offset = sync_pos2 - sync_pos_slot;
|
||||
else
|
||||
ru->rx_offset = (fp->samples_per_subframe*10) + sync_pos2 - sync_pos_slot;
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
|
||||
LOG_I(PHY,"Estimated sync_pos %d, peak_val %d => timing offset %d\n",sync_pos,peak_val,ru->rx_offset);
|
||||
|
||||
if ((peak_val > 300000) && (sync_pos > 0)) {
|
||||
// if (sync_pos++ > 3) {
|
||||
write_output("ru_sync.m","sync",(void*)&sync_corr[0],fp->samples_per_subframe*5,1,2);
|
||||
write_output("ru_rx.m","rxs",(void*)ru->ru_time.rxdata[0][0],fp->samples_per_subframe*10,1,1);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
ru->in_synch=1;
|
||||
}
|
||||
}
|
||||
|
||||
if (release_thread(&ru->proc.mutex_synch,&ru->proc.instance_cnt_synch,"ru_synch_thread") < 0) break;
|
||||
} // oai_exit
|
||||
|
||||
ru_thread_synch_status = 0;
|
||||
return &ru_thread_synch_status;
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
int nr_start_if(struct RU_t_s *ru, struct PHY_VARS_gNB_s *gNB) {
|
||||
return(ru->ifdevice.trx_start_func(&ru->ifdevice));
|
||||
@@ -1785,17 +1334,10 @@ int start_write_thread(RU_t *ru) {
|
||||
void init_RU_proc(RU_t *ru) {
|
||||
int i=0;
|
||||
RU_proc_t *proc;
|
||||
char name[100];
|
||||
LOG_I(PHY,"Initializing RU proc %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]);
|
||||
proc = &ru->proc;
|
||||
memset((void *)proc,0,sizeof(RU_proc_t));
|
||||
proc->ru = ru;
|
||||
proc->instance_cnt_prach = -1;
|
||||
proc->instance_cnt_synch = -1;
|
||||
proc->instance_cnt_FH = -1;
|
||||
proc->instance_cnt_FH1 = -1;
|
||||
proc->instance_cnt_gNBs = -1;
|
||||
proc->instance_cnt_asynch_rxtx = -1;
|
||||
proc->instance_cnt_emulateRF = -1;
|
||||
proc->first_rx = 1;
|
||||
proc->first_tx = 1;
|
||||
@@ -1806,44 +1348,13 @@ void init_RU_proc(RU_t *ru) {
|
||||
|
||||
for (i=0; i<10; i++) proc->symbol_mask[i]=0;
|
||||
|
||||
pthread_mutex_init( &proc->mutex_prach, NULL);
|
||||
pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL);
|
||||
pthread_mutex_init( &proc->mutex_synch,NULL);
|
||||
pthread_mutex_init( &proc->mutex_FH,NULL);
|
||||
pthread_mutex_init( &proc->mutex_FH1,NULL);
|
||||
pthread_mutex_init( &proc->mutex_emulateRF,NULL);
|
||||
pthread_mutex_init( &proc->mutex_gNBs, NULL);
|
||||
pthread_cond_init( &proc->cond_prach, NULL);
|
||||
pthread_cond_init( &proc->cond_FH, NULL);
|
||||
pthread_cond_init( &proc->cond_FH1, NULL);
|
||||
pthread_cond_init( &proc->cond_emulateRF, NULL);
|
||||
pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
|
||||
pthread_cond_init( &proc->cond_synch,NULL);
|
||||
pthread_cond_init( &proc->cond_gNBs, NULL);
|
||||
threadCreate( &proc->pthread_FH, ru_thread, (void *)ru, "thread_FH", -1, OAI_PRIORITY_RT_MAX );
|
||||
|
||||
if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)
|
||||
threadCreate( &proc->pthread_FH1, ru_thread_tx, (void *)ru, "thread_FH1", -1, OAI_PRIORITY_RT );
|
||||
|
||||
if(emulate_rf)
|
||||
threadCreate( &proc->pthread_emulateRF, emulatedRF_thread, (void *)proc, "emulateRF", -1, OAI_PRIORITY_RT );
|
||||
|
||||
if (ru->function == NGFI_RRU_IF4p5) {
|
||||
threadCreate( &proc->pthread_prach, ru_thread_prach, (void *)ru, "RACH", -1, OAI_PRIORITY_RT );
|
||||
///tmp deactivation of synch thread
|
||||
// if (ru->is_slave == 1) pthread_create( &proc->pthread_synch, attr_synch, ru_thread_synch, (void*)ru);
|
||||
|
||||
if ((ru->if_timing == synch_to_other) ||
|
||||
(ru->function == NGFI_RRU_IF5) ||
|
||||
(ru->function == NGFI_RRU_IF4p5)) threadCreate( &proc->pthread_asynch_rxtx, ru_thread_asynch_rxtx, (void *)ru, "asynch_rxtx", -1, OAI_PRIORITY_RT );
|
||||
|
||||
snprintf( name, sizeof(name), "ru_thread_FH %d", ru->idx );
|
||||
pthread_setname_np( proc->pthread_FH, name );
|
||||
} else if (ru->function == gNodeB_3GPP && ru->if_south == LOCAL_RF) { // DJP - need something else to distinguish between monolithic and PNF
|
||||
LOG_I(PHY,"%s() DJP - added creation of pthread_prach\n", __FUNCTION__);
|
||||
threadCreate( &proc->pthread_prach, ru_thread_prach, (void *)ru,"RACH", -1, OAI_PRIORITY_RT );
|
||||
}
|
||||
|
||||
if (get_thread_worker_conf() == WORKER_ENABLE) {
|
||||
if (ru->feprx) nr_init_feprx_thread(ru);
|
||||
|
||||
@@ -1856,46 +1367,9 @@ void init_RU_proc(RU_t *ru) {
|
||||
void kill_NR_RU_proc(int inst) {
|
||||
RU_t *ru = RC.ru[inst];
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
pthread_mutex_lock(&proc->mutex_FH);
|
||||
proc->instance_cnt_FH = 0;
|
||||
pthread_mutex_unlock(&proc->mutex_FH);
|
||||
pthread_cond_signal(&proc->cond_FH);
|
||||
pthread_mutex_lock(&proc->mutex_prach);
|
||||
proc->instance_cnt_prach = 0;
|
||||
pthread_mutex_unlock(&proc->mutex_prach);
|
||||
pthread_cond_signal(&proc->cond_prach);
|
||||
pthread_mutex_lock(&proc->mutex_synch);
|
||||
proc->instance_cnt_synch = 0;
|
||||
pthread_mutex_unlock(&proc->mutex_synch);
|
||||
pthread_cond_signal(&proc->cond_synch);
|
||||
pthread_mutex_lock(&proc->mutex_gNBs);
|
||||
proc->instance_cnt_gNBs = 0;
|
||||
pthread_mutex_unlock(&proc->mutex_gNBs);
|
||||
pthread_cond_signal(&proc->cond_gNBs);
|
||||
pthread_mutex_lock(&proc->mutex_asynch_rxtx);
|
||||
proc->instance_cnt_asynch_rxtx = 0;
|
||||
pthread_mutex_unlock(&proc->mutex_asynch_rxtx);
|
||||
pthread_cond_signal(&proc->cond_asynch_rxtx);
|
||||
LOG_D(PHY, "Joining pthread_FH\n");
|
||||
pthread_join(proc->pthread_FH, NULL);
|
||||
|
||||
if (ru->function == NGFI_RRU_IF4p5) {
|
||||
LOG_D(PHY, "Joining pthread_prach\n");
|
||||
pthread_join(proc->pthread_prach, NULL);
|
||||
|
||||
if (ru->is_slave) {
|
||||
LOG_D(PHY, "Joining pthread_\n");
|
||||
pthread_join(proc->pthread_synch, NULL);
|
||||
}
|
||||
|
||||
if ((ru->if_timing == synch_to_other) ||
|
||||
(ru->function == NGFI_RRU_IF5) ||
|
||||
(ru->function == NGFI_RRU_IF4p5)) {
|
||||
LOG_D(PHY, "Joining pthread_asynch_rxtx\n");
|
||||
pthread_join(proc->pthread_asynch_rxtx, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (get_nprocs() >= 2) {
|
||||
if (ru->feprx) {
|
||||
pthread_mutex_lock(&proc->mutex_fep);
|
||||
@@ -1924,17 +1398,6 @@ void kill_NR_RU_proc(int inst) {
|
||||
LOG_D(PHY, "Joining ru_stats_thread\n");
|
||||
pthread_join(ru->ru_stats_thread, NULL);
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&proc->mutex_prach);
|
||||
pthread_mutex_destroy(&proc->mutex_asynch_rxtx);
|
||||
pthread_mutex_destroy(&proc->mutex_synch);
|
||||
pthread_mutex_destroy(&proc->mutex_FH);
|
||||
pthread_mutex_destroy(&proc->mutex_gNBs);
|
||||
pthread_cond_destroy(&proc->cond_prach);
|
||||
pthread_cond_destroy(&proc->cond_FH);
|
||||
pthread_cond_destroy(&proc->cond_asynch_rxtx);
|
||||
pthread_cond_destroy(&proc->cond_synch);
|
||||
pthread_cond_destroy(&proc->cond_gNBs);
|
||||
}
|
||||
|
||||
int check_capabilities(RU_t *ru,RRU_capabilities_t *cap)
|
||||
|
||||
+16
-9
@@ -703,16 +703,23 @@ void *UE_thread(void *arg) {
|
||||
|
||||
int flags = 0;
|
||||
int slot_tx_usrp = slot_nr + DURATION_RX_TO_TX - RX_NB_TH;
|
||||
uint8_t tdd_period = mac->phy_config.config_req.tdd_table.tdd_period_in_slots;
|
||||
uint8_t num_UL_slots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots +
|
||||
(mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0);
|
||||
uint8_t first_tx_slot = tdd_period - num_UL_slots;
|
||||
if (slot_tx_usrp%tdd_period==first_tx_slot)
|
||||
flags=2;
|
||||
else if (slot_tx_usrp%tdd_period==first_tx_slot+num_UL_slots-1)
|
||||
flags = 3;
|
||||
else if (slot_tx_usrp%tdd_period>first_tx_slot)
|
||||
|
||||
if (openair0_cfg[0].duplex_mode == duplex_mode_TDD) {
|
||||
|
||||
uint8_t tdd_period = mac->phy_config.config_req.tdd_table.tdd_period_in_slots;
|
||||
int nrofUplinkSlots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
|
||||
uint8_t num_UL_slots = nrofUplinkSlots + (nrofUplinkSlots != 0);
|
||||
uint8_t first_tx_slot = tdd_period - num_UL_slots;
|
||||
|
||||
if (slot_tx_usrp % tdd_period == first_tx_slot)
|
||||
flags = 2;
|
||||
else if (slot_tx_usrp % tdd_period == first_tx_slot + num_UL_slots - 1)
|
||||
flags = 3;
|
||||
else if (slot_tx_usrp % tdd_period > first_tx_slot)
|
||||
flags = 1;
|
||||
} else {
|
||||
flags = 1;
|
||||
}
|
||||
|
||||
if (flags || IS_SOFTMODEM_RFSIM)
|
||||
AssertFatal( writeBlockSize ==
|
||||
|
||||
@@ -531,7 +531,8 @@ int main( int argc, char **argv ) {
|
||||
fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config;
|
||||
|
||||
nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config, *mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]);
|
||||
init_symbol_rotation(&UE[CC_id]->frame_parms, UE[CC_id]->frame_parms.dl_CarrierFreq);
|
||||
|
||||
init_symbol_rotation(&UE[CC_id]->frame_parms);
|
||||
init_nr_ue_vars(UE[CC_id], 0, abstraction_flag);
|
||||
|
||||
#ifdef FR2_TEST
|
||||
|
||||
@@ -245,6 +245,13 @@ extern char *get_softmodem_function(uint64_t *sofmodemfunc_mask_ptr);
|
||||
extern void set_softmodem_sighandler(void);
|
||||
extern uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
extern uint16_t sl_ahead;
|
||||
extern uint16_t sf_ahead;
|
||||
extern volatile int oai_exit;
|
||||
|
||||
void tx_func(void *param);
|
||||
void rx_func(void *param);
|
||||
void ru_tx_func(void *param);
|
||||
extern uint8_t nfapi_mode;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
+40
-15
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include "executables/nr-softmodem-common.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/phy_extern.h"
|
||||
#include "PHY/NR_REFSIG/nr_refsig.h"
|
||||
@@ -45,10 +46,42 @@
|
||||
|
||||
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
|
||||
|
||||
/*
|
||||
extern uint32_t from_nrarfcn(int nr_bandP,uint32_t dl_nrarfcn);
|
||||
extern openair0_config_t openair0_cfg[MAX_CARDS];
|
||||
*/
|
||||
static
|
||||
uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex)
|
||||
{
|
||||
const uint64_t dl_freq_khz = downlink_frequency / 1000;
|
||||
const int32_t delta_duplex_khz = delta_duplex / 1000;
|
||||
|
||||
uint64_t center_freq_diff_khz = 999999999999999999; // 2^64
|
||||
uint16_t current_band = 0;
|
||||
|
||||
for (int ind = 0; ind < nr_bandtable_size; ind++) {
|
||||
|
||||
LOG_D(PHY, "Scanning band %d, dl_min %"PRIu64", ul_min %"PRIu64"\n", nr_bandtable[ind].band, nr_bandtable[ind].dl_min, nr_bandtable[ind].ul_min);
|
||||
|
||||
if (dl_freq_khz < nr_bandtable[ind].dl_min || dl_freq_khz > nr_bandtable[ind].dl_max)
|
||||
continue;
|
||||
|
||||
int32_t current_offset_khz = nr_bandtable[ind].ul_min - nr_bandtable[ind].dl_min;
|
||||
|
||||
if (current_offset_khz != delta_duplex_khz)
|
||||
continue;
|
||||
|
||||
uint64_t center_frequency_khz = (nr_bandtable[ind].dl_max + nr_bandtable[ind].dl_min) / 2;
|
||||
|
||||
if (abs(dl_freq_khz - center_frequency_khz) < center_freq_diff_khz){
|
||||
current_band = nr_bandtable[ind].band;
|
||||
center_freq_diff_khz = abs(dl_freq_khz - center_frequency_khz);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_I(PHY, "DL frequency %"PRIu64": band %d, UL frequency %"PRIu64"\n",
|
||||
downlink_frequency, current_band, downlink_frequency+delta_duplex);
|
||||
|
||||
AssertFatal(current_band != 0, "Can't find EUTRA band for frequency %"PRIu64" and duplex_spacing %u\n", downlink_frequency, delta_duplex);
|
||||
|
||||
return current_band;
|
||||
}
|
||||
|
||||
int l1_north_init_gNB() {
|
||||
|
||||
@@ -455,7 +488,6 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) {
|
||||
uint8_t short_sequence, num_sequences, rootSequenceIndex, fd_occasion;
|
||||
NR_DL_FRAME_PARMS *fp = &RC.gNB[Mod_id]->frame_parms;
|
||||
nfapi_nr_config_request_scf_t *gNB_config = &RC.gNB[Mod_id]->gNB_config;
|
||||
int32_t dlul_offset = 0;
|
||||
|
||||
memcpy((void*)gNB_config,phy_config->cfg,sizeof(*phy_config->cfg));
|
||||
RC.gNB[Mod_id]->mac_enabled = 1;
|
||||
@@ -466,16 +498,9 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) {
|
||||
uint64_t ul_bw_khz = (12*gNB_config->carrier_config.ul_grid_size[gNB_config->ssb_config.scs_common.value].value)*(15<<gNB_config->ssb_config.scs_common.value);
|
||||
fp->ul_CarrierFreq = ((ul_bw_khz>>1) + gNB_config->carrier_config.uplink_frequency.value)*1000 ;
|
||||
|
||||
//fp->nr_band = *RC.nrmac[Mod_id]->common_channels[0].ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
|
||||
lte_frame_type_t frame_type = 0; // FDD
|
||||
|
||||
get_band(fp->dl_CarrierFreq,&fp->nr_band,&dlul_offset,&frame_type); //RC.nrmac[Mod_id] cannot be accessed in NFAPI
|
||||
int32_t dlul_offset = fp->ul_CarrierFreq - fp->dl_CarrierFreq;
|
||||
fp->nr_band = get_band(fp->dl_CarrierFreq, dlul_offset);
|
||||
|
||||
get_delta_duplex(fp->nr_band, gNB_config->ssb_config.scs_common.value, &dlul_offset);
|
||||
dlul_offset *= 1000;
|
||||
|
||||
AssertFatal(fp->ul_CarrierFreq == (fp->dl_CarrierFreq + dlul_offset), "Disagreement in uplink frequency for band %d: ul_CarrierFreq = %lu Hz vs expected %lu Hz\n", fp->nr_band, fp->ul_CarrierFreq, fp->dl_CarrierFreq + dlul_offset);
|
||||
|
||||
LOG_I(PHY, "DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %d Hz\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, dlul_offset);
|
||||
|
||||
fp->threequarter_fs = openair0_cfg[0].threequarter_fs;
|
||||
@@ -504,7 +529,7 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) {
|
||||
// }
|
||||
RC.gNB[Mod_id]->configured = 1;
|
||||
|
||||
init_symbol_rotation(fp,fp->dl_CarrierFreq);
|
||||
init_symbol_rotation(fp);
|
||||
|
||||
LOG_I(PHY,"gNB %d configured\n",Mod_id);
|
||||
}
|
||||
|
||||
@@ -352,9 +352,8 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
|
||||
fp->N_RB_UL = config->carrier_config.ul_grid_size[fp->numerology_index];
|
||||
fp->N_RB_DL = config->carrier_config.dl_grid_size[fp->numerology_index];
|
||||
|
||||
int32_t uplink_frequency_offset = 0;
|
||||
get_delta_duplex(fp->nr_band, fp->numerology_index, &uplink_frequency_offset);
|
||||
get_frame_type(fp->nr_band, fp->numerology_index, &fp->frame_type);
|
||||
fp->frame_type = get_frame_type(fp->nr_band, fp->numerology_index);
|
||||
int32_t uplink_frequency_offset = get_delta_duplex(fp->nr_band, fp->numerology_index);
|
||||
uplink_frequency_offset *= 1000;
|
||||
|
||||
LOG_I(PHY, "Initializing frame parms: DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %d Hz\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, uplink_frequency_offset);
|
||||
|
||||
@@ -591,35 +591,63 @@ void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH)
|
||||
}
|
||||
|
||||
|
||||
void init_symbol_rotation(NR_DL_FRAME_PARMS *fp,uint64_t CarrierFreq) {
|
||||
void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) {
|
||||
|
||||
uint64_t dl_CarrierFreq = fp->dl_CarrierFreq;
|
||||
uint64_t ul_CarrierFreq = fp->ul_CarrierFreq;
|
||||
double f[2] = {(double)dl_CarrierFreq, (double)ul_CarrierFreq};
|
||||
|
||||
const int nsymb = fp->symbols_per_slot * fp->slots_per_frame/10;
|
||||
const double Tc=(1/480e3/4096);
|
||||
const double Nu=2048*64*(1/(float)(1<<fp->numerology_index));
|
||||
const double f0= (double)CarrierFreq;
|
||||
const double Ncp0=16*64 + (144*64*(1/(float)(1<<fp->numerology_index)));
|
||||
const double Ncp1=(144*64*(1/(float)(1<<fp->numerology_index)));
|
||||
double tl=0,poff,exp_re,exp_im;
|
||||
double Ncp,Ncpm1=Ncp0;
|
||||
|
||||
poff = 2*M_PI*((Ncp0*Tc))*f0;
|
||||
exp_re = cos(poff);
|
||||
exp_im = sin(-poff);
|
||||
fp->symbol_rotation[0]=(int16_t)floor(exp_re*32767);
|
||||
fp->symbol_rotation[1]=(int16_t)floor(exp_im*32767);
|
||||
LOG_I(PHY,"Doing symbol rotation calculation for gNB TX/RX, f0 %f Hz, Nsymb %d\n",f0,nsymb);
|
||||
LOG_I(PHY,"Symbol rotation %d/%d => (%d,%d)\n",0,nsymb,fp->symbol_rotation[0],fp->symbol_rotation[1]);
|
||||
for (int l=1;l<nsymb;l++) {
|
||||
if (l==(7*(1<<fp->numerology_index))) Ncp=Ncp0;
|
||||
else Ncp=Ncp1;
|
||||
tl += (Nu+Ncpm1)*Tc;
|
||||
poff = 2*M_PI*(tl + (Ncp*Tc))*f0;
|
||||
exp_re = cos(poff);
|
||||
exp_im = sin(-poff);
|
||||
fp->symbol_rotation[l<<1]=(int16_t)floor(exp_re*32767);
|
||||
fp->symbol_rotation[1+(l<<1)]=(int16_t)floor(exp_im*32767);
|
||||
LOG_I(PHY,"Symbol rotation %d/%d => tl %f (%d,%d) (%f)\n",l,nsymb,tl,fp->symbol_rotation[l<<1],fp->symbol_rotation[1+(l<<1)],
|
||||
(poff/2/M_PI)-floor(poff/2/M_PI));
|
||||
Ncpm1=Ncp;
|
||||
for (uint8_t ll = 0; ll < 2; ll++){
|
||||
|
||||
double f0 = f[ll];
|
||||
double Ncpm1 = Ncp0;
|
||||
int16_t *symbol_rotation = fp->symbol_rotation[ll];
|
||||
|
||||
double tl = 0;
|
||||
double poff = 2 * M_PI * ((Ncp0 * Tc)) * f0;
|
||||
double exp_re = cos(poff);
|
||||
double exp_im = sin(-poff);
|
||||
symbol_rotation[0] = (int16_t)floor(exp_re * 32767);
|
||||
symbol_rotation[1] = (int16_t)floor(exp_im * 32767);
|
||||
LOG_I(PHY, "Doing symbol rotation calculation for gNB TX/RX, f0 %f Hz, Nsymb %d\n", f0, nsymb);
|
||||
LOG_I(PHY, "Symbol rotation %d/%d => (%d,%d)\n",
|
||||
0,
|
||||
nsymb,
|
||||
symbol_rotation[0],
|
||||
symbol_rotation[1]);
|
||||
|
||||
for (int l = 1; l < nsymb; l++) {
|
||||
|
||||
double Ncp;
|
||||
if (l == (7 * (1 << fp->numerology_index))) {
|
||||
Ncp = Ncp0;
|
||||
} else {
|
||||
Ncp = Ncp1;
|
||||
}
|
||||
|
||||
tl += (Nu + Ncpm1) * Tc;
|
||||
poff = 2 * M_PI * (tl + (Ncp * Tc)) * f0;
|
||||
exp_re = cos(poff);
|
||||
exp_im = sin(-poff);
|
||||
symbol_rotation[l<<1] = (int16_t)floor(exp_re * 32767);
|
||||
symbol_rotation[1 + (l<<1)] = (int16_t)floor(exp_im * 32767);
|
||||
|
||||
LOG_I(PHY, "Symbol rotation %d/%d => tl %f (%d,%d) (%f)\n",
|
||||
l,
|
||||
nsymb,
|
||||
tl,
|
||||
symbol_rotation[l<<1],
|
||||
symbol_rotation[1 + (l<<1)],
|
||||
(poff / 2 / M_PI) - floor(poff / 2 / M_PI));
|
||||
|
||||
Ncpm1 = Ncp;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ void apply_nr_rotation(NR_DL_FRAME_PARMS *fp,
|
||||
int nsymb,
|
||||
int length);
|
||||
|
||||
void init_symbol_rotation(NR_DL_FRAME_PARMS *fp,uint64_t CarrierFreq);
|
||||
void init_symbol_rotation(NR_DL_FRAME_PARMS *fp);
|
||||
|
||||
void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms,
|
||||
int32_t *rxdataF,
|
||||
|
||||
@@ -306,15 +306,23 @@ void apply_nr_rotation(NR_DL_FRAME_PARMS *fp,
|
||||
int length) {
|
||||
int symb_offset = (slot%fp->slots_per_subframe)*fp->symbols_per_slot;
|
||||
|
||||
int16_t *symbol_rotation = fp->symbol_rotation[0];
|
||||
|
||||
for (int sidx=0;sidx<nsymb;sidx++) {
|
||||
|
||||
LOG_D(PHY,"Rotating symbol %d, slot %d, symbol_subframe_index %d, length %d (%d,%d)\n",
|
||||
first_symbol+sidx,slot,sidx+first_symbol+symb_offset,length,
|
||||
fp->symbol_rotation[2*(sidx+first_symbol+symb_offset)],fp->symbol_rotation[1+2*(sidx+first_symbol+symb_offset)]);
|
||||
rotate_cpx_vector(trxdata+(sidx*length*2),
|
||||
&fp->symbol_rotation[2*(sidx+first_symbol+symb_offset)],
|
||||
trxdata+(sidx*length*2),
|
||||
length,
|
||||
15);
|
||||
first_symbol + sidx,
|
||||
slot,
|
||||
sidx + first_symbol + symb_offset,
|
||||
length,
|
||||
symbol_rotation[2 * (sidx + first_symbol + symb_offset)],
|
||||
symbol_rotation[1 + 2 * (sidx + first_symbol + symb_offset)]);
|
||||
|
||||
rotate_cpx_vector(trxdata + (sidx * length * 2),
|
||||
&symbol_rotation[2 * (sidx + first_symbol + symb_offset)],
|
||||
trxdata + (sidx * length * 2),
|
||||
length,
|
||||
15);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -205,7 +205,7 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
#endif
|
||||
|
||||
int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot;
|
||||
int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation)[symbol+symb_offset];
|
||||
int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation[0])[symbol + symb_offset];
|
||||
((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1];
|
||||
rotate_cpx_vector((int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],
|
||||
(int16_t*)&rot2,
|
||||
@@ -386,7 +386,7 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
|
||||
int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot;
|
||||
int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation)[symbol+symb_offset];
|
||||
int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation[0])[symbol + symb_offset];
|
||||
((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1];
|
||||
|
||||
#ifdef DEBUG_FEP
|
||||
@@ -513,7 +513,7 @@ void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms,
|
||||
|
||||
for (int symbol=0;symbol<nsymb;symbol++) {
|
||||
|
||||
uint32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation)[symbol+symb_offset];
|
||||
uint32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation[1])[symbol + symb_offset];
|
||||
((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1];
|
||||
LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n",slot,symb_offset,((int16_t*)&rot2)[0],((int16_t*)&rot2)[1]);
|
||||
rotate_cpx_vector((int16_t *)&rxdataF[frame_parms->ofdm_symbol_size*symbol],
|
||||
|
||||
@@ -61,8 +61,6 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
debug_ch_est = fopen("debug_ch_est.txt","w");
|
||||
#endif
|
||||
|
||||
//uint16_t Nid_cell = (eNB_offset == 0) ? gNB->frame_parms.Nid_cell : gNB->measurements.adj_cell_id[eNB_offset-1];
|
||||
|
||||
uint8_t nushift;
|
||||
int **ul_ch_estimates = gNB->pusch_vars[ul_id]->ul_ch_estimates;
|
||||
int **rxdataF = gNB->common_vars.rxdataF;
|
||||
@@ -79,12 +77,17 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
|
||||
uint16_t nb_rb_pusch = pusch_pdu->rb_size;
|
||||
|
||||
/*
|
||||
#ifdef DEBUG_CH
|
||||
printf("PUSCH Channel Estimation : ch_offset %d, symbol_offset %d OFDM size %d, Ncp=%d, l=%d, Ns=%d, k=%d symbol %d\n", ,ch_offset,symbol_offset,gNB->frame_parms.ofdm_symbol_size,
|
||||
gNB->frame_parms.Ncp,l,Ns,k, symbol);
|
||||
LOG_D(PHY, "In %s: ch_offset %d, symbol_offset %d OFDM size %d, Ns = %d, k = %d symbol %d\n",
|
||||
__FUNCTION__,
|
||||
ch_offset,
|
||||
symbol_offset,
|
||||
gNB->frame_parms.ofdm_symbol_size,
|
||||
Ns,
|
||||
k,
|
||||
symbol);
|
||||
#endif
|
||||
*/
|
||||
|
||||
switch (nushift) {
|
||||
case 0:
|
||||
fl = filt8_l0;
|
||||
@@ -124,9 +127,9 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
|
||||
//------------------generate DMRS------------------//
|
||||
|
||||
if (pusch_pdu->transform_precoding == transform_precoder_disabled)
|
||||
if (pusch_pdu->transform_precoding == transform_precoder_disabled) {
|
||||
nr_pusch_dmrs_rx(gNB, Ns, gNB->nr_gold_pusch_dmrs[pusch_pdu->scid][Ns][symbol], &pilot[0], 1000, 0, nb_rb_pusch, pusch_pdu->rb_start*NR_NB_SC_PER_RB, pusch_pdu->dmrs_config_type);
|
||||
|
||||
}
|
||||
else { // if transform precoding or SC-FDMA is enabled in Uplink
|
||||
|
||||
// NR_SC_FDMA supports type1 DMRS so only 6 DMRS REs per RB possible
|
||||
@@ -151,11 +154,15 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
//------------------------------------------------//
|
||||
|
||||
|
||||
|
||||
#ifdef DEBUG_PUSCH
|
||||
for (int i=0;i<(6*nb_rb_pusch);i++)
|
||||
printf("%d+j*(%d)\n",((int16_t*)pilot)[2*i],((int16_t*)pilot)[1+(2*i)]);
|
||||
for (int i = 0; i < (6 * nb_rb_pusch); i++) {
|
||||
LOG_I(PHY, "In %s: %d + j*(%d)\n",
|
||||
__FUNCTION__,
|
||||
((int16_t*)pilot)[2 * i],
|
||||
((int16_t*)pilot)[1 + (2 * i)]);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (aarx=0; aarx<gNB->frame_parms.nb_antennas_rx; aarx++) {
|
||||
|
||||
re_offset = k; /* Initializing the Resource element offset for each Rx antenna */
|
||||
@@ -167,11 +174,11 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
memset(ul_ch,0,4*(gNB->frame_parms.ofdm_symbol_size));
|
||||
|
||||
#ifdef DEBUG_PUSCH
|
||||
printf("symbol_offset %d, nushift %d\n",symbol_offset,nushift);
|
||||
printf("ch est pilot addr %p RB_DL %d\n",&pilot[0], gNB->frame_parms.N_RB_UL);
|
||||
printf("bwp_start_subcarrier %d, k %d, first_carrier %d, nb_rb_pusch %d\n",bwp_start_subcarrier,k,gNB->frame_parms.first_carrier_offset,nb_rb_pusch);
|
||||
printf("rxF addr %p p %d\n", rxF,p);
|
||||
printf("ul_ch addr %p nushift %d\n",ul_ch,nushift);
|
||||
LOG_I(PHY, "In %s symbol_offset %d, nushift %d\n", __FUNCTION__, symbol_offset, nushift);
|
||||
LOG_I(PHY, "In %s ch est pilot addr %p, N_RB_UL %d\n", __FUNCTION__, &pilot[0], gNB->frame_parms.N_RB_UL);
|
||||
LOG_I(PHY, "In %s bwp_start_subcarrier %d, k %d, first_carrier %d, nb_rb_pusch %d\n", __FUNCTION__, bwp_start_subcarrier, k, gNB->frame_parms.first_carrier_offset, nb_rb_pusch);
|
||||
LOG_I(PHY, "In %s rxF addr %p p %d\n", __FUNCTION__, rxF, p);
|
||||
LOG_I(PHY, "In %s ul_ch addr %p nushift %d\n", __FUNCTION__, ul_ch, nushift);
|
||||
#endif
|
||||
//if ((gNB->frame_parms.N_RB_UL&1)==0) {
|
||||
|
||||
@@ -182,9 +189,18 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
|
||||
#ifdef DEBUG_PUSCH
|
||||
printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1]));
|
||||
printf("pilot 0 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]);
|
||||
printf("data 0 : rxF - > (%d,%d) (%d)\n",rxF[2],rxF[3],dBc(rxF[2],rxF[3]));
|
||||
LOG_I(PHY, "In %s ch 0 %d\n", __FUNCTION__, ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1]));
|
||||
LOG_I(PHY, "In %s pilot 0 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",
|
||||
__FUNCTION__,
|
||||
rxF[0],
|
||||
rxF[1],
|
||||
dBc(rxF[0],rxF[1]),
|
||||
ch[0],
|
||||
ch[1],
|
||||
dBc(ch[0],ch[1]),
|
||||
pil[0],
|
||||
pil[1]);
|
||||
LOG_I(PHY, "In %s data 0 : rxF - > (%d,%d) (%d)\n", __FUNCTION__, rxF[2], rxF[3], dBc(rxF[2],rxF[3]));
|
||||
#endif
|
||||
|
||||
multadd_real_vector_complex_scalar(fl,
|
||||
@@ -201,9 +217,23 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
|
||||
#ifdef DEBUG_PUSCH
|
||||
printf("pilot 1 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]);
|
||||
printf("data 1 : rxF - > (%d,%d) (%d)\n",rxF[2],rxF[3],dBc(rxF[2],rxF[3]));
|
||||
LOG_I(PHY, "In %s pilot 1 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",
|
||||
__FUNCTION__,
|
||||
rxF[0],
|
||||
rxF[1],
|
||||
dBc(rxF[0],rxF[1]),
|
||||
ch[0],
|
||||
ch[1],
|
||||
dBc(ch[0],ch[1]),
|
||||
pil[0],
|
||||
pil[1]);
|
||||
LOG_I(PHY, "In %s data 1 : rxF - > (%d,%d) (%d)\n",
|
||||
__FUNCTION__,
|
||||
rxF[2],
|
||||
rxF[3],
|
||||
dBc(rxF[2],rxF[3]));
|
||||
#endif
|
||||
|
||||
multadd_real_vector_complex_scalar(fml,
|
||||
ch,
|
||||
ul_ch,
|
||||
@@ -217,9 +247,23 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
|
||||
#ifdef DEBUG_PUSCH
|
||||
printf("pilot 2 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]);
|
||||
printf("data 2 : rxF - > (%d,%d) (%d)\n",rxF[2],rxF[3],dBc(rxF[2],rxF[3]));
|
||||
LOG_I(PHY, "In %s pilot 2 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",
|
||||
__FUNCTION__,
|
||||
rxF[0],
|
||||
rxF[1],
|
||||
dBc(rxF[0],rxF[1]),
|
||||
ch[0],
|
||||
ch[1],
|
||||
dBc(ch[0],ch[1]),
|
||||
pil[0],
|
||||
pil[1]);
|
||||
LOG_I(PHY, "In %s data 2 : rxF - > (%d,%d) (%d)\n",
|
||||
__FUNCTION__,
|
||||
rxF[2],
|
||||
rxF[3],
|
||||
dBc(rxF[2],rxF[3]));
|
||||
#endif
|
||||
|
||||
multadd_real_vector_complex_scalar(fmm,
|
||||
ch,
|
||||
ul_ch,
|
||||
|
||||
@@ -40,9 +40,9 @@
|
||||
#include "PHY/defs_gNB.h"
|
||||
|
||||
/*Table 7.4.1.1.2-1/2 from 38.211 */
|
||||
int wf1[8][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,1}};
|
||||
int wf1[8][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1}};
|
||||
int wt1[8][2] = {{1,1},{1,1},{1,1},{1,1},{1,-1},{1,-1},{1,-1},{1,-1}};
|
||||
int wf2[12][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,1},{1,1},{1,-1},{1,1},{1,1}};
|
||||
int wf2[12][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1}};
|
||||
int wt2[12][2] = {{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,-1},{1,-1},{1,-1},{1,-1},{1,-1},{1,-1}};
|
||||
|
||||
// complex conjugate of mod table
|
||||
|
||||
@@ -147,19 +147,18 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB,
|
||||
uint16_t n_dmrs;
|
||||
if (rel15->dmrsConfigType==NFAPI_NR_DMRS_TYPE1) {
|
||||
nb_re_dmrs = 6*rel15->numDmrsCdmGrpsNoData;
|
||||
n_dmrs = ((rel15->rbSize+rel15->rbStart)*6)<<1;
|
||||
}
|
||||
else {
|
||||
nb_re_dmrs = 4*rel15->numDmrsCdmGrpsNoData;
|
||||
n_dmrs = ((rel15->rbSize+rel15->rbStart)*4)<<1;
|
||||
}
|
||||
n_dmrs = (rel15->rbSize+rel15->rbStart)*nb_re_dmrs;
|
||||
|
||||
uint16_t dmrs_symbol_map = rel15->dlDmrsSymbPos;//single DMRS: 010000100 Double DMRS 110001100
|
||||
uint8_t dmrs_len = get_num_dmrs(rel15->dlDmrsSymbPos);
|
||||
uint16_t nb_re = ((12*rel15->NrOfSymbols)-nb_re_dmrs*dmrs_len-xOverhead)*rel15->rbSize*rel15->nrOfLayers;
|
||||
uint8_t Qm = rel15->qamModOrder[0];
|
||||
uint32_t encoded_length = nb_re*Qm;
|
||||
int16_t mod_dmrs[14][n_dmrs] __attribute__ ((aligned(16)));
|
||||
int16_t mod_dmrs[14][n_dmrs<<1] __attribute__ ((aligned(16)));
|
||||
|
||||
/* PTRS */
|
||||
uint16_t beta_ptrs = 1;
|
||||
@@ -271,10 +270,10 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB,
|
||||
/// DMRS QPSK modulation
|
||||
for (int l=rel15->StartSymbolIndex; l<rel15->StartSymbolIndex+rel15->NrOfSymbols; l++) {
|
||||
if (rel15->dlDmrsSymbPos & (1 << l)) {
|
||||
nr_modulation(pdsch_dmrs[l][0], n_dmrs, DMRS_MOD_ORDER, mod_dmrs[l]); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated
|
||||
nr_modulation(pdsch_dmrs[l][0], n_dmrs*2, DMRS_MOD_ORDER, mod_dmrs[l]); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated
|
||||
|
||||
#ifdef DEBUG_DLSCH
|
||||
printf("DMRS modulation (symbol %d, %d symbols, type %d):\n", l, n_dmrs>>1, dmrs_Type);
|
||||
printf("DMRS modulation (symbol %d, %d symbols, type %d):\n", l, n_dmrs, dmrs_Type);
|
||||
for (int i=0; i<n_dmrs>>4; i++) {
|
||||
for (int j=0; j<8; j++) {
|
||||
printf("%d %d\t", mod_dmrs[l][((i<<3)+j)<<1], mod_dmrs[l][(((i<<3)+j)<<1)+1]);
|
||||
|
||||
@@ -158,7 +158,6 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr,
|
||||
if ((reg % reg_bundle_size_L) == 0) r++;
|
||||
}
|
||||
|
||||
|
||||
// Get cce_list indices by reg_idx in ascending order
|
||||
int f_bundle_j_list_id = 0;
|
||||
int f_bundle_j_list_ord[NR_MAX_PDCCH_AGG_LEVEL] = {};
|
||||
@@ -175,7 +174,6 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(int reg=0; reg<((coreset_nbr_rb*coreset_time_dur)); reg++) {
|
||||
|
||||
f_reg = (f_bundle_j_list_ord[reg/6]*reg_bundle_size_L)+(reg%reg_bundle_size_L);
|
||||
|
||||
@@ -105,6 +105,8 @@ typedef struct {
|
||||
uint8_t O_ACK;
|
||||
/// Index of current HARQ round for this ULSCH
|
||||
uint8_t round;
|
||||
/// Last Ndi for this harq process
|
||||
uint8_t ndi;
|
||||
/// pointer to pdu from MAC interface (TS 36.212 V15.4.0, Sec 5.1 p. 8)
|
||||
unsigned char *a;
|
||||
/// Pointer to the payload + CRC
|
||||
|
||||
@@ -78,13 +78,15 @@ void nr_rf_card_config(openair0_config_t *openair0_cfg,
|
||||
|
||||
openair0_cfg->autocal[i] = 1;
|
||||
|
||||
LOG_I(PHY, "HW: Configuring channel %d (rf_chain %d): setting tx_gain %f, rx_gain %f, tx_freq %f Hz, rx_freq %f Hz\n",
|
||||
i,
|
||||
rf_chain,
|
||||
openair0_cfg->tx_gain[i],
|
||||
openair0_cfg->rx_gain[i],
|
||||
openair0_cfg->tx_freq[i],
|
||||
openair0_cfg->rx_freq[i]);
|
||||
if (i < openair0_cfg->rx_num_channels) {
|
||||
LOG_I(PHY, "HW: Configuring channel %d (rf_chain %d): setting tx_gain %f, rx_gain %f, tx_freq %f Hz, rx_freq %f Hz\n",
|
||||
i,
|
||||
rf_chain,
|
||||
openair0_cfg->tx_gain[i],
|
||||
openair0_cfg->rx_gain[i],
|
||||
openair0_cfg->tx_freq[i],
|
||||
openair0_cfg->rx_freq[i]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -202,7 +202,6 @@ NR_UE_ULSCH_t *new_nr_ue_ulsch(uint16_t N_RB_UL,
|
||||
for (i=0; i<number_of_harq_pids; i++) {
|
||||
ulsch->harq_processes[i]->round=0;
|
||||
}
|
||||
|
||||
return(ulsch);
|
||||
}
|
||||
}
|
||||
@@ -257,7 +256,6 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch,
|
||||
Ilbrm = 0;
|
||||
Tbslbrm = 950984; //max tbs
|
||||
Coderate = 0.0;
|
||||
harq_process->round = nr_rv_round_map_ue[harq_process->pusch_pdu.pusch_data.rv_index];
|
||||
|
||||
///////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -267,8 +265,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch,
|
||||
LOG_D(PHY,"ulsch coding nb_rb %d, Nl = %d\n", nb_rb, harq_process->pusch_pdu.nrOfLayers);
|
||||
LOG_D(PHY,"ulsch coding A %d G %d mod_order %d\n", A,G, mod_order);
|
||||
|
||||
// if (harq_process->Ndi == 1) { // this is a new packet
|
||||
if (harq_process->round == 0) { // this is a new packet
|
||||
if (harq_process->ndi != harq_process->pusch_pdu.pusch_data.new_data_indicator) { // this is a new packet
|
||||
#ifdef DEBUG_ULSCH_CODING
|
||||
printf("encoding thinks this is a new packet \n");
|
||||
#endif
|
||||
@@ -415,7 +412,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch,
|
||||
|
||||
///////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
harq_process->ndi = harq_process->pusch_pdu.pusch_data.new_data_indicator;
|
||||
}
|
||||
F = harq_process->F;
|
||||
Kr = harq_process->K;
|
||||
|
||||
@@ -496,13 +496,19 @@ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE,
|
||||
int symb_offset = (slot%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot;
|
||||
for(ap = 0; ap < Nl; ap++) {
|
||||
for (int s=0;s<NR_NUMBER_OF_SYMBOLS_PER_SLOT;s++){
|
||||
LOG_D(PHY,"rotating txdataF symbol %d (%d) => (%d.%d)\n",
|
||||
s,s+symb_offset,frame_parms->symbol_rotation[2*(s+symb_offset)],frame_parms->symbol_rotation[1+(2*(s+symb_offset))]);
|
||||
rotate_cpx_vector((int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size*s],
|
||||
&frame_parms->symbol_rotation[2*(s+symb_offset)],
|
||||
(int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size*s],
|
||||
frame_parms->ofdm_symbol_size,
|
||||
15);
|
||||
|
||||
LOG_D(PHY,"In %s: rotating txdataF symbol %d (%d) => (%d.%d)\n",
|
||||
__FUNCTION__,
|
||||
s,
|
||||
s + symb_offset,
|
||||
frame_parms->symbol_rotation[1][2 * (s + symb_offset)],
|
||||
frame_parms->symbol_rotation[1][1 + (2 * (s + symb_offset))]);
|
||||
|
||||
rotate_cpx_vector((int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size * s],
|
||||
&frame_parms->symbol_rotation[1][2 * (s + symb_offset)],
|
||||
(int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size * s],
|
||||
frame_parms->ofdm_symbol_size,
|
||||
15);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -282,30 +282,6 @@ static void genericWaterFall (OAIgraph_t *graph, scopeSample_t *values, const in
|
||||
graph->iteration++;
|
||||
}
|
||||
|
||||
static void genericLogPowerPerAntena(OAIgraph_t *graph, const int nb_ant, const scopeSample_t **data, const int len) {
|
||||
float *values, *time;
|
||||
oai_xygraph_getbuff(graph, &time, &values, len, 0);
|
||||
|
||||
for (int ant=0; ant<nb_ant; ant++) {
|
||||
if (data[ant] != NULL) {
|
||||
float *values, *time;
|
||||
oai_xygraph_getbuff(graph, &time, &values, len, ant);
|
||||
|
||||
for (int i=0; i<len; i+=8) {
|
||||
float *vals=values+i;
|
||||
const scopeSample_t *in=&(data[ant][i]);
|
||||
|
||||
// TRY AUTOMATIC simd BY GCC
|
||||
for (int k=0; k<8; k++ ) {
|
||||
vals[k] = 10*log10(1.0+SquaredNorm(in[k]));
|
||||
}
|
||||
}
|
||||
|
||||
oai_xygraph(graph,time,values, len, ant, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void genericPowerPerAntena(OAIgraph_t *graph, const int nb_ant, const scopeSample_t **data, const int len) {
|
||||
float *values, *time;
|
||||
oai_xygraph_getbuff(graph, &time, &values, len, 0);
|
||||
|
||||
@@ -741,4 +741,10 @@ typedef struct RRU_config_s {
|
||||
MBSFN_config_t MBSFN_config[8];
|
||||
} RRU_config_t;
|
||||
|
||||
typedef struct processingData_RU {
|
||||
int frame_tx;
|
||||
int slot_tx;
|
||||
openair0_timestamp timestamp_tx;
|
||||
RU_t *ru;
|
||||
} processingData_RU_t;
|
||||
#endif //__PHY_DEFS_RU__H__
|
||||
|
||||
@@ -830,6 +830,9 @@ typedef struct PHY_VARS_gNB_s {
|
||||
time_stats_t ulsch_freq_offset_estimation_stats;
|
||||
*/
|
||||
notifiedFIFO_t *respDecode;
|
||||
notifiedFIFO_t *resp_L1;
|
||||
notifiedFIFO_t *resp_L1_tx;
|
||||
notifiedFIFO_t *resp_RU_tx;
|
||||
tpool_t *threadPool;
|
||||
int nbDecode;
|
||||
uint8_t pusch_proc_threads;
|
||||
@@ -871,4 +874,13 @@ union ldpcReqUnion {
|
||||
uint64_t p;
|
||||
};
|
||||
|
||||
typedef struct processingData_L1 {
|
||||
int frame_rx;
|
||||
int frame_tx;
|
||||
int slot_rx;
|
||||
int slot_tx;
|
||||
openair0_timestamp timestamp_tx;
|
||||
PHY_VARS_gNB *gNB;
|
||||
} processingData_L1_t;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -327,7 +327,8 @@ struct NR_DL_FRAME_PARMS {
|
||||
/// Cyclic Prefix for DL (0=Normal CP, 1=Extended CP)
|
||||
lte_prefix_type_t Ncp;
|
||||
/// sequence which is computed based on carrier frequency and numerology to rotate/derotate each OFDM symbol according to Section 5.3 in 38.211
|
||||
int16_t symbol_rotation[224*2];
|
||||
/// First dimension is for the direction of the link (0 DL, 1 UL)
|
||||
int16_t symbol_rotation[2][224*2];
|
||||
/// shift of pilot position in one RB
|
||||
uint8_t nushift;
|
||||
/// SRS configuration from TS 38.331 RRC
|
||||
@@ -368,20 +369,4 @@ struct NR_DL_FRAME_PARMS {
|
||||
#define KHz (1000UL)
|
||||
#define MHz (1000*KHz)
|
||||
|
||||
typedef struct nr_bandentry_s {
|
||||
int16_t band;
|
||||
uint64_t ul_min;
|
||||
uint64_t ul_max;
|
||||
uint64_t dl_min;
|
||||
uint64_t dl_max;
|
||||
uint64_t step_size;
|
||||
uint64_t N_OFFs_DL;
|
||||
uint8_t deltaf_raster;
|
||||
} nr_bandentry_t;
|
||||
|
||||
typedef struct nr_band_info_s {
|
||||
int nbands;
|
||||
nr_bandentry_t band_info[100];
|
||||
} nr_band_info_t;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -542,6 +542,9 @@ void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
|
||||
}
|
||||
|
||||
void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
|
||||
/* those variables to log T_GNB_PHY_PUCCH_PUSCH_IQ only when we try to decode */
|
||||
int pucch_decode_done = 0;
|
||||
int pusch_decode_done = 0;
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,1);
|
||||
LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx);
|
||||
@@ -563,6 +566,8 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
|
||||
(pucch->frame == frame_rx) &&
|
||||
(pucch->slot == slot_rx) ) {
|
||||
|
||||
pucch_decode_done = 1;
|
||||
|
||||
nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu;
|
||||
uint16_t num_ucis;
|
||||
switch (pucch_pdu->format_type) {
|
||||
@@ -651,7 +656,7 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
|
||||
}
|
||||
#endif
|
||||
|
||||
T(T_BENETEL, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF[0][0], 2048*4*14));
|
||||
pusch_decode_done = 1;
|
||||
|
||||
uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index;
|
||||
uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols;
|
||||
@@ -680,5 +685,9 @@ T(T_BENETEL, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF
|
||||
// figure out a better way to choose slot_rx, 19 is ok for a particular TDD configuration with 30kHz SCS
|
||||
if ((frame_rx&127) == 0 && slot_rx==19) dump_pusch_stats(gNB);
|
||||
|
||||
if (pucch_decode_done || pusch_decode_done) {
|
||||
T(T_GNB_PHY_PUCCH_PUSCH_IQ, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF[0][0], gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size * 4));
|
||||
}
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,0);
|
||||
}
|
||||
|
||||
@@ -132,6 +132,7 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
|
||||
}
|
||||
|
||||
switch (pdu_type){
|
||||
case FAPI_NR_RX_PDU_TYPE_SIB:
|
||||
case FAPI_NR_RX_PDU_TYPE_DLSCH:
|
||||
case FAPI_NR_RX_PDU_TYPE_RAR:
|
||||
harq_pid = dlsch0->current_harq_pid;
|
||||
@@ -238,33 +239,15 @@ void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx){
|
||||
int factor_mu = 1 << numerology;
|
||||
uint16_t bw_scaling = get_bw_scaling(bwp_ul_NB_RB);
|
||||
|
||||
LOG_D(PHY, "In %s: applying timing advance -- frame %d -- slot %d -- UE_mode %d\n", __FUNCTION__, frame_tx, slot_tx, ue->UE_mode[gNB_id]);
|
||||
ue->timing_advance += (ul_time_alignment->ta_command - 31) * bw_scaling / factor_mu;
|
||||
|
||||
if (ue->UE_mode[gNB_id] == RA_RESPONSE){
|
||||
|
||||
ue->timing_advance = ul_time_alignment->ta_command * bw_scaling / factor_mu;
|
||||
|
||||
LOG_D(PHY, "In %s: [UE %d] [%d.%d] Received (RAR) timing advance command %d new value is %u \n",
|
||||
__FUNCTION__,
|
||||
ue->Mod_id,
|
||||
frame_tx,
|
||||
slot_tx,
|
||||
ul_time_alignment->ta_command,
|
||||
ue->timing_advance);
|
||||
|
||||
} else if (ue->UE_mode[gNB_id] == PUSCH){
|
||||
|
||||
ue->timing_advance += (ul_time_alignment->ta_command - 31) * bw_scaling / factor_mu;
|
||||
|
||||
LOG_D(PHY, "In %s: [UE %d] [%d.%d] Got timing advance command %u from MAC, new value is %d\n",
|
||||
__FUNCTION__,
|
||||
ue->Mod_id,
|
||||
frame_tx,
|
||||
slot_tx,
|
||||
ul_time_alignment->ta_command,
|
||||
ue->timing_advance);
|
||||
|
||||
}
|
||||
LOG_I(PHY, "In %s: [UE %d] [%d.%d] Got timing advance command %u from MAC, new value is %d\n",
|
||||
__FUNCTION__,
|
||||
ue->Mod_id,
|
||||
frame_tx,
|
||||
slot_tx,
|
||||
ul_time_alignment->ta_command,
|
||||
ue->timing_advance);
|
||||
|
||||
ul_time_alignment->ta_frame = -1;
|
||||
ul_time_alignment->ta_slot = -1;
|
||||
@@ -1208,7 +1191,8 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_DLSCH, eNB_id, ue, dlsch0, number_pdus);
|
||||
break;
|
||||
case SI_PDSCH:
|
||||
rx_ind.rx_indication_body[0].pdu_type = FAPI_NR_RX_PDU_TYPE_SIB;
|
||||
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, eNB_id);
|
||||
nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SIB, eNB_id, ue, dlsch0, number_pdus);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -1179,7 +1179,7 @@ int main(int argc, char **argv) {
|
||||
DS_TDL,
|
||||
forgetting_factor,
|
||||
rx_sample_offset,
|
||||
0);
|
||||
0, 0);
|
||||
reset_meas(&eNB2UE[0]->random_channel);
|
||||
reset_meas(&eNB2UE[0]->interp_time);
|
||||
|
||||
@@ -1193,7 +1193,7 @@ int main(int argc, char **argv) {
|
||||
DS_TDL,
|
||||
forgetting_factor,
|
||||
rx_sample_offset,
|
||||
0);
|
||||
0, 0);
|
||||
reset_meas(&eNB2UE[n]->random_channel);
|
||||
reset_meas(&eNB2UE[n]->interp_time);
|
||||
}
|
||||
|
||||
@@ -988,7 +988,7 @@ int main(int argc, char **argv)
|
||||
N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL),
|
||||
forgetting_factor,
|
||||
rx_sample_offset,
|
||||
0);
|
||||
0, 0);
|
||||
|
||||
if(num_rounds>1) {
|
||||
for(n=1; n<8; n++)
|
||||
@@ -999,7 +999,7 @@ int main(int argc, char **argv)
|
||||
N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL),
|
||||
forgetting_factor,
|
||||
rx_sample_offset,
|
||||
0);
|
||||
0, 0);
|
||||
}
|
||||
|
||||
if (eNB2UE[0]==NULL) {
|
||||
|
||||
@@ -834,7 +834,7 @@ int main(int argc, char **argv) {
|
||||
N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL),
|
||||
forgetting_factor,
|
||||
rx_sample_offset,
|
||||
0);
|
||||
0, 0);
|
||||
|
||||
if(num_rounds>1) {
|
||||
for(n=1; n<4; n++)
|
||||
@@ -845,7 +845,7 @@ int main(int argc, char **argv) {
|
||||
N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL),
|
||||
forgetting_factor,
|
||||
rx_sample_offset,
|
||||
0);
|
||||
0, 0);
|
||||
}
|
||||
|
||||
if (eNB2UE[0]==NULL) {
|
||||
|
||||
@@ -1290,7 +1290,7 @@ int main(int argc, char **argv) {
|
||||
N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL),
|
||||
forgetting_factor,
|
||||
rx_sample_offset,
|
||||
0);
|
||||
0, 0);
|
||||
reset_meas(&eNB2UE[0]->random_channel);
|
||||
reset_meas(&eNB2UE[0]->interp_time);
|
||||
|
||||
@@ -1303,7 +1303,7 @@ int main(int argc, char **argv) {
|
||||
N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL),
|
||||
forgetting_factor,
|
||||
rx_sample_offset,
|
||||
0);
|
||||
0, 0);
|
||||
reset_meas(&eNB2UE[n]->random_channel);
|
||||
reset_meas(&eNB2UE[n]->interp_time);
|
||||
}
|
||||
|
||||
@@ -386,7 +386,7 @@ int main(int argc, char **argv) {
|
||||
N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL),
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
0, 0);
|
||||
|
||||
if (interf1>-20)
|
||||
eNB2UE1 = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx,
|
||||
@@ -396,7 +396,7 @@ int main(int argc, char **argv) {
|
||||
N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL),
|
||||
0,
|
||||
4,
|
||||
0);
|
||||
0, 0);
|
||||
|
||||
if (interf2>-20)
|
||||
eNB2UE2 = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx,
|
||||
@@ -406,7 +406,7 @@ int main(int argc, char **argv) {
|
||||
N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL),
|
||||
0,
|
||||
8,
|
||||
0);
|
||||
0, 0);
|
||||
|
||||
if (eNB2UE==NULL) {
|
||||
msg("Problem generating channel model. Exiting.\n");
|
||||
|
||||
@@ -708,7 +708,7 @@ int main(int argc, char **argv) {
|
||||
N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL),
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
0, 0);
|
||||
L1_rxtx_proc_t *proc_rxtx = (subframe == 0)? &eNB->proc.L1_proc: &eNB->proc.L1_proc_tx;
|
||||
eNB->ulsch[0] = new_eNB_ulsch(MAX_TURBO_ITERATIONS,N_RB_DL,0);
|
||||
UE->ulsch[0] = new_ue_ulsch(N_RB_DL,0);
|
||||
|
||||
@@ -343,7 +343,7 @@ int main(int argc, char **argv) {
|
||||
N_RB2channel_bandwidth(eNB->frame_parms.N_RB_UL),
|
||||
0.0,
|
||||
delay,
|
||||
0);
|
||||
0, 0);
|
||||
|
||||
if (UE2eNB==NULL) {
|
||||
msg("Problem generating channel model. Exiting.\n");
|
||||
|
||||
@@ -323,7 +323,7 @@ int main(int argc, char **argv) {
|
||||
N_RB2channel_bandwidth(eNB->frame_parms.N_RB_UL),
|
||||
0.0,
|
||||
0,
|
||||
0);
|
||||
0, 0);
|
||||
|
||||
if (UE2eNB==NULL) {
|
||||
printf("Problem generating channel model. Exiting.\n");
|
||||
|
||||
@@ -335,7 +335,7 @@ int main(int argc, char **argv) {
|
||||
N_RB2channel_bandwidth(PHY_vars_eNB->lte_frame_parms.N_RB_DL),
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
0, 0);
|
||||
|
||||
if (eNB2UE==NULL) {
|
||||
msg("Problem generating channel model. Exiting.\n");
|
||||
|
||||
@@ -724,7 +724,7 @@ int main(int argc, char **argv) {
|
||||
BW,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
0, 0);
|
||||
|
||||
if (interf1>-20)
|
||||
eNB2UE1 = new_channel_desc_scm(PHY_vars_eNB->lte_frame_parms.nb_antennas_tx,
|
||||
@@ -733,7 +733,7 @@ int main(int argc, char **argv) {
|
||||
BW,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
0, 0);
|
||||
|
||||
if (interf2>-20)
|
||||
eNB2UE2 = new_channel_desc_scm(PHY_vars_eNB->lte_frame_parms.nb_antennas_tx,
|
||||
@@ -742,7 +742,7 @@ int main(int argc, char **argv) {
|
||||
BW,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
0, 0);
|
||||
|
||||
if (eNB2UE==NULL) {
|
||||
msg("Problem generating channel model. Exiting.\n");
|
||||
|
||||
@@ -734,7 +734,7 @@ int main(int argc, char **argv) {
|
||||
30e-9,
|
||||
forgetting_factor,
|
||||
delay,
|
||||
0);
|
||||
0, 0);
|
||||
// set Doppler
|
||||
UE2eNB->max_Doppler = maxDoppler;
|
||||
|
||||
|
||||
@@ -339,7 +339,7 @@ int main(int argc, char **argv)
|
||||
61.44e6, //N_RB2sampling_rate(N_RB_DL),
|
||||
40e6, //N_RB2channel_bandwidth(N_RB_DL),
|
||||
DS_TDL,
|
||||
0, 0, 0);
|
||||
0, 0, 0, 0);
|
||||
|
||||
if (gNB2UE == NULL) {
|
||||
printf("Problem generating channel model. Exiting.\n");
|
||||
|
||||
@@ -79,8 +79,8 @@ int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
|
||||
double cpuf;
|
||||
|
||||
int sf_ahead=4 ;
|
||||
int sl_ahead=0;
|
||||
uint16_t sf_ahead=4 ;
|
||||
uint16_t sl_ahead=0;
|
||||
//uint8_t nfapi_mode = 0;
|
||||
uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
|
||||
@@ -97,6 +97,21 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP,
|
||||
const int CC_id,
|
||||
const uint8_t gNB_id,
|
||||
const frame_t frameP,
|
||||
const rb_id_t Srb_id,
|
||||
uint8_t *buffer_pP)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rrc_data_ind(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
@@ -185,10 +200,6 @@ int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0);
|
||||
int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); }
|
||||
int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); }
|
||||
|
||||
int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// needed for some functions
|
||||
openair0_config_t openair0_cfg[MAX_CARDS];
|
||||
void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex,int8_t *ptrs_arg);
|
||||
@@ -248,7 +259,10 @@ int main(int argc, char **argv)
|
||||
int i,aa;//,l;
|
||||
double sigma2, sigma2_dB=10, SNR, snr0=-2.0, snr1=2.0;
|
||||
uint8_t snr1set=0;
|
||||
float roundStats[50];
|
||||
double roundStats[500] = {0};
|
||||
double blerStats[500] = {0};
|
||||
double berStats[500] = {0};
|
||||
double snrStats[500] = {0};
|
||||
float effRate;
|
||||
//float psnr;
|
||||
float eff_tp_check = 0.7;
|
||||
@@ -743,7 +757,7 @@ int main(int argc, char **argv)
|
||||
30e-9,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
0, 0);
|
||||
|
||||
if (gNB2UE==NULL) {
|
||||
printf("Problem generating channel model. Exiting.\n");
|
||||
@@ -1114,7 +1128,9 @@ int main(int argc, char **argv)
|
||||
if (UE_harq_process->harq_ack.ack==1) effRate += ((float)TBS)/round;
|
||||
} // noise trials
|
||||
|
||||
blerStats[snrRun] = (float) n_errors / (float) n_trials;
|
||||
roundStats[snrRun]/=((float)n_trials);
|
||||
berStats[snrRun] = (double)errors_scrambling/available_bits/n_trials;
|
||||
effRate /= n_trials;
|
||||
printf("*****************************************\n");
|
||||
printf("SNR %f, (false positive %f)\n", SNR,
|
||||
@@ -1122,7 +1138,7 @@ int main(int argc, char **argv)
|
||||
printf("*****************************************\n");
|
||||
printf("\n");
|
||||
dump_pdsch_stats(gNB);
|
||||
printf("SNR %f : n_errors (negative CRC) = %d/%d, Avg round %.2f, Channel BER %e, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", SNR, n_errors, n_trials,roundStats[snrRun],(double)errors_scrambling/available_bits/n_trials,effRate,effRate/TBS*100,TBS);
|
||||
printf("SNR %f : n_errors (negative CRC) = %d/%d, Avg round %.2f, Channel BER %e, BLER %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", SNR, n_errors, n_trials,roundStats[snrRun],berStats[snrRun],blerStats[snrRun],effRate,effRate/TBS*100,TBS);
|
||||
printf("\n");
|
||||
|
||||
if (print_perf==1) {
|
||||
@@ -1187,15 +1203,19 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
}
|
||||
|
||||
//if ((float)n_errors/(float)n_trials <= target_error_rate) {
|
||||
if (effRate > (eff_tp_check*TBS)) {
|
||||
printf("PDSCH test OK\n");
|
||||
break;
|
||||
}
|
||||
|
||||
snrStats[snrRun] = SNR;
|
||||
snrRun++;
|
||||
} // NSR
|
||||
|
||||
LOG_M("dlsimStats.m","SNR",snrStats,snrRun,1,7);
|
||||
LOG_MM("dlsimStats.m","BLER",blerStats,snrRun,1,7);
|
||||
LOG_MM("dlsimStats.m","BER",berStats,snrRun,1,7);
|
||||
LOG_MM("dlsimStats.m","rounds",roundStats,snrRun,1,7);
|
||||
/*if (n_trials>1) {
|
||||
printf("HARQ stats:\nSNR\tRounds\n");
|
||||
psnr = snr0;
|
||||
|
||||
@@ -55,19 +55,6 @@ signed char quantize(double D, double x, unsigned char B) {
|
||||
return ((char) qxd);
|
||||
}
|
||||
|
||||
|
||||
int8_t
|
||||
mac_rrc_data_req_ue(
|
||||
const module_id_t Mod_idP,
|
||||
const int CC_id,
|
||||
const frame_t frameP,
|
||||
const rb_id_t Srb_id,
|
||||
const uint8_t Nb_tb,
|
||||
uint8_t *const buffer_pP,
|
||||
const mac_enb_index_t eNB_indexP,
|
||||
const uint8_t mbsfn_sync_area
|
||||
) { return(0);}
|
||||
|
||||
int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind) {return(0);}
|
||||
//NR_IF_Module_t *NR_IF_Module_init(int Mod_id){return(NULL);}
|
||||
int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { return(0); }
|
||||
|
||||
@@ -111,7 +111,7 @@ void nr_phy_config_request_sim_pbchsim(PHY_VARS_gNB *gNB,
|
||||
|
||||
nr_init_frame_parms(gNB_config, fp);
|
||||
|
||||
init_symbol_rotation(fp,fp->dl_CarrierFreq);
|
||||
init_symbol_rotation(fp);
|
||||
|
||||
gNB->configured = 1;
|
||||
LOG_I(PHY,"gNB configured\n");
|
||||
@@ -479,7 +479,7 @@ int main(int argc, char **argv)
|
||||
300e-9,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
0, 0);
|
||||
|
||||
if (gNB2UE==NULL) {
|
||||
printf("Problem generating channel model. Exiting.\n");
|
||||
@@ -540,7 +540,7 @@ int main(int argc, char **argv)
|
||||
if (input_fd==NULL) {
|
||||
gNB->pbch_configured = 1;
|
||||
|
||||
gNB->ssb_pdu.ssb_pdu_rel15.bchPayload = 0;
|
||||
gNB->ssb_pdu.ssb_pdu_rel15.bchPayload = 0x55dd33;
|
||||
|
||||
for (int slot=0;slot<frame_parms->slots_per_frame;slot++) {
|
||||
for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++)
|
||||
@@ -718,9 +718,9 @@ int main(int argc, char **argv)
|
||||
|
||||
payload_ret = (UE->pbch_vars[0]->xtra_byte == gNB_xtra_byte);
|
||||
for (i=0;i<3;i++){
|
||||
payload_ret += (UE->pbch_vars[0]->decoded_output[i] == (gNB->ssb_pdu.ssb_pdu_rel15.bchPayload>>(8*i)));
|
||||
payload_ret += (UE->pbch_vars[0]->decoded_output[i] == ((gNB->ssb_pdu.ssb_pdu_rel15.bchPayload>>(8*i)) & 0xff));
|
||||
}
|
||||
//printf("xtra byte gNB: 0x%02x UE: 0x%02x\n",gNB_xtra_byte, UE->rx_ind.rx_indication_body->mib_pdu.additional_bits);
|
||||
//printf("xtra byte gNB: 0x%02x UE: 0x%02x\n",gNB_xtra_byte, UE->pbch_vars[0]->xtra_byte);
|
||||
//printf("ret %d\n", payload_ret);
|
||||
if (payload_ret!=4)
|
||||
n_errors_payload++;
|
||||
|
||||
@@ -64,7 +64,7 @@ double cpuf;
|
||||
extern uint16_t prach_root_sequence_map0_3[838];
|
||||
openair0_config_t openair0_cfg[MAX_CARDS];
|
||||
//uint8_t nfapi_mode=0;
|
||||
int sl_ahead = 0;
|
||||
uint16_t sl_ahead = 0;
|
||||
|
||||
//void dump_nr_prach_config(NR_DL_FRAME_PARMS *frame_parms,uint8_t subframe);
|
||||
|
||||
@@ -132,13 +132,24 @@ nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(
|
||||
|
||||
int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, const uint8_t gNB_index, const int8_t channel, const uint8_t* pduP, const sdu_size_t pdu_len) {return 0;}
|
||||
|
||||
// Dummy function to avoid linking error at compilation of nr-prachsim
|
||||
int is_x2ap_enabled(void)
|
||||
void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP,
|
||||
const int CC_id,
|
||||
const uint8_t gNB_id,
|
||||
const frame_t frameP,
|
||||
const rb_id_t Srb_id,
|
||||
uint8_t *buffer_pP)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len) {
|
||||
// Dummy function to avoid linking error at compilation of nr-prachsim
|
||||
int is_x2ap_enabled(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -644,7 +655,7 @@ int main(int argc, char **argv){
|
||||
DS_TDL,
|
||||
0.0,
|
||||
delay,
|
||||
0);
|
||||
0, 0);
|
||||
|
||||
if (UE2gNB==NULL) {
|
||||
printf("Problem generating channel model. Exiting.\n");
|
||||
|
||||
@@ -418,7 +418,7 @@ int main(int argc, char **argv)
|
||||
printf("FFO = %lf; IFO = %d\n",eps-IFO,IFO);
|
||||
}
|
||||
|
||||
UE2gNB = new_channel_desc_scm(n_tx, n_rx, channel_model, fs, bw, DS_TDL,0, 0, 0);
|
||||
UE2gNB = new_channel_desc_scm(n_tx, n_rx, channel_model, fs, bw, DS_TDL,0, 0, 0, 0);
|
||||
|
||||
if (UE2gNB==NULL) {
|
||||
printf("Problem generating channel model. Exiting.\n");
|
||||
|
||||
@@ -364,7 +364,7 @@ int main(int argc, char **argv)
|
||||
61.44e6, //N_RB2sampling_rate(N_RB_DL),
|
||||
40e6, //N_RB2channel_bandwidth(N_RB_DL),
|
||||
DS_TDL,
|
||||
0,0,0);
|
||||
0,0,0, 0);
|
||||
|
||||
if (gNB2UE == NULL) {
|
||||
printf("Problem generating channel model. Exiting.\n");
|
||||
|
||||
@@ -75,9 +75,9 @@ PHY_VARS_NR_UE *UE;
|
||||
RAN_CONTEXT_t RC;
|
||||
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
|
||||
int sf_ahead=4 ;
|
||||
uint16_t sf_ahead=4 ;
|
||||
int slot_ahead=6 ;
|
||||
int sl_ahead=0;
|
||||
uint16_t sl_ahead=0;
|
||||
double cpuf;
|
||||
//uint8_t nfapi_mode = 0;
|
||||
uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
@@ -155,15 +155,27 @@ int is_x2ap_enabled(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//nFAPI P7 dummy functions
|
||||
void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP,
|
||||
const int CC_id,
|
||||
const uint8_t gNB_id,
|
||||
const frame_t frameP,
|
||||
const rb_id_t Srb_id,
|
||||
uint8_t *buffer_pP)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//nFAPI P7 dummy functions
|
||||
|
||||
int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); }
|
||||
int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); }
|
||||
int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); }
|
||||
int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); }
|
||||
int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nr_derive_key(int alg_type, uint8_t alg_id,
|
||||
const uint8_t key[32], uint8_t **out)
|
||||
@@ -580,7 +592,7 @@ int main(int argc, char **argv)
|
||||
sampling_frequency,
|
||||
bandwidth,
|
||||
DS_TDL,
|
||||
0, 0, 0);
|
||||
0, 0, 0, 0);
|
||||
|
||||
if (UE2gNB == NULL) {
|
||||
printf("Problem generating channel model. Exiting.\n");
|
||||
|
||||
@@ -398,6 +398,11 @@ typedef struct s1ap_register_enb_req_s {
|
||||
/* Number of SCTP streams used for a mme association */
|
||||
uint16_t sctp_in_streams;
|
||||
uint16_t sctp_out_streams;
|
||||
uint16_t s1_setuprsp_wait_timer;
|
||||
uint16_t s1_setupreq_wait_timer;
|
||||
uint16_t s1_setupreq_count;
|
||||
uint16_t sctp_req_timer;
|
||||
uint16_t sctp_req_count;
|
||||
} s1ap_register_enb_req_t;
|
||||
|
||||
//-------------------------------------------------------------------------------------------//
|
||||
|
||||
@@ -2429,6 +2429,65 @@ int RCconfig_S1(
|
||||
"to\n"
|
||||
" tracking_area_code = 1; // no string!!\n"
|
||||
" plmn_list = ( { mcc = 208; mnc = 93; mnc_length = 2; } )\n");
|
||||
if(*ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr <= 0xffff)
|
||||
{
|
||||
S1AP_REGISTER_ENB_REQ(msg_p).s1_setuprsp_wait_timer = *ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_E(S1AP,
|
||||
"s1setup_rsp_timer value in conf file is invalid (%d). Default value is set.\n",
|
||||
*ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr);
|
||||
S1AP_REGISTER_ENB_REQ(msg_p).s1_setuprsp_wait_timer = 5;
|
||||
}
|
||||
|
||||
if(*ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr <= 0xffff)
|
||||
{
|
||||
S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_wait_timer = *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_E(S1AP,
|
||||
"s1setup_req_timer value in conf file is invalid (%d). Default value is set.\n",
|
||||
*ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr);
|
||||
S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_wait_timer = 5;
|
||||
}
|
||||
|
||||
if(*ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr <= 0xffff)
|
||||
{
|
||||
S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_count = *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_E(S1AP,
|
||||
"s1setup_req_count value in conf file is invalid (%d). Default value is set.\n",
|
||||
*ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr);
|
||||
S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_count = 0xffff;
|
||||
}
|
||||
|
||||
if(*ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr <= 0xffff)
|
||||
{
|
||||
S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_timer = *ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_E(S1AP,
|
||||
"sctp_req_timer value in conf file is invalid (%d). Default value is set.\n",
|
||||
*ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr);
|
||||
S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_timer = 180;
|
||||
}
|
||||
|
||||
if(*ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr <= 0xffff)
|
||||
{
|
||||
S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_count = *ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_E(S1AP,
|
||||
"sctp_req_count value in conf file is invalid (%d). Default value is set.\n",
|
||||
*ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr);
|
||||
S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_count = 0xffff;
|
||||
}
|
||||
config_getlist(&PLMNParamList, PLMNParams, sizeof(PLMNParams)/sizeof(paramdef_t), aprefix);
|
||||
|
||||
if (PLMNParamList.numelt < 1 || PLMNParamList.numelt > 6) {
|
||||
|
||||
@@ -214,6 +214,11 @@ typedef enum {
|
||||
#define ENB_CONFIG_STRING_X2 "enable_x2"
|
||||
#define ENB_CONFIG_STRING_ENB_M2 "enable_enb_m2"
|
||||
#define ENB_CONFIG_STRING_MCE_M2 "enable_mce_m2"
|
||||
#define ENB_CONFIG_STRING_S1SETUP_RSP_TIMER "s1setup_rsp_timer"
|
||||
#define ENB_CONFIG_STRING_S1SETUP_REQ_TIMER "s1setup_req_timer"
|
||||
#define ENB_CONFIG_STRING_S1SETUP_REQ_COUNT "s1setup_req_count"
|
||||
#define ENB_CONFIG_STRING_SCTP_REQ_TIMER "sctp_req_timer"
|
||||
#define ENB_CONFIG_STRING_SCTP_REQ_COUNT "sctp_req_count"
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* cell configuration parameters */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
@@ -239,6 +244,11 @@ typedef enum {
|
||||
{ENB_CONFIG_STRING_X2, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
|
||||
{ENB_CONFIG_STRING_ENB_M2, NULL, 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \
|
||||
{ENB_CONFIG_STRING_MCE_M2, NULL, 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \
|
||||
{ENB_CONFIG_STRING_S1SETUP_RSP_TIMER, NULL, 0, uptr:NULL, defuintval:5, TYPE_UINT, 0}, \
|
||||
{ENB_CONFIG_STRING_S1SETUP_REQ_TIMER, NULL, 0, uptr:NULL, defuintval:5, TYPE_UINT, 0}, \
|
||||
{ENB_CONFIG_STRING_S1SETUP_REQ_COUNT, NULL, 0, uptr:NULL, defuintval:65535, TYPE_UINT, 0}, \
|
||||
{ENB_CONFIG_STRING_SCTP_REQ_TIMER, NULL, 0, uptr:NULL, defuintval:180, TYPE_UINT, 0}, \
|
||||
{ENB_CONFIG_STRING_SCTP_REQ_COUNT, NULL, 0, uptr:NULL, defuintval:65535, TYPE_UINT, 0}, \
|
||||
}
|
||||
|
||||
#define ENB_ENB_ID_IDX 0
|
||||
@@ -261,6 +271,11 @@ typedef enum {
|
||||
#define ENB_ENABLE_X2 17
|
||||
#define ENB_ENABLE_ENB_M2 18
|
||||
#define ENB_ENABLE_MCE_M2 19
|
||||
#define ENB_S1SETUP_RSP_TIMER_IDX 20
|
||||
#define ENB_S1SETUP_REQ_TIMER_IDX 21
|
||||
#define ENB_S1SETUP_REQ_COUNT_IDX 22
|
||||
#define ENB_SCTP_REQ_TIMER_IDX 23
|
||||
#define ENB_SCTP_REQ_COUNT_IDX 24
|
||||
|
||||
#define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD}
|
||||
#define ENBPARAMS_CHECK { \
|
||||
|
||||
@@ -490,7 +490,7 @@ typedef struct {
|
||||
|
||||
/*! \brief Uplink SCH PDU Structure */
|
||||
typedef struct {
|
||||
int8_t payload[SCH_PAYLOAD_SIZE_MAX]; /*!< \brief SACH payload */
|
||||
uint8_t payload[SCH_PAYLOAD_SIZE_MAX]; /*!< \brief SACH payload */
|
||||
uint16_t Pdu_size;
|
||||
} __attribute__ ((__packed__)) ULSCH_PDU;
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
*/
|
||||
|
||||
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include <limits.h>
|
||||
|
||||
#define reserved 0xffff
|
||||
@@ -1220,6 +1221,11 @@ int get_nr_prach_occasion_info_from_index(uint8_t index,
|
||||
else { // FDD
|
||||
x = table_6_3_3_2_2_prachConfig_Index[index][2];
|
||||
s_map = table_6_3_3_2_2_prachConfig_Index[index][4];
|
||||
for(int i = 0; i < 64 ; i++) {
|
||||
if ( (s_map >> i) & 0x01) {
|
||||
(*N_RA_sfn)++;
|
||||
}
|
||||
}
|
||||
*N_RA_slot = table_6_3_3_2_2_prachConfig_Index[index][6];
|
||||
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
|
||||
*start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5];
|
||||
@@ -1429,6 +1435,11 @@ int get_nr_prach_info_from_index(uint8_t index,
|
||||
if ( (table_6_3_3_2_2_prachConfig_Index[index][6] <= 1) && (slot%2 == 0) )
|
||||
return 0; // no prach in even slots @ 30kHz for 1 prach per subframe
|
||||
}
|
||||
for(int i = 0; i <= subframe ; i++) {
|
||||
if ( (s_map >> i) & 0x01) {
|
||||
(*RA_sfn_index)++;
|
||||
}
|
||||
}
|
||||
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
|
||||
*start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5];
|
||||
*N_t_slot = table_6_3_3_2_2_prachConfig_Index[index][7];
|
||||
@@ -1567,79 +1578,6 @@ uint8_t compute_nr_root_seq(NR_RACH_ConfigCommon_t *rach_config,
|
||||
}
|
||||
}
|
||||
|
||||
// Table 5.2-1 NR operating bands in FR1 & FR2 (3GPP TS 38.101)
|
||||
// Table 5.4.2.3-1 Applicable NR-ARFCN per operating band in FR1 & FR2 (3GPP TS 38.101)
|
||||
// Notes:
|
||||
// - N_OFFs for bands from 80 to 89 and band 95 is referred to UL
|
||||
// - Frequencies are expressed in KHz
|
||||
// - col: NR_band ul_min ul_max dl_min dl_max step N_OFFs_DL deltaf_raster
|
||||
nr_bandentry_t nr_bandtable[] = {
|
||||
{1, 1920000, 1980000, 2110000, 2170000, 20, 422000, 100},
|
||||
{2, 1850000, 1910000, 1930000, 1990000, 20, 386000, 100},
|
||||
{3, 1710000, 1785000, 1805000, 1880000, 20, 361000, 100},
|
||||
{5, 824000, 849000, 869000, 894000, 20, 173800, 100},
|
||||
{7, 2500000, 2570000, 2620000, 2690000, 20, 524000, 100},
|
||||
{8, 880000, 915000, 925000, 960000, 20, 185000, 100},
|
||||
{12, 698000, 716000, 729000, 746000, 20, 145800, 100},
|
||||
{14, 788000, 798000, 758000, 768000, 20, 151600, 100},
|
||||
{18, 815000, 830000, 860000, 875000, 20, 172000, 100},
|
||||
{20, 832000, 862000, 791000, 821000, 20, 158200, 100},
|
||||
{25, 1850000, 1915000, 1930000, 1995000, 20, 386000, 100},
|
||||
{26, 814000, 849000, 859000, 894000, 20, 171800, 100},
|
||||
{28, 703000, 758000, 758000, 813000, 20, 151600, 100},
|
||||
{29, 000, 000, 717000, 728000, 20, 143400, 100},
|
||||
{30, 2305000, 2315000, 2350000, 2360000, 20, 470000, 100},
|
||||
{34, 2010000, 2025000, 2010000, 2025000, 20, 402000, 100},
|
||||
{38, 2570000, 2620000, 2570000, 2630000, 20, 514000, 100},
|
||||
{39, 1880000, 1920000, 1880000, 1920000, 20, 376000, 100},
|
||||
{40, 2300000, 2400000, 2300000, 2400000, 20, 460000, 100},
|
||||
{41, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15},
|
||||
{41, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30},
|
||||
{47, 5855000, 5925000, 5855000, 5925000, 1, 790334, 15},
|
||||
//{48, 3550000, 3700000, 3550000, 3700000, 1, 636667, 15},
|
||||
//{48, 3550000, 3700000, 3550000, 3700000, 2, 636668, 30},
|
||||
{50, 1432000, 1517000, 1432000, 1517000, 20, 286400, 100},
|
||||
{51, 1427000, 1432000, 1427000, 1432000, 20, 285400, 100},
|
||||
{53, 2483500, 2495000, 2483500, 2495000, 20, 496700, 100},
|
||||
{65, 1920000, 2010000, 2110000, 2200000, 20, 422000, 100},
|
||||
{66, 1710000, 1780000, 2110000, 2200000, 20, 422000, 100},
|
||||
{70, 1695000, 1710000, 1995000, 2020000, 20, 399000, 100},
|
||||
{71, 663000, 698000, 617000, 652000, 20, 123400, 100},
|
||||
{74, 1427000, 1470000, 1475000, 1518000, 20, 295000, 100},
|
||||
{75, 000, 000, 1432000, 1517000, 20, 286400, 100},
|
||||
{76, 000, 000, 1427000, 1432000, 20, 285400, 100},
|
||||
{77, 3300000, 4200000, 3300000, 4200000, 1, 620000, 15},
|
||||
{77, 3300000, 4200000, 3300000, 4200000, 2, 620000, 30},
|
||||
{78, 3300000, 3800000, 3300000, 3800000, 1, 620000, 15},
|
||||
{78, 3300000, 3800000, 3300000, 3800000, 2, 620000, 30},
|
||||
{79, 4400010, 5000000, 4400010, 5000000, 1, 693334, 15},
|
||||
{79, 4400010, 5000000, 4400010, 5000000, 2, 693334, 30},
|
||||
{80, 1710000, 1785000, 000, 000, 20, 342000, 100},
|
||||
{81, 880000, 915000, 000, 000, 20, 176000, 100},
|
||||
{82, 832000, 862000, 000, 000, 20, 166400, 100},
|
||||
{83, 703000, 748000, 000, 000, 20, 140600, 100},
|
||||
{84, 1920000, 1980000, 000, 000, 20, 384000, 100},
|
||||
{86, 1710000, 1785000, 000, 000, 20, 342000, 100},
|
||||
{89, 824000, 849000, 000, 000, 20, 342000, 100},
|
||||
{90, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15},
|
||||
{90, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30},
|
||||
{90, 2496000, 2690000, 2496000, 2690000, 20, 499200, 100},
|
||||
{91, 832000, 862000, 1427000, 1432000, 20, 285400, 100},
|
||||
{92, 832000, 862000, 1432000, 1517000, 20, 286400, 100},
|
||||
{93, 880000, 915000, 1427000, 1432000, 20, 285400, 100},
|
||||
{94, 880000, 915000, 1432000, 1517000, 20, 286400, 100},
|
||||
{95, 2010000, 2025000, 000, 000, 20, 402000, 100},
|
||||
{257,26500020,29500000,26500020,29500000, 1,2054166, 60},
|
||||
{257,26500080,29500000,26500080,29500000, 2,2054167, 120},
|
||||
{258,24250080,27500000,24250080,27500000, 1,2016667, 60},
|
||||
{258,24250080,27500000,24250080,27500000, 2,2016667, 120},
|
||||
{260,37000020,40000000,37000020,40000000, 1,2229166, 60},
|
||||
{260,37000080,40000000,37000080,40000000, 2,2229167, 120},
|
||||
{261,27500040,28350000,27500040,28350000, 1,2070833, 60},
|
||||
{261,27500040,28350000,27500040,28350000, 2,2070833, 120}
|
||||
};
|
||||
|
||||
|
||||
// TS 38.211 Table 6.4.1.1.3-3: PUSCH DMRS positions l' within a slot for single-symbol DMRS and intra-slot frequency hopping disabled.
|
||||
// The first 4 colomns are PUSCH mapping type A and the last 4 colomns are PUSCH mapping type B.
|
||||
// When l' = l0, it is represented by 1
|
||||
@@ -1680,11 +1618,9 @@ int32_t table_6_4_1_1_3_4_pusch_dmrs_positions_l [12][8] = {
|
||||
{1, 1025, -1, -1, 1, 513, -1, -1}, //14 // (DMRS l' position)
|
||||
};
|
||||
|
||||
#define NR_BANDTABLE_SIZE (sizeof(nr_bandtable)/sizeof(nr_bandentry_t))
|
||||
|
||||
// Returns the corresponding row index of the NR table
|
||||
int get_nr_table_idx(int nr_bandP, uint8_t scs_index){
|
||||
|
||||
int get_nr_table_idx(int nr_bandP, uint8_t scs_index)
|
||||
{
|
||||
int i, j;
|
||||
int scs_khz = 15 << scs_index;
|
||||
int supplementary_bands[] = {29,75,76,80,81,82,83,84,86,89,95};
|
||||
@@ -1695,8 +1631,8 @@ int get_nr_table_idx(int nr_bandP, uint8_t scs_index){
|
||||
AssertFatal(0 == 1, "Band %d is a supplementary band (%d). This is not supported yet.\n", nr_bandP, supplementary_bands[j]);
|
||||
}
|
||||
|
||||
AssertFatal(nr_bandP <= nr_bandtable[NR_BANDTABLE_SIZE-1].band, "NR band %d exceeds NR bands table maximum limit %d\n", nr_bandP, nr_bandtable[NR_BANDTABLE_SIZE-1].band);
|
||||
for (i = 0; i < NR_BANDTABLE_SIZE && nr_bandtable[i].band != nr_bandP; i++);
|
||||
AssertFatal(nr_bandP <= nr_bandtable[nr_bandtable_size-1].band, "NR band %d exceeds NR bands table maximum limit %d\n", nr_bandP, nr_bandtable[nr_bandtable_size-1].band);
|
||||
for (i = 0; i < nr_bandtable_size && nr_bandtable[i].band != nr_bandP; i++);
|
||||
|
||||
// selection of correct Deltaf raster according to SCS
|
||||
if ((nr_bandtable[i].deltaf_raster != 100) && (nr_bandtable[i].deltaf_raster != scs_khz))
|
||||
@@ -1705,35 +1641,33 @@ int get_nr_table_idx(int nr_bandP, uint8_t scs_index){
|
||||
LOG_D(PHY, "NR band table index %d (Band %d, dl_min %lu, ul_min %lu)\n", i, nr_bandtable[i].band, nr_bandtable[i].dl_min,nr_bandtable[i].ul_min);
|
||||
|
||||
return i;
|
||||
|
||||
}
|
||||
|
||||
// Computes the duplex spacing (either positive or negative) in KHz
|
||||
void get_delta_duplex(int nr_bandP, uint8_t scs_index, int32_t *delta_duplex){
|
||||
|
||||
int32_t get_delta_duplex(int nr_bandP, uint8_t scs_index)
|
||||
{
|
||||
int nr_table_idx = get_nr_table_idx(nr_bandP, scs_index);
|
||||
|
||||
*delta_duplex = (nr_bandtable[nr_table_idx].ul_min - nr_bandtable[nr_table_idx].dl_min);
|
||||
int32_t delta_duplex = (nr_bandtable[nr_table_idx].ul_min - nr_bandtable[nr_table_idx].dl_min);
|
||||
|
||||
LOG_D(PHY, "NR band duplex spacing is %d KHz (nr_bandtable[%d].band = %d)\n", *delta_duplex, nr_table_idx, nr_bandtable[nr_table_idx].band);
|
||||
LOG_I(PHY, "NR band duplex spacing is %d KHz (nr_bandtable[%d].band = %d)\n", delta_duplex, nr_table_idx, nr_bandtable[nr_table_idx].band);
|
||||
|
||||
return delta_duplex;
|
||||
}
|
||||
|
||||
void get_frame_type(uint16_t current_band,
|
||||
uint8_t scs_index,
|
||||
lte_frame_type_t *current_type){
|
||||
lte_frame_type_t get_frame_type(uint16_t current_band, uint8_t scs_index)
|
||||
{
|
||||
lte_frame_type_t current_type;
|
||||
int32_t delta_duplex = get_delta_duplex(current_band, scs_index);
|
||||
|
||||
int32_t current_offset;
|
||||
get_delta_duplex(current_band, scs_index, ¤t_offset);
|
||||
|
||||
current_offset *= 1000;
|
||||
if (current_offset == 0)
|
||||
*current_type = TDD;
|
||||
if (delta_duplex == 0)
|
||||
current_type = TDD;
|
||||
else
|
||||
*current_type = FDD;
|
||||
current_type = FDD;
|
||||
|
||||
LOG_I(MAC, "NR band %d, duplex mode %s, duplex spacing = %d KHz\n", current_band, duplex_mode[*current_type], current_offset);
|
||||
LOG_I(MAC, "NR band %d, duplex mode %s, duplex spacing = %d KHz\n", current_band, duplex_mode[current_type], delta_duplex);
|
||||
|
||||
return current_type;
|
||||
}
|
||||
|
||||
uint16_t config_bandwidth(int mu, int nb_rb, int nr_band)
|
||||
@@ -1911,7 +1845,6 @@ uint64_t from_nrarfcn(int nr_bandP,
|
||||
int deltaFglobal = 5;
|
||||
uint32_t N_REF_Offs = 0;
|
||||
uint64_t F_REF_Offs_khz = 0;
|
||||
int32_t delta_duplex;
|
||||
uint64_t N_OFFs, frequency, freq_min;
|
||||
int i = get_nr_table_idx(nr_bandP, scs_index);
|
||||
|
||||
@@ -1926,7 +1859,7 @@ uint64_t from_nrarfcn(int nr_bandP,
|
||||
F_REF_Offs_khz = 24250080;
|
||||
}
|
||||
|
||||
get_delta_duplex(nr_bandP, scs_index, &delta_duplex);
|
||||
int32_t delta_duplex = get_delta_duplex(nr_bandP, scs_index);
|
||||
|
||||
if (delta_duplex <= 0){ // DL band >= UL band
|
||||
if (nrarfcn >= nr_bandtable[i].N_OFFs_DL){ // is TDD of FDD DL
|
||||
@@ -2836,11 +2769,15 @@ int is_nr_DL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slot) {
|
||||
else return(slot_in_period <= slots1+scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots ? 1 : 0);
|
||||
}
|
||||
|
||||
int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slot) {
|
||||
int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc, slot_t slot, lte_frame_type_t frame_type) {
|
||||
|
||||
int period,period1,period2=0;
|
||||
|
||||
if (scc->tdd_UL_DL_ConfigurationCommon==NULL) return(1);
|
||||
// Note: condition on frame_type
|
||||
// goal: the UL scheduler assumes mode is TDD therefore this hack is needed to make FDD work
|
||||
if (scc->tdd_UL_DL_ConfigurationCommon == NULL || frame_type == FDD) {
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1 &&
|
||||
scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530)
|
||||
@@ -3067,48 +3004,6 @@ bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config,
|
||||
//printf("[MAC] PTRS is set K= %u L= %u\n", *K_ptrs,1<<*L_ptrs);
|
||||
return valid;
|
||||
}
|
||||
void get_band(uint64_t downlink_frequency,
|
||||
uint16_t *current_band,
|
||||
int32_t *current_offset,
|
||||
lte_frame_type_t *current_type)
|
||||
{
|
||||
int ind;
|
||||
uint64_t center_frequency_khz;
|
||||
uint64_t center_freq_diff_khz;
|
||||
uint64_t dl_freq_khz = downlink_frequency/1000;
|
||||
|
||||
center_freq_diff_khz = 999999999999999999; // 2^64
|
||||
*current_band = 0;
|
||||
|
||||
for ( ind=0;
|
||||
ind < sizeof(nr_bandtable) / sizeof(nr_bandtable[0]);
|
||||
ind++) {
|
||||
|
||||
LOG_I(PHY, "Scanning band %d, dl_min %"PRIu64", ul_min %"PRIu64"\n", nr_bandtable[ind].band, nr_bandtable[ind].dl_min,nr_bandtable[ind].ul_min);
|
||||
|
||||
if ( nr_bandtable[ind].dl_min <= dl_freq_khz && nr_bandtable[ind].dl_max >= dl_freq_khz ) {
|
||||
|
||||
center_frequency_khz = (nr_bandtable[ind].dl_max + nr_bandtable[ind].dl_min)/2;
|
||||
if (abs(dl_freq_khz - center_frequency_khz) < center_freq_diff_khz){
|
||||
*current_band = nr_bandtable[ind].band;
|
||||
*current_offset = (nr_bandtable[ind].ul_min - nr_bandtable[ind].dl_min)*1000;
|
||||
center_freq_diff_khz = abs(dl_freq_khz - center_frequency_khz);
|
||||
|
||||
if (*current_offset == 0)
|
||||
*current_type = TDD;
|
||||
else
|
||||
*current_type = FDD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG_I( PHY, "DL frequency %"PRIu64": band %d, frame_type %d, UL frequency %"PRIu64"\n",
|
||||
downlink_frequency, *current_band, *current_type, downlink_frequency+*current_offset);
|
||||
|
||||
AssertFatal(*current_band != 0,
|
||||
"Can't find EUTRA band for frequency %lu\n", downlink_frequency);
|
||||
}
|
||||
|
||||
|
||||
uint32_t get_ssb_slot(uint32_t ssb_index){
|
||||
// this function now only support f <= 3GHz
|
||||
|
||||
@@ -39,9 +39,9 @@
|
||||
|
||||
uint16_t config_bandwidth(int mu, int nb_rb, int nr_band);
|
||||
|
||||
void get_frame_type(uint16_t nr_bandP, uint8_t scs_index, lte_frame_type_t *current_type);
|
||||
lte_frame_type_t get_frame_type(uint16_t nr_bandP, uint8_t scs_index);
|
||||
|
||||
void get_delta_duplex(int nr_bandP, uint8_t scs_index, int32_t *delta_duplex);
|
||||
int32_t get_delta_duplex(int nr_bandP, uint8_t scs_index);
|
||||
|
||||
uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t dl_nrarfcn);
|
||||
|
||||
@@ -51,7 +51,7 @@ int16_t fill_dmrs_mask(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,i
|
||||
|
||||
int is_nr_DL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP);
|
||||
|
||||
int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP);
|
||||
int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc, slot_t slotP, lte_frame_type_t frame_type);
|
||||
|
||||
uint16_t nr_dci_size(const NR_ServingCellConfigCommon_t *scc,
|
||||
const NR_CellGroupConfig_t *secondaryCellGroup,
|
||||
@@ -140,7 +140,6 @@ bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config,
|
||||
uint8_t *K_ptrs, uint8_t *L_ptrs,uint8_t *portIndex,
|
||||
uint8_t *nERatio,uint8_t *reOffset,
|
||||
uint8_t NrOfSymbols);
|
||||
void get_band(uint64_t downlink_frequency, uint16_t *current_band, int32_t *current_offset, lte_frame_type_t *current_type);
|
||||
|
||||
uint8_t get_num_dmrs_symbols(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols);
|
||||
|
||||
|
||||
@@ -203,13 +203,12 @@ void config_common_ue(NR_UE_MAC_INST_t *mac,
|
||||
uint32_t band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
|
||||
frequency_range_t frequency_range = band<100?FR1:FR2;
|
||||
|
||||
lte_frame_type_t frame_type;
|
||||
get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing, &frame_type);
|
||||
mac->frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing);
|
||||
|
||||
// cell config
|
||||
|
||||
cfg->cell_config.phy_cell_id = *scc->physCellId;
|
||||
cfg->cell_config.frame_duplex_type = frame_type;
|
||||
cfg->cell_config.frame_duplex_type = mac->frame_type;
|
||||
|
||||
// SSB config
|
||||
cfg->ssb_config.ss_pbch_power = scc->ss_PBCH_BlockPower;
|
||||
@@ -313,7 +312,7 @@ void config_common_ue(NR_UE_MAC_INST_t *mac,
|
||||
|
||||
cfg->prach_config.num_prach_fd_occasions_list[i].k1 = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart;
|
||||
cfg->prach_config.num_prach_fd_occasions_list[i].prach_zero_corr_conf = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig;
|
||||
cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup, nb_preambles, frame_type,frequency_range);
|
||||
cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup, nb_preambles, mac->frame_type, frequency_range);
|
||||
//cfg->prach_config.num_prach_fd_occasions_list[i].num_unused_root_sequences = ???
|
||||
}
|
||||
|
||||
|
||||
@@ -325,6 +325,8 @@ typedef struct {
|
||||
NR_ControlResourceSet_t *coreset[MAX_NUM_BWP][FAPI_NR_MAX_CORESET_PER_BWP];
|
||||
NR_SearchSpace_t *SSpace[MAX_NUM_BWP][FAPI_NR_MAX_CORESET_PER_BWP][FAPI_NR_MAX_SS_PER_CORESET];
|
||||
|
||||
lte_frame_type_t frame_type;
|
||||
|
||||
/*BWP*/
|
||||
// dedicated active DL BWP
|
||||
NR_BWP_Id_t DL_BWP_Id;
|
||||
|
||||
@@ -56,14 +56,14 @@ int8_t nr_ue_decode_mib(
|
||||
void *pduP,
|
||||
uint16_t cell_id );
|
||||
|
||||
/**\brief decode sib1 pdu in NR_UE, from if_module dl_ind
|
||||
/**\brief decode SIB1 and other SIs pdus in NR_UE, from if_module dl_ind
|
||||
\param module_id module id
|
||||
\param cc_id component carrier id
|
||||
\param gNB_index gNB index
|
||||
\param sibs_mask sibs mask
|
||||
\param pduP pointer to pdu
|
||||
\param pdu_length length of pdu */
|
||||
int8_t nr_ue_decode_sib1(module_id_t module_id,
|
||||
int8_t nr_ue_decode_BCCH_DL_SCH(module_id_t module_id,
|
||||
int cc_id,
|
||||
unsigned int gNB_index,
|
||||
uint32_t sibs_mask,
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
const char *rnti_types[]={"RNTI_new", "RNTI_C", "RNTI_RA", "NR_RNTI_P", "NR_RNTI_CS", "NR_RNTI_TC"};
|
||||
const char *rnti_types[]={"RNTI_new", "RNTI_C", "RNTI_RA", "NR_RNTI_P", "NR_RNTI_CS", "NR_RNTI_TC", "NR_RNTI_SP_CSI", "NR_RNTI_SI"};
|
||||
const char *dci_formats[]={"1_0", "1_1", "2_0", "2_1", "2_2", "2_3", "0_0", "0_1"};
|
||||
|
||||
// table_7_3_1_1_2_2_3_4_5 contains values for number of layers and precoding information for tables 7.3.1.1.2-2/3/4/5 from TS 38.212 subclause 7.3.1.1.2
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
/* RRC */
|
||||
#include "NR_RACH-ConfigCommon.h"
|
||||
#include "RRC/NR_UE/rrc_proto.h"
|
||||
|
||||
/* PHY */
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
@@ -514,7 +515,8 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
|
||||
|
||||
uint8_t sdu_lcids[NB_RB_MAX] = {0};
|
||||
uint16_t sdu_lengths[NB_RB_MAX] = {0};
|
||||
int TBS_bytes = 848, header_length_total=0, num_sdus, offset, mac_ce_len;
|
||||
int num_sdus = 0;
|
||||
int offset = 0;
|
||||
|
||||
// Delay init RA procedure to allow the convergence of the IIR filter on PRACH noise measurements at gNB side
|
||||
if (!prach_resources->init_msg1) {
|
||||
@@ -532,36 +534,27 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
|
||||
|
||||
LOG_D(MAC, "RA not active. Checking for data to transmit from upper layers...\n");
|
||||
|
||||
payload = (uint8_t*) &mac->CCCH_pdu.payload;
|
||||
mac_ce_len = 0;
|
||||
uint8_t TBS_max = 8 + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT);
|
||||
payload = (uint8_t*) mac->CCCH_pdu.payload;
|
||||
|
||||
num_sdus = 1;
|
||||
post_padding = 1;
|
||||
sdu_lcids[0] = lcid;
|
||||
|
||||
if (0){
|
||||
// initialisation by RRC
|
||||
// CCCH PDU
|
||||
// size_sdu = (uint16_t) mac_rrc_data_req_ue(mod_id,
|
||||
// CC_id,
|
||||
// frame,
|
||||
// CCCH,
|
||||
// 1,
|
||||
// mac_sdus,
|
||||
// gNB_id,
|
||||
// 0);
|
||||
LOG_D(MAC,"[UE %d] Frame %d: Requested RRCConnectionRequest, got %d bytes\n", mod_id, frame, size_sdu);
|
||||
} else {
|
||||
// fill ulsch_buffer with random data
|
||||
for (int i = 0; i < TBS_bytes; i++){
|
||||
mac_sdus[i] = (unsigned char) (lrand48()&0xff);
|
||||
}
|
||||
//Sending SDUs with size 1
|
||||
//Initialize elements of sdu_lcids and sdu_lengths
|
||||
sdu_lcids[0] = lcid;
|
||||
sdu_lengths[0] = TBS_bytes - 3 - post_padding - mac_ce_len;
|
||||
header_length_total += 2 + (sdu_lengths[0] >= 128);
|
||||
size_sdu += sdu_lengths[0];
|
||||
// initialisation by RRC
|
||||
|
||||
// TODO: To be removed after RA procedures fully implemented
|
||||
if(get_softmodem_params()->do_ra) {
|
||||
nr_rrc_ue_generate_RRCSetupRequest(mod_id,gNB_id);
|
||||
}
|
||||
|
||||
// CCCH PDU
|
||||
size_sdu = (uint16_t) nr_mac_rrc_data_req_ue(mod_id, CC_id, gNB_id, frame, CCCH, mac_sdus);
|
||||
|
||||
sdu_lengths[0] = size_sdu;
|
||||
|
||||
LOG_D(MAC,"[UE %d] Frame %d: Requested RRCConnectionRequest, got %d bytes\n", mod_id, frame, size_sdu);
|
||||
|
||||
if (size_sdu > 0) {
|
||||
|
||||
LOG_D(MAC, "[UE %d][%d.%d]: starting initialisation Random Access Procedure...\n", mod_id, frame, nr_slot_tx);
|
||||
@@ -589,12 +582,27 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
|
||||
post_padding,
|
||||
0);
|
||||
|
||||
AssertFatal(TBS_max > offset, "Frequency resources are not enough for Msg3!\n");
|
||||
|
||||
// Padding: fill remainder with 0
|
||||
if (post_padding > 0){
|
||||
for (int j = 0; j < (TBS_bytes - offset); j++)
|
||||
payload[offset + j] = 0; // mac_pdu[offset + j] = 0;
|
||||
for (int j = 0; j < (TBS_max - offset); j++)
|
||||
payload[offset + j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG_D(MAC,"size_sdu = %i\n", size_sdu);
|
||||
LOG_D(MAC,"offset = %i\n", offset);
|
||||
for(int k = 0; k < TBS_max; k++) {
|
||||
LOG_D(MAC,"(%i): %i\n", k, prach_resources->Msg3[k]);
|
||||
}
|
||||
|
||||
// Msg3 was initialized with TBS_max bytes because the RA_Msg3_size will only be known after
|
||||
// receiving Msg2 (which contains the Msg3 resource reserve).
|
||||
// Msg3 will be transmitted with RA_Msg3_size bytes, removing unnecessary 0s.
|
||||
mac->ulsch_pdu.Pdu_size = TBS_max;
|
||||
memcpy(mac->ulsch_pdu.payload, prach_resources->Msg3, TBS_max);
|
||||
|
||||
} else if (ra->RA_window_cnt != -1) { // RACH is active
|
||||
|
||||
LOG_D(MAC, "In %s [%d.%d] RA is active: RA window count %d, RA backoff count %d\n", __FUNCTION__, frame, nr_slot_tx, ra->RA_window_cnt, ra->RA_backoff_cnt);
|
||||
|
||||
@@ -154,13 +154,13 @@ int8_t nr_ue_decode_mib(module_id_t module_id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t nr_ue_decode_sib1(module_id_t module_id,
|
||||
int cc_id,
|
||||
unsigned int gNB_index,
|
||||
uint32_t sibs_mask,
|
||||
uint8_t *pduP,
|
||||
uint32_t pdu_len) {
|
||||
LOG_D(MAC, "Decode sib1\n");
|
||||
int8_t nr_ue_decode_BCCH_DL_SCH(module_id_t module_id,
|
||||
int cc_id,
|
||||
unsigned int gNB_index,
|
||||
uint32_t sibs_mask,
|
||||
uint8_t *pduP,
|
||||
uint32_t pdu_len) {
|
||||
LOG_D(NR_MAC, "Decoding NR-BCCH-DL-SCH-Message (SIB1 or SI)\n");
|
||||
nr_mac_rrc_data_ind_ue(module_id, cc_id, gNB_index, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len);
|
||||
return 0;
|
||||
}
|
||||
@@ -814,7 +814,17 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
|
||||
|
||||
dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH;
|
||||
dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.rnti = rnti;
|
||||
|
||||
// FIXME: fix number of additional dmrs
|
||||
if(pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition == NULL)
|
||||
pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition=calloc(1,sizeof(*pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition));
|
||||
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu_1_1 = &dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.dlsch_config_rel15;
|
||||
|
||||
dlsch_config_pdu_1_1->BWPSize = NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
dlsch_config_pdu_1_1->BWPStart = NRRIV2PRBOFFSET(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
dlsch_config_pdu_1_1->SubcarrierSpacing = mac->DLbwp[0]->bwp_Common->genericParameters.subcarrierSpacing;
|
||||
|
||||
/* IDENTIFIER_DCI_FORMATS */
|
||||
/* CARRIER_IND */
|
||||
/* BANDWIDTH_PART_IND */
|
||||
@@ -2230,7 +2240,7 @@ int nr_ue_process_rar(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t
|
||||
|
||||
// TA command
|
||||
ul_time_alignment->apply_ta = 1;
|
||||
ul_time_alignment->ta_command = rar->TA2 + (rar->TA1 << 5);
|
||||
ul_time_alignment->ta_command = 31 + rar->TA2 + (rar->TA1 << 5);
|
||||
|
||||
#ifdef DEBUG_RAR
|
||||
// CSI
|
||||
|
||||
@@ -118,13 +118,14 @@ long get_k2(NR_UE_MAC_INST_t *mac, uint8_t time_domain_ind) {
|
||||
* This function returns the UL config corresponding to a given UL slot
|
||||
* from MAC instance .
|
||||
*/
|
||||
fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int slot) {
|
||||
fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int slot)
|
||||
{
|
||||
//Check if request to access ul_config is for a UL slot
|
||||
if (is_nr_UL_slot(mac->scc, slot) == 0) {
|
||||
if (is_nr_UL_slot(mac->scc, slot, mac->frame_type) == 0) {
|
||||
LOG_W(MAC, "Slot %d is not a UL slot. %s called for wrong slot!!!\n", slot, __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// Calculate the index of the UL slot in mac->ul_config_request list. This is
|
||||
// based on the TDD pattern (slot configuration period) and number of UL+mixed
|
||||
// slots in the period. TS 38.213 Sec 11.1
|
||||
@@ -889,34 +890,40 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
|
||||
|
||||
uint16_t TBS_bytes = ulcfg_pdu->pusch_config_pdu.pusch_data.tb_size;
|
||||
|
||||
// Push data from MAC to PHY only when NDI toggles
|
||||
if (IS_SOFTMODEM_NOS1 && (mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] != ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator)){
|
||||
// Getting IP traffic to be transmitted
|
||||
data_existing = nr_ue_get_sdu(mod_id,
|
||||
cc_id,
|
||||
frame_tx,
|
||||
slot_tx,
|
||||
0,
|
||||
ulsch_input_buffer,
|
||||
TBS_bytes,
|
||||
&access_mode);
|
||||
}
|
||||
if (ra->ra_state == WAIT_RAR){
|
||||
memcpy(ulsch_input_buffer, mac->ulsch_pdu.payload, TBS_bytes);
|
||||
LOG_D(NR_MAC,"[RAPROC] Msg3 to be transmitted:\n");
|
||||
for (int k = 0; k < TBS_bytes; k++) {
|
||||
LOG_D(NR_MAC,"(%i): 0x%x\n",k,mac->ulsch_pdu.payload[k]);
|
||||
}
|
||||
} else {
|
||||
if (IS_SOFTMODEM_NOS1 && (mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] != ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator)){
|
||||
// Getting IP traffic to be transmitted
|
||||
data_existing = nr_ue_get_sdu(mod_id,
|
||||
cc_id,
|
||||
frame_tx,
|
||||
slot_tx,
|
||||
0,
|
||||
ulsch_input_buffer,
|
||||
TBS_bytes,
|
||||
&access_mode);
|
||||
}
|
||||
|
||||
mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator;
|
||||
//Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity
|
||||
if (!IS_SOFTMODEM_NOS1 || !data_existing) {
|
||||
//Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid
|
||||
//and block this traffic from being forwarded to the upper layers at the gNB
|
||||
LOG_D(PHY, "In %s: Random data to be transmitted: TBS_bytes %d \n", __FUNCTION__, TBS_bytes);
|
||||
mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator;
|
||||
//Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity
|
||||
if (!IS_SOFTMODEM_NOS1 || !data_existing) {
|
||||
//Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid
|
||||
//and block this traffic from being forwarded to the upper layers at the gNB
|
||||
LOG_D(PHY, "In %s: Random data to be transmitted: TBS_bytes %d \n", __FUNCTION__, TBS_bytes);
|
||||
|
||||
//Give the first byte a dummy value (a value not corresponding to any valid LCID based on 38.321, Table 6.2.1-2)
|
||||
//in order to distinguish the PHY random packets at the MAC layer of the gNB receiver from the normal packets that should
|
||||
//have a valid LCID (nr_process_mac_pdu function)
|
||||
ulsch_input_buffer[0] = 0x31;
|
||||
//Give the first byte a dummy value (a value not corresponding to any valid LCID based on 38.321, Table 6.2.1-2)
|
||||
//in order to distinguish the PHY random packets at the MAC layer of the gNB receiver from the normal packets that should
|
||||
//have a valid LCID (nr_process_mac_pdu function)
|
||||
ulsch_input_buffer[0] = 0x31;
|
||||
|
||||
for (int i = 1; i < TBS_bytes; i++) {
|
||||
ulsch_input_buffer[i] = (unsigned char) rand();
|
||||
//printf(" input encoder a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]);
|
||||
for (int i = 1; i < TBS_bytes; i++) {
|
||||
ulsch_input_buffer[i] = (unsigned char) rand();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1662,7 +1669,7 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s
|
||||
ra->RA_offset = 2; // to compensate the rx frame offset at the gNB
|
||||
ra->generate_nr_prach = 0; // Reset flag for PRACH generation
|
||||
|
||||
if (is_nr_UL_slot(scc, slotP)) {
|
||||
if (is_nr_UL_slot(scc, slotP, mac->frame_type)) {
|
||||
|
||||
// WIP Need to get the proper selected ssb_idx
|
||||
// Initial beam selection functionality is not available yet
|
||||
@@ -1683,13 +1690,11 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s
|
||||
format0 = format & 0xff; // single PRACH format
|
||||
format1 = (format >> 8) & 0xff; // dual PRACH format
|
||||
|
||||
ul_config->sfn = frameP;
|
||||
ul_config->slot = slotP;
|
||||
|
||||
ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PRACH;
|
||||
prach_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].prach_config_pdu;
|
||||
memset(prach_config_pdu, 0, sizeof(fapi_nr_ul_config_prach_pdu));
|
||||
ul_config->number_pdus += 1;
|
||||
|
||||
fill_ul_config(ul_config, frameP, slotP, FAPI_NR_UL_CONFIG_TYPE_PRACH);
|
||||
|
||||
LOG_D(PHY, "In %s: (%p) %d UL PDUs:\n", __FUNCTION__, ul_config, ul_config->number_pdus);
|
||||
|
||||
ncs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, setup->restrictedSetConfig);
|
||||
@@ -1767,11 +1772,10 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s
|
||||
AssertFatal(1 == 0, "Invalid PRACH format");
|
||||
}
|
||||
} // if format1
|
||||
fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, module_idP, 0 /*TBR fix*/, frameP, slotP, thread_id);
|
||||
if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL)
|
||||
mac->if_module->scheduled_response(&scheduled_response);
|
||||
} // is_nr_prach_slot
|
||||
|
||||
fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, module_idP, 0 /*TBR fix*/, frameP, slotP, thread_id);
|
||||
if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL)
|
||||
mac->if_module->scheduled_response(&scheduled_response);
|
||||
} // if is_nr_UL_slot
|
||||
}
|
||||
|
||||
|
||||
@@ -127,8 +127,7 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm
|
||||
uint32_t band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
|
||||
frequency_range_t frequency_range = band<100?FR1:FR2;
|
||||
|
||||
lte_frame_type_t frame_type;
|
||||
get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing, &frame_type);
|
||||
lte_frame_type_t frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing);
|
||||
RC.nrmac[Mod_idP]->common_channels[0].frame_type = frame_type;
|
||||
|
||||
// Cell configuration
|
||||
|
||||
@@ -364,7 +364,9 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
/* send tick to RLC and RRC every ms */
|
||||
if ((slot & ((1 << *scc->ssbSubcarrierSpacing) - 1)) == 0) {
|
||||
void nr_rlc_tick(int frame, int subframe);
|
||||
void nr_pdcp_tick(int frame, int subframe);
|
||||
nr_rlc_tick(frame, slot >> *scc->ssbSubcarrierSpacing);
|
||||
nr_pdcp_tick(frame, slot >> *scc->ssbSubcarrierSpacing);
|
||||
nr_rrc_trigger(&ctxt, 0 /*CC_id*/, frame, slot >> *scc->ssbSubcarrierSpacing);
|
||||
}
|
||||
|
||||
|
||||
@@ -245,7 +245,8 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP
|
||||
nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[0][slotP];
|
||||
nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0];
|
||||
|
||||
if (is_nr_UL_slot(scc,slotP)) {
|
||||
if (is_nr_UL_slot(scc, slotP, cc->frame_type)) {
|
||||
|
||||
uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
|
||||
uint8_t mu,N_dur,N_t_slot,start_symbol = 0,N_RA_slot;
|
||||
uint16_t RA_sfn_index = -1;
|
||||
@@ -647,7 +648,8 @@ void nr_get_Msg3alloc(module_id_t module_id,
|
||||
NR_RA_t *ra) {
|
||||
|
||||
// msg3 is schedulend in mixed slot in the following TDD period
|
||||
// for now we consider a TBS of 18 bytes
|
||||
|
||||
uint16_t msg3_nb_rb = 8 + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT); // sdu has 6 or 8 bytes
|
||||
|
||||
int mu = ubwp->bwp_Common->genericParameters.subcarrierSpacing;
|
||||
int StartSymbolIndex, NrOfSymbols, startSymbolAndLength, temp_slot;
|
||||
@@ -677,21 +679,22 @@ void nr_get_Msg3alloc(module_id_t module_id,
|
||||
uint16_t *vrb_map_UL =
|
||||
&RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[ra->Msg3_slot * MAX_BWP_SIZE];
|
||||
const uint16_t bwpSize = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
/* search 18 free RBs */
|
||||
|
||||
/* search msg3_nb_rb free RBs */
|
||||
int rbSize = 0;
|
||||
int rbStart = 0;
|
||||
while (rbSize < 18) {
|
||||
while (rbSize < msg3_nb_rb) {
|
||||
rbStart += rbSize; /* last iteration rbSize was not enough, skip it */
|
||||
rbSize = 0;
|
||||
while (rbStart < bwpSize && vrb_map_UL[rbStart])
|
||||
rbStart++;
|
||||
AssertFatal(rbStart < bwpSize - 18, "no space to allocate Msg 3 for RA!\n");
|
||||
AssertFatal(rbStart < bwpSize - msg3_nb_rb, "no space to allocate Msg 3 for RA!\n");
|
||||
while (rbStart + rbSize < bwpSize
|
||||
&& !vrb_map_UL[rbStart + rbSize]
|
||||
&& rbSize < 18)
|
||||
&& rbSize < msg3_nb_rb)
|
||||
rbSize++;
|
||||
}
|
||||
ra->msg3_nb_rb = 18;
|
||||
ra->msg3_nb_rb = msg3_nb_rb;
|
||||
ra->msg3_first_rb = rbStart;
|
||||
}
|
||||
|
||||
|
||||
@@ -235,6 +235,7 @@ void schedule_control_sib1(module_id_t module_id,
|
||||
int time_domain_allocation,
|
||||
uint8_t mcsTableIdx,
|
||||
uint8_t mcs,
|
||||
uint8_t candidate_idx,
|
||||
int num_total_bytes) {
|
||||
|
||||
gNB_MAC_INST *gNB_mac = RC.nrmac[module_id];
|
||||
@@ -266,13 +267,10 @@ void schedule_control_sib1(module_id_t module_id,
|
||||
gNB_mac->sched_ctrlCommon->coreset,
|
||||
gNB_mac->sched_ctrlCommon->aggregation_level,
|
||||
0,
|
||||
0,
|
||||
candidate_idx,
|
||||
nr_of_candidates);
|
||||
|
||||
if (gNB_mac->sched_ctrlCommon->cce_index < 0) {
|
||||
LOG_E(MAC, "%s(): could not find CCE for coreset0\n", __func__);
|
||||
return;
|
||||
}
|
||||
AssertFatal(gNB_mac->sched_ctrlCommon->cce_index >= 0, "Could not find CCE for coreset0\n");
|
||||
|
||||
const uint16_t bwpSize = gNB_mac->type0_PDCCH_CSS_config.num_rbs;
|
||||
int rbStart = gNB_mac->type0_PDCCH_CSS_config.cset_start_rb;
|
||||
@@ -301,9 +299,7 @@ void schedule_control_sib1(module_id_t module_id,
|
||||
TBS = nr_compute_tbs(nr_get_Qm_dl(gNB_mac->sched_ctrlCommon->mcs, gNB_mac->sched_ctrlCommon->mcsTableIdx),
|
||||
nr_get_code_rate_dl(gNB_mac->sched_ctrlCommon->mcs, gNB_mac->sched_ctrlCommon->mcsTableIdx),
|
||||
rbSize, nrOfSymbols, N_PRB_DMRS * dmrs_length,0, 0,1) >> 3;
|
||||
|
||||
// FIXME: Something is not working in nr_modulation() for TBS = 84, so we need to skip it
|
||||
} while ( (rbStart + rbSize < bwpSize && !vrb_map[rbStart + rbSize] && TBS < gNB_mac->sched_ctrlCommon->num_total_bytes) || (TBS==84) );
|
||||
} while (rbStart + rbSize < bwpSize && !vrb_map[rbStart + rbSize] && TBS < gNB_mac->sched_ctrlCommon->num_total_bytes);
|
||||
|
||||
gNB_mac->sched_ctrlCommon->rbSize = rbSize;
|
||||
gNB_mac->sched_ctrlCommon->rbStart = 0;
|
||||
@@ -467,6 +463,7 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
|
||||
int time_domain_allocation = 0;
|
||||
uint8_t mcsTableIdx = 0;
|
||||
uint8_t mcs = 6;
|
||||
uint8_t candidate_idx = 0;
|
||||
|
||||
gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP];
|
||||
|
||||
@@ -482,7 +479,7 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
|
||||
for (int i=0;i<sib1_sdu_length;i++) LOG_D(MAC,"byte %d : %x\n",i,((uint8_t*)sib1_payload)[i]);
|
||||
|
||||
// Configure sched_ctrlCommon for SIB1
|
||||
schedule_control_sib1(module_idP, CC_id, time_domain_allocation, mcsTableIdx, mcs, sib1_sdu_length);
|
||||
schedule_control_sib1(module_idP, CC_id, time_domain_allocation, mcsTableIdx, mcs, candidate_idx, sib1_sdu_length);
|
||||
|
||||
// Calculate number of symbols
|
||||
int startSymbolIndex, nrOfSymbols;
|
||||
|
||||
@@ -1045,7 +1045,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
size += 3;
|
||||
}
|
||||
}
|
||||
else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra) {
|
||||
else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra || get_softmodem_params()->sa) {
|
||||
/* we will need the large header, phy-test typically allocates all
|
||||
* resources and fills to the last byte below */
|
||||
NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf;
|
||||
|
||||
@@ -395,7 +395,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
T_BUFFER(sduP, sdu_lenP));
|
||||
|
||||
UE_info->mac_stats[UE_id].ulsch_total_bytes_rx += sdu_lenP;
|
||||
LOG_D(MAC, "[gNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu from PHY (rnti %x, UE_id %d) ul_cqi %d sduP %p\n",
|
||||
LOG_D(NR_MAC, "[gNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu from PHY (rnti %x, UE_id %d) ul_cqi %d sduP %p\n",
|
||||
gnb_mod_idP,
|
||||
harq_pid,
|
||||
CC_idP,
|
||||
@@ -412,7 +412,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
if (timing_advance != 0xffff)
|
||||
UE_scheduling_control->ta_update = timing_advance;
|
||||
UE_scheduling_control->ul_rssi = rssi;
|
||||
LOG_D(MAC, "[UE %d] PUSCH TPC %d and TA %d\n",UE_id,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update);
|
||||
LOG_D(NR_MAC, "[UE %d] PUSCH TPC %d and TA %d\n",UE_id,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update);
|
||||
}
|
||||
else{
|
||||
UE_scheduling_control->tpc0 = 1;
|
||||
@@ -431,7 +431,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
#endif
|
||||
|
||||
if (sduP != NULL){
|
||||
LOG_D(MAC, "Received PDU at MAC gNB \n");
|
||||
LOG_D(NR_MAC, "Received PDU at MAC gNB \n");
|
||||
|
||||
const uint32_t tb_size = UE_scheduling_control->ul_harq_processes[harq_pid].sched_pusch.tb_size;
|
||||
UE_scheduling_control->sched_ul_bytes -= tb_size;
|
||||
@@ -468,7 +468,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
|
||||
// random access pusch with TC-RNTI
|
||||
if (ra->rnti != current_rnti) {
|
||||
LOG_W(MAC,
|
||||
LOG_W(NR_MAC,
|
||||
"expected TC-RNTI %04x to match current RNTI %04x\n",
|
||||
ra->rnti,
|
||||
current_rnti);
|
||||
@@ -476,19 +476,25 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
}
|
||||
const int UE_id = add_new_nr_ue(gnb_mod_idP, ra->rnti, ra->secondaryCellGroup);
|
||||
UE_info->UE_beam_index[UE_id] = ra->beam_id;
|
||||
LOG_I(MAC,
|
||||
LOG_I(NR_MAC,
|
||||
"[gNB %d][RAPROC] PUSCH with TC_RNTI %x received correctly, "
|
||||
"adding UE MAC Context UE_id %d/RNTI %04x\n",
|
||||
gnb_mod_idP,
|
||||
current_rnti,
|
||||
UE_id,
|
||||
ra->rnti);
|
||||
|
||||
LOG_D(NR_MAC,"[RAPROC] Received Msg3:\n");
|
||||
for (int k = 0; k < sdu_lenP; k++) {
|
||||
LOG_D(NR_MAC,"(%i): 0x%x\n",k,sduP[k]);
|
||||
}
|
||||
|
||||
// re-initialize ta update variables afrer RA procedure completion
|
||||
UE_info->UE_sched_ctrl[UE_id].ta_frame = frameP;
|
||||
|
||||
free(ra->preambles.preamble_list);
|
||||
ra->state = RA_IDLE;
|
||||
LOG_I(MAC,
|
||||
LOG_I(NR_MAC,
|
||||
"reset RA state information for RA-RNTI %04x/index %d\n",
|
||||
ra->rnti,
|
||||
i);
|
||||
|
||||
@@ -73,6 +73,7 @@ void schedule_control_sib1(module_id_t module_id,
|
||||
int time_domain_allocation,
|
||||
uint8_t mcsTableIdx,
|
||||
uint8_t mcs,
|
||||
uint8_t candidate_idx,
|
||||
int num_total_bytes);
|
||||
|
||||
void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP);
|
||||
|
||||
@@ -96,7 +96,7 @@ void mac_top_init_gNB(void)
|
||||
// These should be out of here later
|
||||
pdcp_layer_init();
|
||||
|
||||
if(IS_SOFTMODEM_NOS1 && !get_softmodem_params()->do_ra)
|
||||
if(IS_SOFTMODEM_NOS1 && !(get_softmodem_params()->do_ra || get_softmodem_params()->sa) )
|
||||
nr_DRB_preconfiguration(0x1234);
|
||||
|
||||
rrc_init_nr_global_param();
|
||||
|
||||
@@ -21,24 +21,222 @@
|
||||
|
||||
#include "nr_pdcp_entity.h"
|
||||
|
||||
#include "nr_pdcp_entity_drb_am.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nr_pdcp_security_nea2.h"
|
||||
#include "nr_pdcp_sdu.h"
|
||||
|
||||
#include "LOG/log.h"
|
||||
|
||||
nr_pdcp_entity_t *new_nr_pdcp_entity_srb(
|
||||
int is_gnb, int rb_id,
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
|
||||
char *buf, int size),
|
||||
void *deliver_sdu_data,
|
||||
void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity,
|
||||
char *buf, int size, int sdu_id),
|
||||
void *deliver_pdu_data)
|
||||
static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity,
|
||||
char *_buffer, int size)
|
||||
{
|
||||
abort();
|
||||
unsigned char *buffer = (unsigned char *)_buffer;
|
||||
nr_pdcp_sdu_t *sdu;
|
||||
int rcvd_sn;
|
||||
uint32_t rcvd_hfn;
|
||||
uint32_t rcvd_count;
|
||||
int header_size;
|
||||
int integrity_size;
|
||||
int rx_deliv_sn;
|
||||
uint32_t rx_deliv_hfn;
|
||||
|
||||
if (size < 1) {
|
||||
LOG_E(PDCP, "bad PDU received (size = %d)\n", size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(buffer[0] & 0x80)) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (entity->sn_size == 12) {
|
||||
rcvd_sn = (((unsigned char)buffer[0] & 0xf) << 8) |
|
||||
(unsigned char)buffer[1];
|
||||
header_size = 2;
|
||||
} else {
|
||||
rcvd_sn = (((unsigned char)buffer[0] & 0x3) << 16) |
|
||||
((unsigned char)buffer[1] << 8) |
|
||||
(unsigned char)buffer[2];
|
||||
header_size = 3;
|
||||
}
|
||||
|
||||
integrity_size = 0;
|
||||
|
||||
if (size < header_size + integrity_size + 1) {
|
||||
LOG_E(PDCP, "bad PDU received (size = %d)\n", size);
|
||||
return;
|
||||
}
|
||||
|
||||
rx_deliv_sn = entity->rx_deliv & entity->sn_max;
|
||||
rx_deliv_hfn = (entity->rx_deliv >> entity->sn_size) & ~entity->sn_max;
|
||||
|
||||
if (rcvd_sn < rx_deliv_sn - entity->window_size) {
|
||||
rcvd_hfn = rx_deliv_hfn + 1;
|
||||
} else if (rcvd_sn >= rx_deliv_sn + entity->window_size) {
|
||||
rcvd_hfn = rx_deliv_hfn - 1;
|
||||
} else {
|
||||
rcvd_hfn = rx_deliv_hfn;
|
||||
}
|
||||
|
||||
rcvd_count = (rcvd_hfn << entity->sn_size) | rcvd_sn;
|
||||
|
||||
if (entity->has_ciphering)
|
||||
entity->cipher(entity->security_context,
|
||||
(unsigned char *)buffer+header_size, size-header_size,
|
||||
entity->rb_id, rcvd_count, entity->is_gnb ? 0 : 1);
|
||||
|
||||
if (rcvd_count < entity->rx_deliv
|
||||
|| nr_pdcp_sdu_in_list(entity->rx_list, rcvd_count)) {
|
||||
LOG_D(PDCP, "discard NR PDU rcvd_count=%d\n", rcvd_count);
|
||||
return;
|
||||
}
|
||||
|
||||
sdu = nr_pdcp_new_sdu(rcvd_count,
|
||||
(char *)buffer + header_size,
|
||||
size - header_size - integrity_size);
|
||||
entity->rx_list = nr_pdcp_sdu_list_add(entity->rx_list, sdu);
|
||||
entity->rx_size += size-header_size;
|
||||
|
||||
if (rcvd_count >= entity->rx_next) {
|
||||
entity->rx_next = rcvd_count + 1;
|
||||
}
|
||||
|
||||
/* TODO(?): out of order delivery */
|
||||
|
||||
if (rcvd_count == entity->rx_deliv) {
|
||||
/* deliver all SDUs starting from rx_deliv up to discontinuity or end of list */
|
||||
uint32_t count = entity->rx_deliv;
|
||||
while (entity->rx_list != NULL && count == entity->rx_list->count) {
|
||||
nr_pdcp_sdu_t *cur = entity->rx_list;
|
||||
entity->deliver_sdu(entity->deliver_sdu_data, entity,
|
||||
cur->buffer, cur->size);
|
||||
entity->rx_list = cur->next;
|
||||
entity->rx_size -= cur->size;
|
||||
nr_pdcp_free_sdu(cur);
|
||||
count++;
|
||||
}
|
||||
entity->rx_deliv = count;
|
||||
}
|
||||
|
||||
if (entity->t_reordering_start != 0 && entity->rx_deliv > entity->rx_reord) {
|
||||
/* stop and reset t-Reordering */
|
||||
entity->t_reordering_start = 0;
|
||||
}
|
||||
|
||||
if (entity->t_reordering_start == 0 && entity->rx_deliv < entity->rx_next) {
|
||||
entity->rx_reord = entity->rx_next;
|
||||
entity->t_reordering_start = entity->t_current;
|
||||
}
|
||||
}
|
||||
|
||||
nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am(
|
||||
static void nr_pdcp_entity_recv_sdu(nr_pdcp_entity_t *entity,
|
||||
char *buffer, int size, int sdu_id)
|
||||
{
|
||||
uint32_t count;
|
||||
int sn;
|
||||
int header_size;
|
||||
char buf[size+3+4];
|
||||
|
||||
count = entity->tx_next;
|
||||
sn = entity->tx_next & entity->sn_max;
|
||||
|
||||
if (entity->sn_size == 12) {
|
||||
buf[0] = 0x80 | ((sn >> 8) & 0xf);
|
||||
buf[1] = sn & 0xff;
|
||||
header_size = 2;
|
||||
} else {
|
||||
buf[0] = 0x80 | ((sn >> 16) & 0x3);
|
||||
buf[1] = (sn >> 8) & 0xff;
|
||||
buf[2] = sn & 0xff;
|
||||
header_size = 3;
|
||||
}
|
||||
|
||||
memcpy(buf+header_size, buffer, size);
|
||||
|
||||
if (entity->has_ciphering)
|
||||
entity->cipher(entity->security_context,
|
||||
(unsigned char *)buf+header_size, size,
|
||||
entity->rb_id, count, entity->is_gnb ? 1 : 0);
|
||||
|
||||
entity->tx_next++;
|
||||
|
||||
entity->deliver_pdu(entity->deliver_pdu_data, entity, buf,
|
||||
size+header_size, sdu_id);
|
||||
}
|
||||
|
||||
static void nr_pdcp_entity_set_integrity_key(nr_pdcp_entity_t *entity,
|
||||
char *key)
|
||||
{
|
||||
memcpy(entity->integrity_key, key, 16);
|
||||
}
|
||||
|
||||
static void check_t_reordering(nr_pdcp_entity_t *entity)
|
||||
{
|
||||
uint32_t count;
|
||||
|
||||
if (entity->t_reordering_start == 0
|
||||
|| entity->t_current <= entity->t_reordering_start + entity->t_reordering)
|
||||
return;
|
||||
|
||||
/* stop timer */
|
||||
entity->t_reordering_start = 0;
|
||||
|
||||
/* deliver all SDUs with count < rx_reord */
|
||||
while (entity->rx_list != NULL && entity->rx_list->count < entity->rx_reord) {
|
||||
nr_pdcp_sdu_t *cur = entity->rx_list;
|
||||
entity->deliver_sdu(entity->deliver_sdu_data, entity,
|
||||
cur->buffer, cur->size);
|
||||
entity->rx_list = cur->next;
|
||||
entity->rx_size -= cur->size;
|
||||
nr_pdcp_free_sdu(cur);
|
||||
}
|
||||
|
||||
/* deliver all SDUs starting from rx_reord up to discontinuity or end of list */
|
||||
count = entity->rx_reord;
|
||||
while (entity->rx_list != NULL && count == entity->rx_list->count) {
|
||||
nr_pdcp_sdu_t *cur = entity->rx_list;
|
||||
entity->deliver_sdu(entity->deliver_sdu_data, entity,
|
||||
cur->buffer, cur->size);
|
||||
entity->rx_list = cur->next;
|
||||
entity->rx_size -= cur->size;
|
||||
nr_pdcp_free_sdu(cur);
|
||||
count++;
|
||||
}
|
||||
|
||||
entity->rx_deliv = count;
|
||||
|
||||
if (entity->rx_deliv < entity->rx_next) {
|
||||
entity->rx_reord = entity->rx_next;
|
||||
entity->t_reordering_start = entity->t_current;
|
||||
}
|
||||
}
|
||||
|
||||
void nr_pdcp_entity_set_time(struct nr_pdcp_entity_t *entity, uint64_t now)
|
||||
{
|
||||
entity->t_current = now;
|
||||
|
||||
check_t_reordering(entity);
|
||||
}
|
||||
|
||||
void nr_pdcp_entity_delete(nr_pdcp_entity_t *entity)
|
||||
{
|
||||
nr_pdcp_sdu_t *cur = entity->rx_list;
|
||||
while (cur != NULL) {
|
||||
nr_pdcp_sdu_t *next = cur->next;
|
||||
nr_pdcp_free_sdu(cur);
|
||||
cur = next;
|
||||
}
|
||||
if (entity->free_security != NULL)
|
||||
entity->free_security(entity->security_context);
|
||||
free(entity);
|
||||
}
|
||||
|
||||
nr_pdcp_entity_t *new_nr_pdcp_entity(
|
||||
nr_pdcp_entity_type_t type,
|
||||
int is_gnb, int rb_id,
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
|
||||
char *buf, int size),
|
||||
@@ -54,52 +252,56 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am(
|
||||
unsigned char *ciphering_key,
|
||||
unsigned char *integrity_key)
|
||||
{
|
||||
nr_pdcp_entity_drb_am_t *ret;
|
||||
nr_pdcp_entity_t *ret;
|
||||
|
||||
ret = calloc(1, sizeof(nr_pdcp_entity_drb_am_t));
|
||||
ret = calloc(1, sizeof(nr_pdcp_entity_t));
|
||||
if (ret == NULL) {
|
||||
LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret->common.recv_pdu = nr_pdcp_entity_drb_am_recv_pdu;
|
||||
ret->common.recv_sdu = nr_pdcp_entity_drb_am_recv_sdu;
|
||||
ret->common.set_integrity_key = nr_pdcp_entity_drb_am_set_integrity_key;
|
||||
ret->type = type;
|
||||
|
||||
ret->common.delete = nr_pdcp_entity_drb_am_delete;
|
||||
ret->recv_pdu = nr_pdcp_entity_recv_pdu;
|
||||
ret->recv_sdu = nr_pdcp_entity_recv_sdu;
|
||||
ret->set_integrity_key = nr_pdcp_entity_set_integrity_key;
|
||||
ret->set_time = nr_pdcp_entity_set_time;
|
||||
|
||||
ret->common.deliver_sdu = deliver_sdu;
|
||||
ret->common.deliver_sdu_data = deliver_sdu_data;
|
||||
ret->delete = nr_pdcp_entity_delete;
|
||||
|
||||
ret->common.deliver_pdu = deliver_pdu;
|
||||
ret->common.deliver_pdu_data = deliver_pdu_data;
|
||||
ret->deliver_sdu = deliver_sdu;
|
||||
ret->deliver_sdu_data = deliver_sdu_data;
|
||||
|
||||
ret->deliver_pdu = deliver_pdu;
|
||||
ret->deliver_pdu_data = deliver_pdu_data;
|
||||
|
||||
ret->rb_id = rb_id;
|
||||
ret->sn_size = sn_size;
|
||||
ret->t_reordering = t_reordering;
|
||||
ret->discard_timer = discard_timer;
|
||||
|
||||
ret->common.maximum_nr_pdcp_sn = (1 << sn_size) - 1;
|
||||
ret->sn_max = (1 << sn_size) - 1;
|
||||
ret->window_size = 1 << (sn_size - 1);
|
||||
|
||||
if (ciphering_key != NULL && ciphering_algorithm != 0) {
|
||||
if (ciphering_algorithm != 2) {
|
||||
LOG_E(PDCP, "FATAL: only nea2 supported for the moment\n");
|
||||
exit(1);
|
||||
}
|
||||
ret->common.has_ciphering = 1;
|
||||
ret->common.ciphering_algorithm = ciphering_algorithm;
|
||||
memcpy(ret->common.ciphering_key, ciphering_key, 16);
|
||||
ret->has_ciphering = 1;
|
||||
ret->ciphering_algorithm = ciphering_algorithm;
|
||||
memcpy(ret->ciphering_key, ciphering_key, 16);
|
||||
|
||||
ret->common.security_context = nr_pdcp_security_nea2_init(ciphering_key);
|
||||
ret->common.cipher = nr_pdcp_security_nea2_cipher;
|
||||
ret->common.free_security = nr_pdcp_security_nea2_free_security;
|
||||
ret->security_context = nr_pdcp_security_nea2_init(ciphering_key);
|
||||
ret->cipher = nr_pdcp_security_nea2_cipher;
|
||||
ret->free_security = nr_pdcp_security_nea2_free_security;
|
||||
}
|
||||
ret->common.is_gnb = is_gnb;
|
||||
ret->is_gnb = is_gnb;
|
||||
|
||||
if (integrity_key != NULL) {
|
||||
printf("%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return (nr_pdcp_entity_t *)ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -19,18 +19,29 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef _NR_PDCP_ENTITY_H_
|
||||
#define _NR_PDCP_ENTITY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "nr_pdcp_sdu.h"
|
||||
|
||||
typedef enum {
|
||||
NR_PDCP_DRB_AM,
|
||||
NR_PDCP_DRB_UM,
|
||||
NR_PDCP_SRB
|
||||
} nr_pdcp_entity_type_t;
|
||||
|
||||
typedef struct nr_pdcp_entity_t {
|
||||
nr_pdcp_entity_type_t type;
|
||||
|
||||
/* functions provided by the PDCP module */
|
||||
void (*recv_pdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size);
|
||||
void (*recv_sdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size,
|
||||
int sdu_id);
|
||||
void (*delete)(struct nr_pdcp_entity_t *entity);
|
||||
void (*set_integrity_key)(struct nr_pdcp_entity_t *entity, char *key);
|
||||
void (*set_time)(struct nr_pdcp_entity_t *entity, uint64_t now);
|
||||
|
||||
/* callbacks provided to the PDCP module */
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
|
||||
@@ -39,9 +50,28 @@ typedef struct nr_pdcp_entity_t {
|
||||
void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity,
|
||||
char *buf, int size, int sdu_id);
|
||||
void *deliver_pdu_data;
|
||||
int tx_hfn;
|
||||
int next_nr_pdcp_tx_sn;
|
||||
int maximum_nr_pdcp_sn;
|
||||
|
||||
/* configuration variables */
|
||||
int rb_id;
|
||||
|
||||
int sn_size; /* SN size, in bits */
|
||||
int t_reordering; /* unit: ms */
|
||||
int discard_timer; /* unit: ms */
|
||||
|
||||
int sn_max; /* (2^SN_size) - 1 */
|
||||
int window_size; /* 2^(SN_size - 1) */
|
||||
|
||||
/* state variables */
|
||||
uint32_t tx_next;
|
||||
uint32_t rx_next;
|
||||
uint32_t rx_deliv;
|
||||
uint32_t rx_reord;
|
||||
|
||||
/* set to the latest know time by the user of the module. Unit: ms */
|
||||
uint64_t t_current;
|
||||
|
||||
/* timers (stores the ms of activation, 0 means not active) */
|
||||
int t_reordering_start;
|
||||
|
||||
/* security */
|
||||
int has_ciphering;
|
||||
@@ -60,18 +90,15 @@ typedef struct nr_pdcp_entity_t {
|
||||
* pdcp entity is for a gnb or an ue
|
||||
*/
|
||||
int is_gnb;
|
||||
|
||||
/* rx management */
|
||||
nr_pdcp_sdu_t *rx_list;
|
||||
int rx_size;
|
||||
int rx_maxsize;
|
||||
} nr_pdcp_entity_t;
|
||||
|
||||
nr_pdcp_entity_t *new_nr_pdcp_entity_srb(
|
||||
int is_gnb, int rb_id,
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
|
||||
char *buf, int size),
|
||||
void *deliver_sdu_data,
|
||||
void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity,
|
||||
char *buf, int size, int sdu_id),
|
||||
void *deliver_pdu_data);
|
||||
|
||||
nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am(
|
||||
nr_pdcp_entity_t *new_nr_pdcp_entity(
|
||||
nr_pdcp_entity_type_t type,
|
||||
int is_gnb, int rb_id,
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
|
||||
char *buf, int size),
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* 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 "nr_pdcp_entity_drb_am.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
void nr_pdcp_entity_drb_am_recv_pdu(nr_pdcp_entity_t *_entity, char *buffer, int size)
|
||||
{
|
||||
nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity;
|
||||
int sn;
|
||||
|
||||
if (size < 3) abort();
|
||||
|
||||
if (!(buffer[0] & 0x80))
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
sn = (((unsigned char)buffer[0] & 0x3) << 16) |
|
||||
((unsigned char)buffer[1] << 8) |
|
||||
(unsigned char)buffer[2];
|
||||
|
||||
if (entity->common.has_ciphering)
|
||||
entity->common.cipher(entity->common.security_context, (unsigned char *)buffer+3, size-3,
|
||||
entity->rb_id, sn, entity->common.is_gnb ? 0 : 1);
|
||||
|
||||
entity->common.deliver_sdu(entity->common.deliver_sdu_data,
|
||||
(nr_pdcp_entity_t *)entity, buffer+3, size-3);
|
||||
}
|
||||
|
||||
void nr_pdcp_entity_drb_am_recv_sdu(nr_pdcp_entity_t *_entity, char *buffer, int size,
|
||||
int sdu_id)
|
||||
{
|
||||
nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity;
|
||||
int sn;
|
||||
char buf[size+3];
|
||||
|
||||
sn = entity->common.next_nr_pdcp_tx_sn;
|
||||
|
||||
entity->common.next_nr_pdcp_tx_sn++;
|
||||
if (entity->common.next_nr_pdcp_tx_sn > entity->common.maximum_nr_pdcp_sn) {
|
||||
entity->common.next_nr_pdcp_tx_sn = 0;
|
||||
entity->common.tx_hfn++;
|
||||
}
|
||||
|
||||
buf[0] = 0x80 | ((sn >> 16) & 0x3);
|
||||
buf[1] = (sn >> 8) & 0xff;
|
||||
buf[2] = sn & 0xff;
|
||||
memcpy(buf+3, buffer, size);
|
||||
|
||||
if (entity->common.has_ciphering)
|
||||
entity->common.cipher(entity->common.security_context, (unsigned char *)buf+3, size,
|
||||
entity->rb_id, sn, entity->common.is_gnb ? 1 : 0);
|
||||
|
||||
entity->common.deliver_pdu(entity->common.deliver_pdu_data,
|
||||
(nr_pdcp_entity_t *)entity, buf, size+3, sdu_id);
|
||||
}
|
||||
|
||||
void nr_pdcp_entity_drb_am_set_integrity_key(nr_pdcp_entity_t *_entity, char *key)
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
void nr_pdcp_entity_drb_am_delete(nr_pdcp_entity_t *_entity)
|
||||
{
|
||||
nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity;
|
||||
if (entity->common.free_security != NULL)
|
||||
entity->common.free_security(entity->common.security_context);
|
||||
free(entity);
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
#endif
|
||||
#include "asn1_utils.h"
|
||||
#include "nr_pdcp_ue_manager.h"
|
||||
#include "nr_pdcp_timer_thread.h"
|
||||
#include "NR_RadioBearerConfig.h"
|
||||
#include "NR_RLC-BearerConfig.h"
|
||||
#include "NR_RLC-Config.h"
|
||||
@@ -41,6 +42,11 @@
|
||||
|
||||
static nr_pdcp_ue_manager_t *nr_pdcp_ue_manager;
|
||||
|
||||
/* TODO: handle time a bit more properly */
|
||||
static uint64_t nr_pdcp_current_time;
|
||||
static int nr_pdcp_current_time_last_frame;
|
||||
static int nr_pdcp_current_time_last_subframe;
|
||||
|
||||
/* necessary globals for OAI, not used internally */
|
||||
hash_table_t *pdcp_coll_p;
|
||||
static uint64_t pdcp_optmask;
|
||||
@@ -339,6 +345,8 @@ void pdcp_layer_init(void)
|
||||
|
||||
nr_pdcp_ue_manager = new_nr_pdcp_ue_manager(1);
|
||||
init_nr_rlc_data_req_queue();
|
||||
|
||||
nr_pdcp_init_timer_thread(nr_pdcp_ue_manager);
|
||||
}
|
||||
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
@@ -625,11 +633,11 @@ static void add_drb_am(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s,
|
||||
LOG_D(PDCP, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
|
||||
} else {
|
||||
pdcp_drb = new_nr_pdcp_entity_drb_am(is_gnb, drb_id,
|
||||
deliver_sdu_drb, ue, deliver_pdu_drb, ue,
|
||||
sn_size_dl, t_reordering, discard_timer,
|
||||
ciphering_algorithm, integrity_algorithm,
|
||||
ciphering_key, integrity_key);
|
||||
pdcp_drb = new_nr_pdcp_entity(NR_PDCP_DRB_AM, is_gnb, drb_id,
|
||||
deliver_sdu_drb, ue, deliver_pdu_drb, ue,
|
||||
sn_size_dl, t_reordering, discard_timer,
|
||||
ciphering_algorithm, integrity_algorithm,
|
||||
ciphering_key, integrity_key);
|
||||
nr_pdcp_ue_add_drb_pdcp_entity(ue, drb_id, pdcp_drb);
|
||||
|
||||
LOG_D(PDCP, "%s:%d:%s: added drb %d to ue rnti %x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
|
||||
@@ -976,3 +984,14 @@ void
|
||||
pdcp_mbms_run ( const protocol_ctxt_t *const ctxt_pP){
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
void nr_pdcp_tick(int frame, int subframe)
|
||||
{
|
||||
if (frame != nr_pdcp_current_time_last_frame ||
|
||||
subframe != nr_pdcp_current_time_last_subframe) {
|
||||
nr_pdcp_current_time_last_frame = frame;
|
||||
nr_pdcp_current_time_last_subframe = subframe;
|
||||
nr_pdcp_current_time++;
|
||||
nr_pdcp_wakeup_timer_thread(nr_pdcp_current_time);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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 "nr_pdcp_sdu.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size)
|
||||
{
|
||||
nr_pdcp_sdu_t *ret = calloc(1, sizeof(nr_pdcp_sdu_t));
|
||||
if (ret == NULL)
|
||||
exit(1);
|
||||
ret->count = count;
|
||||
ret->buffer = malloc(size);
|
||||
if (ret->buffer == NULL)
|
||||
exit(1);
|
||||
memcpy(ret->buffer, buffer, size);
|
||||
ret->size = size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
nr_pdcp_sdu_t *nr_pdcp_sdu_list_add(nr_pdcp_sdu_t *l, nr_pdcp_sdu_t *sdu)
|
||||
{
|
||||
nr_pdcp_sdu_t head;
|
||||
nr_pdcp_sdu_t *cur;
|
||||
nr_pdcp_sdu_t *prev;
|
||||
|
||||
head.next = l;
|
||||
cur = l;
|
||||
prev = &head;
|
||||
|
||||
/* order is by 'count' */
|
||||
while (cur != NULL) {
|
||||
/* check if 'sdu' is before 'cur' in the list */
|
||||
if (sdu->count < cur->count)
|
||||
break;
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
prev->next = sdu;
|
||||
sdu->next = cur;
|
||||
return head.next;
|
||||
}
|
||||
|
||||
int nr_pdcp_sdu_in_list(nr_pdcp_sdu_t *l, uint32_t count)
|
||||
{
|
||||
while (l != NULL) {
|
||||
if (l->count == count)
|
||||
return 1;
|
||||
l = l->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nr_pdcp_free_sdu(nr_pdcp_sdu_t *sdu)
|
||||
{
|
||||
free(sdu->buffer);
|
||||
free(sdu);
|
||||
}
|
||||
+14
-16
@@ -19,23 +19,21 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef _NR_PDCP_ENTITY_DRB_AM_H_
|
||||
#define _NR_PDCP_ENTITY_DRB_AM_H_
|
||||
#ifndef _NR_PDCP_SDU_H_
|
||||
#define _NR_PDCP_SDU_H_
|
||||
|
||||
#include "nr_pdcp_entity.h"
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
nr_pdcp_entity_t common;
|
||||
int rb_id;
|
||||
int sn_size; /* unit: bits */
|
||||
int t_reordering; /* unit: ms */
|
||||
int discard_timer; /* unit: ms, -1 means infinity */
|
||||
} nr_pdcp_entity_drb_am_t;
|
||||
typedef struct nr_pdcp_sdu_t {
|
||||
uint32_t count;
|
||||
char *buffer;
|
||||
int size;
|
||||
struct nr_pdcp_sdu_t *next;
|
||||
} nr_pdcp_sdu_t;
|
||||
|
||||
void nr_pdcp_entity_drb_am_recv_pdu(nr_pdcp_entity_t *entity, char *buffer, int size);
|
||||
void nr_pdcp_entity_drb_am_recv_sdu(nr_pdcp_entity_t *entity, char *buffer, int size,
|
||||
int sdu_id);
|
||||
void nr_pdcp_entity_drb_am_set_integrity_key(nr_pdcp_entity_t *entity, char *key);
|
||||
void nr_pdcp_entity_drb_am_delete(nr_pdcp_entity_t *entity);
|
||||
nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size);
|
||||
nr_pdcp_sdu_t *nr_pdcp_sdu_list_add(nr_pdcp_sdu_t *l, nr_pdcp_sdu_t *sdu);
|
||||
int nr_pdcp_sdu_in_list(nr_pdcp_sdu_t *l, uint32_t count);
|
||||
void nr_pdcp_free_sdu(nr_pdcp_sdu_t *sdu);
|
||||
|
||||
#endif /* _NR_PDCP_ENTITY_DRB_AM_H_ */
|
||||
#endif /* _NR_PDCP_SDU_H_ */
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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 "nr_pdcp_timer_thread.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "LOG/log.h"
|
||||
|
||||
static pthread_mutex_t timer_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t timer_thread_cond = PTHREAD_COND_INITIALIZER;
|
||||
static volatile uint64_t timer_thread_curtime = 0;
|
||||
|
||||
static void *nr_pdcp_timer_thread(void *_nr_pdcp_ue_manager)
|
||||
{
|
||||
nr_pdcp_ue_manager_t *nr_pdcp_ue_manager = (nr_pdcp_ue_manager_t *)_nr_pdcp_ue_manager;
|
||||
nr_pdcp_ue_t **ue_list;
|
||||
int ue_count;
|
||||
int i;
|
||||
int j;
|
||||
uint64_t curtime = 0;
|
||||
|
||||
while (1) {
|
||||
if (pthread_mutex_lock(&timer_thread_mutex) != 0) abort();
|
||||
while (curtime == timer_thread_curtime)
|
||||
if (pthread_cond_wait(&timer_thread_cond, &timer_thread_mutex) != 0) abort();
|
||||
curtime = timer_thread_curtime;
|
||||
if (pthread_mutex_unlock(&timer_thread_mutex) != 0) abort();
|
||||
|
||||
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
|
||||
|
||||
ue_list = nr_pdcp_manager_get_ue_list(nr_pdcp_ue_manager);
|
||||
ue_count = nr_pdcp_manager_get_ue_count(nr_pdcp_ue_manager);
|
||||
for (i = 0; i < ue_count; i++) {
|
||||
for (j = 0; j < 2; j++) {
|
||||
if (ue_list[i]->srb[j] != NULL)
|
||||
ue_list[i]->srb[j]->set_time(ue_list[i]->srb[j], curtime);
|
||||
}
|
||||
for (j = 0; j < 5; j++) {
|
||||
if (ue_list[i]->drb[j] != NULL)
|
||||
ue_list[i]->drb[j]->set_time(ue_list[i]->drb[j], curtime);
|
||||
}
|
||||
}
|
||||
|
||||
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void nr_pdcp_init_timer_thread(nr_pdcp_ue_manager_t *nr_pdcp_ue_manager)
|
||||
{
|
||||
pthread_t t;
|
||||
|
||||
if (pthread_create(&t, NULL, nr_pdcp_timer_thread, nr_pdcp_ue_manager) != 0) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void nr_pdcp_wakeup_timer_thread(uint64_t time)
|
||||
{
|
||||
if (pthread_mutex_lock(&timer_thread_mutex)) abort();
|
||||
timer_thread_curtime = time;
|
||||
if (pthread_cond_broadcast(&timer_thread_cond)) abort();
|
||||
if (pthread_mutex_unlock(&timer_thread_mutex)) abort();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef _NR_PDCP_TIMER_THREAD_H_
|
||||
#define _NR_PDCP_TIMER_THREAD_H_
|
||||
|
||||
#include "nr_pdcp_ue_manager.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void nr_pdcp_init_timer_thread(nr_pdcp_ue_manager_t *nr_pdcp_ue_manager);
|
||||
void nr_pdcp_wakeup_timer_thread(uint64_t time);
|
||||
|
||||
#endif /* _NR_PDCP_TIMER_THREAD_H_ */
|
||||
@@ -189,6 +189,20 @@ void nr_pdcp_ue_add_drb_pdcp_entity(nr_pdcp_ue_t *ue, int drb_id, nr_pdcp_entity
|
||||
ue->drb[drb_id] = entity;
|
||||
}
|
||||
|
||||
/* must be called with lock acquired */
|
||||
nr_pdcp_ue_t **nr_pdcp_manager_get_ue_list(nr_pdcp_ue_manager_t *_m)
|
||||
{
|
||||
nr_pdcp_ue_manager_internal_t *m = _m;
|
||||
return m->ue_list;
|
||||
}
|
||||
|
||||
/* must be called with lock acquired */
|
||||
int nr_pdcp_manager_get_ue_count(nr_pdcp_ue_manager_t *_m)
|
||||
{
|
||||
nr_pdcp_ue_manager_internal_t *m = _m;
|
||||
return m->ue_count;
|
||||
}
|
||||
|
||||
int nr_pdcp_get_first_rnti(nr_pdcp_ue_manager_t *_m)
|
||||
{
|
||||
nr_pdcp_ue_manager_internal_t *m = _m;
|
||||
|
||||
@@ -46,6 +46,9 @@ void nr_pdcp_manager_unlock(nr_pdcp_ue_manager_t *m);
|
||||
nr_pdcp_ue_t *nr_pdcp_manager_get_ue(nr_pdcp_ue_manager_t *m, int rnti);
|
||||
void nr_pdcp_manager_remove_ue(nr_pdcp_ue_manager_t *m, int rnti);
|
||||
|
||||
nr_pdcp_ue_t **nr_pdcp_manager_get_ue_list(nr_pdcp_ue_manager_t *_m);
|
||||
int nr_pdcp_manager_get_ue_count(nr_pdcp_ue_manager_t *_m);
|
||||
|
||||
/***********************************************************************/
|
||||
/* ue functions */
|
||||
/***********************************************************************/
|
||||
|
||||
@@ -62,7 +62,7 @@ int handle_bcch_bch(module_id_t module_id, int cc_id, unsigned int gNB_index, ui
|
||||
|
||||
// L2 Abstraction Layer
|
||||
int handle_bcch_dlsch(module_id_t module_id, int cc_id, unsigned int gNB_index, uint32_t sibs_mask, uint8_t *pduP, uint32_t pdu_len){
|
||||
return nr_ue_decode_sib1(module_id, cc_id, gNB_index, sibs_mask, pduP, pdu_len);
|
||||
return nr_ue_decode_BCCH_DL_SCH(module_id, cc_id, gNB_index, sibs_mask, pduP, pdu_len);
|
||||
}
|
||||
|
||||
// L2 Abstraction Layer
|
||||
@@ -90,7 +90,7 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info){
|
||||
|
||||
ret = nr_ue_scheduler(NULL, ul_info);
|
||||
|
||||
if (is_nr_UL_slot(mac->scc, ul_info->slot_tx) && get_softmodem_params()->do_ra)
|
||||
if (is_nr_UL_slot(mac->scc, ul_info->slot_tx, mac->frame_type) && get_softmodem_params()->do_ra)
|
||||
nr_ue_prach_scheduler(module_id, ul_info->frame_tx, ul_info->slot_tx, ul_info->thread_id);
|
||||
|
||||
switch(ret){
|
||||
|
||||
@@ -782,21 +782,37 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ(
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask |= UE_IDENTITIES_gummei;
|
||||
|
||||
if (r_mme->plmn_Identity != NULL) {
|
||||
if ((r_mme->plmn_Identity->mcc != NULL) && (r_mme->plmn_Identity->mcc->list.count > 0)) {
|
||||
/* Use first indicated PLMN MCC if it is defined */
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = *r_mme->plmn_Identity->mcc->list.array[selected_plmn_identity];
|
||||
if ((r_mme->plmn_Identity->mcc != NULL) && (r_mme->plmn_Identity->mcc->list.count == 3))
|
||||
{
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = (*r_mme->plmn_Identity->mcc->list.array[0] & 0xf) * 100 +
|
||||
(*r_mme->plmn_Identity->mcc->list.array[1] & 0xf) * 10 +
|
||||
(*r_mme->plmn_Identity->mcc->list.array[2] & 0xf);
|
||||
LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MCC %u ue %x\n",
|
||||
ctxt_pP->module_id,
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc,
|
||||
ue_context_pP->ue_context.rnti);
|
||||
}
|
||||
|
||||
if (r_mme->plmn_Identity->mnc.list.count > 0) {
|
||||
/* Use first indicated PLMN MNC if it is defined */
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = *r_mme->plmn_Identity->mnc.list.array[selected_plmn_identity];
|
||||
LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u ue %x\n",
|
||||
if(r_mme->plmn_Identity->mnc.list.count == 3)
|
||||
{
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = (*r_mme->plmn_Identity->mnc.list.array[0] & 0xf) * 100 +
|
||||
(*r_mme->plmn_Identity->mnc.list.array[1] & 0xf) * 10 +
|
||||
(*r_mme->plmn_Identity->mnc.list.array[2] & 0xf);
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len = 3;
|
||||
LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u %udigit ue %x\n",
|
||||
ctxt_pP->module_id,
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc,
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len,
|
||||
ue_context_pP->ue_context.rnti);
|
||||
}
|
||||
else if(r_mme->plmn_Identity->mnc.list.count == 2)
|
||||
{
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = (*r_mme->plmn_Identity->mnc.list.array[0] & 0xf) * 10 +
|
||||
(*r_mme->plmn_Identity->mnc.list.array[1] & 0xf);
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len = 2;
|
||||
LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u %udigit ue %x\n",
|
||||
ctxt_pP->module_id,
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc,
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len,
|
||||
ue_context_pP->ue_context.rnti);
|
||||
}
|
||||
} else { // end if plmn_Identity != NULL
|
||||
|
||||
@@ -32,11 +32,11 @@
|
||||
#define RRC_TYPES_NR_H_
|
||||
|
||||
typedef enum Rrc_State_NR_e {
|
||||
RRC_STATE_INACTIVE_NR=0,
|
||||
RRC_STATE_IDLE_NR,
|
||||
RRC_STATE_IDLE_NR=0,
|
||||
RRC_STATE_INACTIVE_NR,
|
||||
RRC_STATE_CONNECTED_NR,
|
||||
|
||||
RRC_STATE_FIRST_NR = RRC_STATE_INACTIVE_NR,
|
||||
RRC_STATE_FIRST_NR = RRC_STATE_IDLE_NR,
|
||||
RRC_STATE_LAST_NR = RRC_STATE_CONNECTED_NR,
|
||||
} Rrc_State_NR_t;
|
||||
|
||||
|
||||
@@ -327,7 +327,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
|
||||
1024);
|
||||
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = (enc_rval.encoded+7)>>3;
|
||||
itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(0), msg); //Check right id instead of hardcoding
|
||||
} else if (get_softmodem_params()->do_ra) {
|
||||
} else if (get_softmodem_params()->do_ra || get_softmodem_params()->sa) {
|
||||
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, rrc->module_id, GNB_FLAG_YES, ue_context_p->ue_id_rnti, 0, 0,rrc->module_id);
|
||||
}
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ void fill_default_searchSpaceZero(NR_SearchSpace_t *ss0) {
|
||||
// FIXME: update values from TS38.213 Section 10.1 Table 10.1-1: CCE aggregation levels and maximum number of PDCCH candidates per CCE aggregation level for CSS sets configured by searchSpaceSIB1
|
||||
ss0->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0;
|
||||
ss0->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0;
|
||||
ss0->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1;
|
||||
ss0->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n2;
|
||||
ss0->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0;
|
||||
ss0->nrofCandidates->aggregationLevel16 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0;
|
||||
|
||||
@@ -172,7 +172,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
||||
secondaryCellGroup->cellGroupId = scg_id;
|
||||
NR_RLC_BearerConfig_t *RLC_BearerConfig = calloc(1,sizeof(*RLC_BearerConfig));
|
||||
nr_rlc_bearer_init(RLC_BearerConfig);
|
||||
if (get_softmodem_params()->do_ra)
|
||||
if (get_softmodem_params()->do_ra || get_softmodem_params()->sa)
|
||||
nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_um_Bi_Directional);
|
||||
else
|
||||
nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_am);
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "rrc_defs.h"
|
||||
#include "rrc_proto.h"
|
||||
#include "assertions.h"
|
||||
#include "rrc_vars.h"
|
||||
|
||||
typedef uint32_t channel_t;
|
||||
|
||||
@@ -50,7 +51,7 @@ nr_mac_rrc_data_ind_ue(
|
||||
AssertFatal( nr_rrc_ue_decode_NR_BCCH_BCH_Message(module_id, gNB_index, (uint8_t*)pduP, pdu_len) == 0, "UE decode BCCH-BCH error!\n");
|
||||
break;
|
||||
case NR_BCCH_DL_SCH:
|
||||
AssertFatal( nr_rrc_ue_decode_NR_SIB1_Message(module_id, gNB_index, (uint8_t*)pduP, pdu_len) == 0, "UE decode BCCH-DLSCH error!\n");
|
||||
AssertFatal( nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(module_id, gNB_index, (uint8_t*)pduP, pdu_len, 0, 0) == 0, "UE decode BCCH-DL-SCH error!\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -59,13 +60,36 @@ nr_mac_rrc_data_ind_ue(
|
||||
return(0);
|
||||
}
|
||||
|
||||
int8_t mac_rrc_nr_data_req_ue(const module_id_t Mod_idP,
|
||||
int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP,
|
||||
const int CC_id,
|
||||
const uint8_t gNB_id,
|
||||
const frame_t frameP,
|
||||
const rb_id_t Srb_id,
|
||||
uint8_t *const buffer_pP ){
|
||||
uint8_t *buffer_pP){
|
||||
|
||||
// todo
|
||||
switch(Srb_id){
|
||||
|
||||
case CCCH:
|
||||
|
||||
// TODO: Enable timer T300
|
||||
//NR_UE_rrc_inst[Mod_idP].Info[gNB_id].T300_active = 1;
|
||||
//NR_UE_rrc_inst[Mod_idP].Info[gNB_id].T300_cnt = 0;
|
||||
|
||||
LOG_D(NR_RRC, "nr_mac_rrc_data_req_ue: Payload size = %i\n", NR_UE_rrc_inst[Mod_idP].Srb0[gNB_id].Tx_buffer.payload_size);
|
||||
memcpy(buffer_pP, (uint8_t*)NR_UE_rrc_inst[Mod_idP].Srb0[gNB_id].Tx_buffer.Payload, NR_UE_rrc_inst[Mod_idP].Srb0[gNB_id].Tx_buffer.payload_size);
|
||||
for(int i = 0; i<NR_UE_rrc_inst[Mod_idP].Srb0[gNB_id].Tx_buffer.payload_size; i++) {
|
||||
LOG_D(NR_RRC,"(%i): %i\n", i, buffer_pP[i]);
|
||||
}
|
||||
|
||||
return NR_UE_rrc_inst[Mod_idP].Srb0[gNB_id].Tx_buffer.payload_size;
|
||||
|
||||
case DCCH:
|
||||
AssertFatal(1==0, "SRB1 not implemented yet!\n");
|
||||
case DCCH1:
|
||||
AssertFatal(1==0, "SRB2 not implemented yet!\n");
|
||||
default:
|
||||
AssertFatal(1==0, "Invalid SRB id!\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user