Merge remote-tracking branch 'origin/prs_bug_fix_and_integrate_to_ci' into integration_2025_w45 (!3670)
PRS bug fix and CI Integration - Fix the bug in PRS channel estimation while copying memory to compute the impulse response - Integrate PRS testing to CI
This commit is contained in:
@@ -233,10 +233,10 @@ def Custom_Command(HTML, node, command):
|
|||||||
HTML.CreateHtmlTestRowQueue(command, status, message)
|
HTML.CreateHtmlTestRowQueue(command, status, message)
|
||||||
return status == 'OK' or status == 'Warning'
|
return status == 'OK' or status == 'Warning'
|
||||||
|
|
||||||
def Custom_Script(HTML, node, script):
|
def Custom_Script(HTML, node, script, args):
|
||||||
logging.info(f"Executing custom script on {node}")
|
logging.info(f"Executing custom script on {node}")
|
||||||
with cls_cmd.getConnection(node) as c:
|
with cls_cmd.getConnection(node) as c:
|
||||||
ret = c.exec_script(script, 90)
|
ret = c.exec_script(script, 90, args)
|
||||||
logging.debug(f"Custom_Script: {script} on node: {node} - return code {ret.returncode}, output:\n{ret.stdout}")
|
logging.debug(f"Custom_Script: {script} on node: {node} - return code {ret.returncode}, output:\n{ret.stdout}")
|
||||||
status = 'OK'
|
status = 'OK'
|
||||||
message = [ret.stdout]
|
message = [ret.stdout]
|
||||||
|
|||||||
@@ -0,0 +1,256 @@
|
|||||||
|
Active_gNBs = ( "gNB-OAI");
|
||||||
|
# Asn1_verbosity, choice in: none, info, annoying
|
||||||
|
Asn1_verbosity = "none";
|
||||||
|
|
||||||
|
gNBs =
|
||||||
|
(
|
||||||
|
{
|
||||||
|
////////// Identification parameters:
|
||||||
|
gNB_ID = 0xe00;
|
||||||
|
gNB_name = "gNB-OAI";
|
||||||
|
|
||||||
|
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||||
|
tracking_area_code = 1;
|
||||||
|
|
||||||
|
plmn_list = ({mcc = 208; mnc = 97; mnc_length = 2;});
|
||||||
|
|
||||||
|
////////// Physical parameters:
|
||||||
|
|
||||||
|
min_rxtxtime = 6;
|
||||||
|
|
||||||
|
servingCellConfigCommon = (
|
||||||
|
{
|
||||||
|
#spCellConfigCommon
|
||||||
|
|
||||||
|
physCellId = 0;
|
||||||
|
|
||||||
|
# downlinkConfigCommon
|
||||||
|
#frequencyInfoDL
|
||||||
|
# this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68
|
||||||
|
absoluteFrequencySSB = 621312;
|
||||||
|
# this is 3300.60 MHz
|
||||||
|
dl_absoluteFrequencyPointA = 620040;
|
||||||
|
#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=106 (275*(L-1))+RBstart
|
||||||
|
initialDLBWPlocationAndBandwidth = 28875;
|
||||||
|
# subcarrierSpacing
|
||||||
|
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||||
|
initialDLBWPsubcarrierSpacing = 1;
|
||||||
|
#pdcch-ConfigCommon
|
||||||
|
initialDLBWPcontrolResourceSetZero = 11;
|
||||||
|
initialDLBWPsearchSpaceZero = 0;
|
||||||
|
|
||||||
|
#uplinkConfigCommon
|
||||||
|
#frequencyInfoUL
|
||||||
|
ul_frequencyBand = 78;
|
||||||
|
#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 = 28875;
|
||||||
|
# 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 = 12;
|
||||||
|
preambleReceivedTargetPower = -104;
|
||||||
|
#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;
|
||||||
|
#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;
|
||||||
|
#one (0..15) 4,8,12,16,...60,64
|
||||||
|
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15;
|
||||||
|
#ra_ContentionResolutionTimer
|
||||||
|
#(0..7) 8,16,24,32,40,48,56,64
|
||||||
|
ra_ContentionResolutionTimer = 7;
|
||||||
|
rsrp_ThresholdSSB = 19;
|
||||||
|
#prach-RootSequenceIndex_PR
|
||||||
|
#1 = 839, 2 = 139
|
||||||
|
prach_RootSequenceIndex_PR = 2;
|
||||||
|
prach_RootSequenceIndex = 1;
|
||||||
|
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
|
||||||
|
#
|
||||||
|
msg1_SubcarrierSpacing = 1,
|
||||||
|
# restrictedSetConfig
|
||||||
|
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||||
|
restrictedSetConfig = 0,
|
||||||
|
|
||||||
|
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_PositionsInBurst_Bitmap = 1;
|
||||||
|
|
||||||
|
# ssb_periodicityServingCell
|
||||||
|
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spar e1
|
||||||
|
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 = -25;
|
||||||
|
}
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
# ------- SCTP definitions
|
||||||
|
SCTP :
|
||||||
|
{
|
||||||
|
# Number of streams to use in input/output
|
||||||
|
SCTP_INSTREAMS = 2;
|
||||||
|
SCTP_OUTSTREAMS = 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////// AMF parameters:
|
||||||
|
amf_ip_address = ({ ipv4 = "CI_MME_IP_ADDR"; });
|
||||||
|
|
||||||
|
NETWORK_INTERFACES :
|
||||||
|
{
|
||||||
|
|
||||||
|
GNB_IPV4_ADDRESS_FOR_NG_AMF = "CI_GNB_IP_ADDR";
|
||||||
|
GNB_IPV4_ADDRESS_FOR_NGU = "CI_GNB_IP_ADDR";
|
||||||
|
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
MACRLCs = (
|
||||||
|
{
|
||||||
|
num_cc = 1;
|
||||||
|
tr_s_preference = "local_L1";
|
||||||
|
tr_n_preference = "local_RRC";
|
||||||
|
pusch_TargetSNRx10 = 200;
|
||||||
|
pucch_TargetSNRx10 = 200;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
prs_config = (
|
||||||
|
{
|
||||||
|
NumPRSResources = 1;
|
||||||
|
PRSResourceSetPeriod = [20, 2];
|
||||||
|
SymbolStart = [7];
|
||||||
|
NumPRSSymbols = [6];
|
||||||
|
NumRB = 106;
|
||||||
|
RBOffset = 0;
|
||||||
|
CombSize = 4;
|
||||||
|
REOffset = [0];
|
||||||
|
PRSResourceOffset = [0];
|
||||||
|
PRSResourceRepetition = 1;
|
||||||
|
PRSResourceTimeGap = 1;
|
||||||
|
NPRS_ID = [0];
|
||||||
|
MutingPattern1 = [];
|
||||||
|
MutingPattern2 = [];
|
||||||
|
MutingBitRepetition = 1;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
L1s = (
|
||||||
|
{
|
||||||
|
num_cc = 1;
|
||||||
|
tr_n_preference = "local_mac";
|
||||||
|
prach_dtx_threshold = 120;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
RUs = (
|
||||||
|
{
|
||||||
|
local_rf = "yes"
|
||||||
|
nb_tx = 1
|
||||||
|
nb_rx = 1
|
||||||
|
att_tx = 0
|
||||||
|
att_rx = 0;
|
||||||
|
bands = [78];
|
||||||
|
max_pdschReferenceSignalPower = -27;
|
||||||
|
max_rxgain = 75;
|
||||||
|
sf_extension = 0;
|
||||||
|
eNB_instances = [0];
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
rfsimulator :
|
||||||
|
{
|
||||||
|
serveraddr = "server";
|
||||||
|
serverport = 4043;
|
||||||
|
options = (); #("saviq"); or/and "chanmod"
|
||||||
|
modelname = "AWGN";
|
||||||
|
IQfile = "/tmp/rfsimulator.iqs";
|
||||||
|
};
|
||||||
|
|
||||||
|
security = {
|
||||||
|
# preferred ciphering algorithms
|
||||||
|
# the first one of the list that an UE supports in chosen
|
||||||
|
# valid values: nea0, nea1, nea2, nea3
|
||||||
|
ciphering_algorithms = ( "nea0" );
|
||||||
|
|
||||||
|
# preferred integrity algorithms
|
||||||
|
# the first one of the list that an UE supports in chosen
|
||||||
|
# valid values: nia0, nia1, nia2, nia3
|
||||||
|
integrity_algorithms = ( "nia2", "nia0" );
|
||||||
|
|
||||||
|
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
|
||||||
|
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
|
||||||
|
drb_ciphering = "yes";
|
||||||
|
drb_integrity = "no";
|
||||||
|
};
|
||||||
|
|
||||||
|
log_config :
|
||||||
|
{
|
||||||
|
global_log_level = "info";
|
||||||
|
hw_log_level = "info";
|
||||||
|
phy_log_level = "info";
|
||||||
|
mac_log_level = "info";
|
||||||
|
rlc_log_level = "info";
|
||||||
|
pdcp_log_level = "info";
|
||||||
|
rrc_log_level = "info";
|
||||||
|
f1ap_log_level = "debug";
|
||||||
|
};
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
PRSs =
|
||||||
|
(
|
||||||
|
{
|
||||||
|
Active_gNBs = 1;
|
||||||
|
prs_config0 = (
|
||||||
|
{
|
||||||
|
gNB_id = 0;
|
||||||
|
NumPRSResources = 1;
|
||||||
|
PRSResourceSetPeriod = [20, 2];
|
||||||
|
SymbolStart = [7];
|
||||||
|
NumPRSSymbols = [6];
|
||||||
|
NumRB = 106;
|
||||||
|
RBOffset = 0;
|
||||||
|
CombSize = 4;
|
||||||
|
REOffset = [0];
|
||||||
|
PRSResourceOffset = [0];
|
||||||
|
PRSResourceRepetition = 1;
|
||||||
|
PRSResourceTimeGap = 1;
|
||||||
|
NPRS_ID = [0];
|
||||||
|
MutingPattern1 = [];
|
||||||
|
MutingPattern2 = [];
|
||||||
|
MutingBitRepetition = 1;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
prs_config1 = (
|
||||||
|
{
|
||||||
|
gNB_id = 1;
|
||||||
|
NumPRSResources = 1;
|
||||||
|
PRSResourceSetPeriod = [20, 2];
|
||||||
|
SymbolStart = [7];
|
||||||
|
NumPRSSymbols = [6];
|
||||||
|
NumRB = 106;
|
||||||
|
RBOffset = 0;
|
||||||
|
CombSize = 4;
|
||||||
|
REOffset = [0];
|
||||||
|
PRSResourceOffset = [1];
|
||||||
|
PRSResourceRepetition = 1;
|
||||||
|
PRSResourceTimeGap = 1;
|
||||||
|
NPRS_ID = [1];
|
||||||
|
MutingPattern1 = [];
|
||||||
|
MutingPattern2 = [];
|
||||||
|
MutingBitRepetition = 1;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
prs_config2 = (
|
||||||
|
{
|
||||||
|
gNB_id = 2;
|
||||||
|
NumPRSResources = 1;
|
||||||
|
PRSResourceSetPeriod = [20, 2];
|
||||||
|
SymbolStart = [7];
|
||||||
|
NumPRSSymbols = [6];
|
||||||
|
NumRB = 106;
|
||||||
|
RBOffset = 0;
|
||||||
|
CombSize = 4;
|
||||||
|
REOffset = [0];
|
||||||
|
PRSResourceOffset = [2];
|
||||||
|
PRSResourceRepetition = 1;
|
||||||
|
PRSResourceTimeGap = 1;
|
||||||
|
NPRS_ID = [2];
|
||||||
|
MutingPattern1 = [];
|
||||||
|
MutingPattern2 = [];
|
||||||
|
MutingBitRepetition = 1;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
prs_config3 = (
|
||||||
|
{
|
||||||
|
gNB_id = 3;
|
||||||
|
NumPRSResources = 1;
|
||||||
|
PRSResourceSetPeriod = [20, 2];
|
||||||
|
SymbolStart = [7];
|
||||||
|
NumPRSSymbols = [6];
|
||||||
|
NumRB = 106;
|
||||||
|
RBOffset = 0;
|
||||||
|
CombSize = 4;
|
||||||
|
REOffset = [0];
|
||||||
|
PRSResourceOffset = [3];
|
||||||
|
PRSResourceRepetition = 1;
|
||||||
|
PRSResourceTimeGap = 1;
|
||||||
|
NPRS_ID = [3];
|
||||||
|
MutingPattern1 = [];
|
||||||
|
MutingPattern2 = [];
|
||||||
|
MutingBitRepetition = 1;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
+2
-1
@@ -268,9 +268,10 @@ def ExecuteActionWithParam(action, ctx, node):
|
|||||||
|
|
||||||
elif action == 'Custom_Script':
|
elif action == 'Custom_Script':
|
||||||
script = test.findtext('script')
|
script = test.findtext('script')
|
||||||
|
args = test.findtext('args')
|
||||||
# Allow referencing repository workspace path in XML via %%workspace%%
|
# Allow referencing repository workspace path in XML via %%workspace%%
|
||||||
script = script.replace("%%workspace%%", CONTAINERS.eNBSourceCodePath)
|
script = script.replace("%%workspace%%", CONTAINERS.eNBSourceCodePath)
|
||||||
success = cls_oaicitest.Custom_Script(HTML, node, script)
|
success = cls_oaicitest.Custom_Script(HTML, node, script, args)
|
||||||
|
|
||||||
elif action == 'Pull_Cluster_Image':
|
elif action == 'Pull_Cluster_Image':
|
||||||
tag_prefix = test.findtext('tag_prefix') or ""
|
tag_prefix = test.findtext('tag_prefix') or ""
|
||||||
|
|||||||
+89
@@ -0,0 +1,89 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
[[ $# -lt 1 ]] && { echo "Usage: $0 <distance_in_meters...>"; exit 1; }
|
||||||
|
DISTANCES=("$@")
|
||||||
|
|
||||||
|
IP=192.168.71.150
|
||||||
|
PORT=8091
|
||||||
|
NCAT_TIMEOUT=1 #s
|
||||||
|
SLEEP_WAIT=4 #s
|
||||||
|
MAX_RETRIES=3
|
||||||
|
|
||||||
|
set_and_verify_distance() {
|
||||||
|
local distance=$1
|
||||||
|
echo "Testing PRS ToA estimation for distance: $distance m"
|
||||||
|
|
||||||
|
# it seems that grep returns immediately with this syntax, but not echo | ncat | grep
|
||||||
|
# so prefer this to receive new distance immediately. We use --idle to keep
|
||||||
|
# ncat open for some additional time
|
||||||
|
local setdist_resp="$(grep --max-count 1 new_offset <(echo rfsimu setdistance rfsimu_channel_enB0 $distance | ncat --idle ${NCAT_TIMEOUT} ${IP} ${PORT}))"
|
||||||
|
echo "> response: ${setdist_resp}"
|
||||||
|
|
||||||
|
local gettoa_resp="$(echo "ciUE get_max_dl_toa" | ncat ${IP} ${PORT} | grep "UE max PRS DL ToA")"
|
||||||
|
echo "> response: ${gettoa_resp}"
|
||||||
|
|
||||||
|
[[ -z "$setdist_resp" || -z "$gettoa_resp" ]] && return 1
|
||||||
|
|
||||||
|
# Extract ToA values
|
||||||
|
[[ "$setdist_resp" =~ new_offset\ ([0-9]+) ]] && local set_toa="${BASH_REMATCH[1]}" || { echo "> Set ToA extraction failed for distance: $distance m"; return 1; }
|
||||||
|
|
||||||
|
[[ "$gettoa_resp" =~ UE\ max\ PRS\ DL\ ToA\ ([0-9]+) ]] && local est_toa="${BASH_REMATCH[1]}" || { echo "> Estimated ToA extraction failed for distance: $distance m"; return 1; }
|
||||||
|
|
||||||
|
# Compare extracted ToA values
|
||||||
|
[[ $set_toa == $est_toa ]] && echo "PRS SUCCESS for distance: $distance m" || { echo "PRS FAILURE for distance: $distance m (Actual ToA=$set_toa, Estimated ToA=$est_toa)" ; return 1; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
test_distance() {
|
||||||
|
local distance=$1 retries=0
|
||||||
|
|
||||||
|
# retry loop incase we didn't receive the response
|
||||||
|
while (( retries < MAX_RETRIES )); do
|
||||||
|
echo " Attempt $((retries + 1))/$MAX_RETRIES"
|
||||||
|
|
||||||
|
# Always reset to 0 m before testing target distance
|
||||||
|
if ! set_and_verify_distance 0; then
|
||||||
|
echo " Set distance 0 m failed during attempt $((retries + 1))"
|
||||||
|
else
|
||||||
|
sleep "$SLEEP_WAIT"
|
||||||
|
# Now test the actual target distance
|
||||||
|
if set_and_verify_distance "$distance"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
((retries++))
|
||||||
|
if (( retries < MAX_RETRIES )); then
|
||||||
|
sleep "$SLEEP_WAIT"
|
||||||
|
else
|
||||||
|
echo " ERROR: No valid response after $MAX_RETRIES retries for distance: $distance m"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
num_success=0
|
||||||
|
num_fail=0
|
||||||
|
|
||||||
|
for d in "${DISTANCES[@]}"; do
|
||||||
|
if test_distance "$d"; then
|
||||||
|
((num_success++))
|
||||||
|
else
|
||||||
|
((num_fail++))
|
||||||
|
fi
|
||||||
|
sleep "$SLEEP_WAIT"
|
||||||
|
done
|
||||||
|
|
||||||
|
# ---- Summary ----
|
||||||
|
echo
|
||||||
|
echo "==================== SUMMARY ===================="
|
||||||
|
echo "Total tests run : ${#DISTANCES[@]}"
|
||||||
|
echo "Successful tests: ${num_success}"
|
||||||
|
echo "Failed tests : ${num_fail}"
|
||||||
|
echo "================================================="
|
||||||
|
|
||||||
|
if [ $num_success -gt 0 ]; then
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
<!--
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
-->
|
||||||
|
<testCaseList>
|
||||||
|
<htmlTabRef>rfsim-5gnr-prs</htmlTabRef>
|
||||||
|
<htmlTabName>Monolithic gNB with PRS</htmlTabName>
|
||||||
|
<htmlTabIcon>wrench</htmlTabIcon>
|
||||||
|
<TestCaseRequestedList>
|
||||||
|
111111
|
||||||
|
800813
|
||||||
|
000012
|
||||||
|
000013
|
||||||
|
040001
|
||||||
|
040023
|
||||||
|
100011
|
||||||
|
222222
|
||||||
|
</TestCaseRequestedList>
|
||||||
|
<TestCaseExclusionList></TestCaseExclusionList>
|
||||||
|
|
||||||
|
<testCase id="111111">
|
||||||
|
<class>Pull_Local_Registry</class>
|
||||||
|
<desc>Pull Images from Local Registry</desc>
|
||||||
|
<node>localhost</node>
|
||||||
|
<images>oai-gnb-asan oai-nr-ue-asan</images>
|
||||||
|
</testCase>
|
||||||
|
|
||||||
|
<testCase id="800813">
|
||||||
|
<class>Create_Workspace</class>
|
||||||
|
<desc>Create new Workspace</desc>
|
||||||
|
<node>localhost</node>
|
||||||
|
</testCase>
|
||||||
|
|
||||||
|
<testCase id="000012">
|
||||||
|
<class>Deploy_Object</class>
|
||||||
|
<desc>Deploy OAI 5G gNB+UE RF sim SA</desc>
|
||||||
|
<node>localhost</node>
|
||||||
|
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_prs</yaml_path>
|
||||||
|
<services>oai-gnb oai-nr-ue</services>
|
||||||
|
</testCase>
|
||||||
|
|
||||||
|
<testCase id="000013">
|
||||||
|
<class>Attach_UE</class>
|
||||||
|
<desc>Attach OAI UE (Wait for IP)</desc>
|
||||||
|
<id>rfsim5g_ue</id>
|
||||||
|
<node>localhost</node>
|
||||||
|
</testCase>
|
||||||
|
|
||||||
|
<testCase id="040001">
|
||||||
|
<class>IdleSleep</class>
|
||||||
|
<desc>Sleep</desc>
|
||||||
|
<idle_sleep_time_in_sec>2</idle_sleep_time_in_sec>
|
||||||
|
</testCase>
|
||||||
|
|
||||||
|
<testCase id="040023">
|
||||||
|
<class>Custom_Script</class>
|
||||||
|
<always_exec>true</always_exec>
|
||||||
|
<desc>Set and verify distance at 50, 100, 150 m</desc>
|
||||||
|
<node>localhost</node>
|
||||||
|
<script>scripts/set-and-verify-distance-prs.sh</script>
|
||||||
|
<args>50 100 150</args>
|
||||||
|
</testCase>
|
||||||
|
|
||||||
|
<testCase id="100011">
|
||||||
|
<class>Undeploy_Object</class>
|
||||||
|
<always_exec>true</always_exec>
|
||||||
|
<desc>Undeploy all OAI 5G stack</desc>
|
||||||
|
<node>localhost</node>
|
||||||
|
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_prs</yaml_path>
|
||||||
|
<d_retx_th>30,100,100,100</d_retx_th>
|
||||||
|
<u_retx_th>30,100,100,100</u_retx_th>
|
||||||
|
</testCase>
|
||||||
|
|
||||||
|
<testCase id="222222">
|
||||||
|
<class>Clean_Test_Server_Images</class>
|
||||||
|
<always_exec>true</always_exec>
|
||||||
|
<desc>Clean Test Images on Test Server</desc>
|
||||||
|
<node>localhost</node>
|
||||||
|
<images>oai-gnb-asan oai-nr-ue-asan</images>
|
||||||
|
</testCase>
|
||||||
|
|
||||||
|
</testCaseList>
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
services:
|
||||||
|
oai-gnb:
|
||||||
|
image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop}
|
||||||
|
container_name: rfsim5g-oai-gnb
|
||||||
|
cap_drop:
|
||||||
|
- ALL
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN # for interface bringup
|
||||||
|
- NET_RAW # for ping
|
||||||
|
environment:
|
||||||
|
USE_ADDITIONAL_OPTIONS: --phy-test --rfsim -E
|
||||||
|
--log_config.global_log_options level,nocolor,time
|
||||||
|
ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0
|
||||||
|
networks:
|
||||||
|
public_net:
|
||||||
|
ipv4_address: 192.168.71.140
|
||||||
|
devices:
|
||||||
|
- /dev/net/tun:/dev/net/tun
|
||||||
|
volumes:
|
||||||
|
- ../../conf_files/gnb.sa.band78.106prb.rfsim.prs.conf:/opt/oai-gnb/etc/gnb.conf
|
||||||
|
- rrc.config:/opt/oai-gnb/
|
||||||
|
healthcheck:
|
||||||
|
test: /bin/bash -c "pgrep nr-softmodem"
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
|
oai-nr-ue:
|
||||||
|
image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop}
|
||||||
|
container_name: rfsim5g-oai-nr-ue
|
||||||
|
cap_drop:
|
||||||
|
- ALL
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN # for interface bringup
|
||||||
|
- NET_RAW # for ping
|
||||||
|
environment:
|
||||||
|
USE_ADDITIONAL_OPTIONS: --phy-test --rfsim -E
|
||||||
|
--reconfig-file etc/rrc/reconfig.raw --rbconfig-file etc/rrc/rbconfig.raw
|
||||||
|
--rfsimulator.serveraddr 192.168.71.140
|
||||||
|
--log_config.global_log_options level,nocolor,time
|
||||||
|
--telnetsrv --telnetsrv.listenaddr 192.168.71.150 --telnetsrv.listenport 8091
|
||||||
|
--telnetsrv.shrmod ciUE
|
||||||
|
ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0
|
||||||
|
devices:
|
||||||
|
- /dev/net/tun:/dev/net/tun
|
||||||
|
volumes:
|
||||||
|
- ../../conf_files/nrue.band78.106prb.prs.conf:/opt/oai-nr-ue/etc/nr-ue.conf
|
||||||
|
- rrc.config:/opt/oai-nr-ue/etc/rrc/
|
||||||
|
depends_on:
|
||||||
|
- oai-gnb
|
||||||
|
networks:
|
||||||
|
public_net:
|
||||||
|
ipv4_address: 192.168.71.150
|
||||||
|
healthcheck:
|
||||||
|
test: /bin/bash -c "pgrep nr-uesoftmodem"
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
rrc.config:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
public_net:
|
||||||
|
driver: bridge
|
||||||
|
name: rfsim5g-oai-public-net
|
||||||
|
ipam:
|
||||||
|
config:
|
||||||
|
- subnet: 192.168.71.128/26
|
||||||
|
driver_opts:
|
||||||
|
com.docker.network.bridge.name: "rfsim5g-public"
|
||||||
@@ -37,6 +37,8 @@
|
|||||||
#include "openair2/LAYER2/NR_MAC_UE/mac_defs.h"
|
#include "openair2/LAYER2/NR_MAC_UE/mac_defs.h"
|
||||||
#include "openair2/LAYER2/NR_MAC_UE/mac_proto.h"
|
#include "openair2/LAYER2/NR_MAC_UE/mac_proto.h"
|
||||||
#include "openair2/RRC/NR_UE/rrc_proto.h"
|
#include "openair2/RRC/NR_UE/rrc_proto.h"
|
||||||
|
#include "openair1/PHY/phy_extern_nr_ue.h"
|
||||||
|
#include "openair1/PHY/defs_nr_common.h"
|
||||||
|
|
||||||
#define TELNETSERVERCODE
|
#define TELNETSERVERCODE
|
||||||
#include "telnetsrv.h"
|
#include "telnetsrv.h"
|
||||||
@@ -110,6 +112,26 @@ static int force_deregistration(char *buf, int debug, telnet_printfunc_t prnt)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern float get_prs_max_dl_toa(prs_meas_t *prs_meas);
|
||||||
|
static int get_dl_toa(char *buf, int debug, telnet_printfunc_t prnt)
|
||||||
|
{
|
||||||
|
// TODO multiple antennas, resources, gNBs?
|
||||||
|
int gNB_id = 0;
|
||||||
|
int rsc_id = 0;
|
||||||
|
int ant = 0;
|
||||||
|
|
||||||
|
PHY_VARS_NR_UE *UE = PHY_vars_UE_g[0][0];
|
||||||
|
if (!UE || !UE->prs_vars[gNB_id])
|
||||||
|
ERROR_MSG_RET("no UE/prs_vars found!\n");
|
||||||
|
NR_PRS_RESOURCE_t *prs_res = &UE->prs_vars[gNB_id]->prs_resource[rsc_id];
|
||||||
|
if (!prs_res->prs_meas || !prs_res->prs_meas[ant])
|
||||||
|
ERROR_MSG_RET("prs_meas not initialized!\n");
|
||||||
|
|
||||||
|
float max = get_prs_max_dl_toa(prs_res->prs_meas[ant]);
|
||||||
|
prnt("UE max PRS DL ToA %.3f\n", max);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Telnet shell command definitions */
|
/* Telnet shell command definitions */
|
||||||
static telnetshell_cmddef_t cicmds[] = {
|
static telnetshell_cmddef_t cicmds[] = {
|
||||||
{"sync_state", "[UE_ID(int,opt)]", get_sync_state},
|
{"sync_state", "[UE_ID(int,opt)]", get_sync_state},
|
||||||
@@ -117,6 +139,7 @@ static telnetshell_cmddef_t cicmds[] = {
|
|||||||
{"force_RRC_IDLE", "", force_RRC_IDLE},
|
{"force_RRC_IDLE", "", force_RRC_IDLE},
|
||||||
{"force_crnti_ra", "", force_crnti_ra},
|
{"force_crnti_ra", "", force_crnti_ra},
|
||||||
{"deregistration", "", force_deregistration},
|
{"deregistration", "", force_deregistration},
|
||||||
|
{"get_max_dl_toa", "[ant]", get_dl_toa},
|
||||||
{"", "", NULL},
|
{"", "", NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -157,6 +157,9 @@ void init_nr_prs_ue_vars(PHY_VARS_NR_UE *ue)
|
|||||||
for (int j=0; j<fp->nb_antennas_rx; j++) {
|
for (int j=0; j<fp->nb_antennas_rx; j++) {
|
||||||
prs_vars[idx]->prs_resource[k].prs_meas[j] = malloc16_clear(sizeof(prs_meas_t));
|
prs_vars[idx]->prs_resource[k].prs_meas[j] = malloc16_clear(sizeof(prs_meas_t));
|
||||||
AssertFatal((prs_vars[idx]->prs_resource[k].prs_meas[j]!=NULL), "%s: PRS measurements malloc failed for gNB_id %d, rx_ant %d\n", __FUNCTION__, idx, j);
|
AssertFatal((prs_vars[idx]->prs_resource[k].prs_meas[j]!=NULL), "%s: PRS measurements malloc failed for gNB_id %d, rx_ant %d\n", __FUNCTION__, idx, j);
|
||||||
|
prs_meas_t *m = prs_vars[idx]->prs_resource[k].prs_meas[j];
|
||||||
|
m->next_dl_toa = m->dl_toa;
|
||||||
|
pthread_mutex_init(&m->dl_toa_mtx, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,12 +47,12 @@
|
|||||||
#define NO_INTERP 1
|
#define NO_INTERP 1
|
||||||
|
|
||||||
/* Generic function to find the peak of channel estimation buffer */
|
/* Generic function to find the peak of channel estimation buffer */
|
||||||
void peak_estimator(int32_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t *peak_val, int32_t mean_val)
|
void peak_estimator(c16_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t *peak_val, int32_t mean_val)
|
||||||
{
|
{
|
||||||
int32_t max_val = 0, max_idx = 0, abs_val = 0;
|
int32_t max_val = 0, max_idx = 0, abs_val = 0;
|
||||||
for(int k = 0; k < buf_len; k++)
|
for(int k = 0; k < buf_len; k++)
|
||||||
{
|
{
|
||||||
abs_val = squaredMod(((c16_t*)buffer)[k]);
|
abs_val = squaredMod(buffer[k]);
|
||||||
if(abs_val > max_val)
|
if(abs_val > max_val)
|
||||||
{
|
{
|
||||||
max_val = abs_val;
|
max_val = abs_val;
|
||||||
@@ -71,6 +71,32 @@ void peak_estimator(int32_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_prs_dl_toa(prs_meas_t *prs_meas, float dl_toa)
|
||||||
|
{
|
||||||
|
int rc = pthread_mutex_lock(&prs_meas->dl_toa_mtx);
|
||||||
|
AssertFatal(rc == 0, "pthread_mutex_lock() failed: errno %d, %s\n", errno, strerror(errno));
|
||||||
|
*prs_meas->next_dl_toa++ = dl_toa;
|
||||||
|
if (prs_meas->next_dl_toa >= prs_meas->dl_toa + sizeofArray(prs_meas->dl_toa))
|
||||||
|
prs_meas->next_dl_toa = prs_meas->dl_toa;
|
||||||
|
LOG_D(NR_PHY, "next_dl_toa %p\n", prs_meas->next_dl_toa);
|
||||||
|
rc = pthread_mutex_unlock(&prs_meas->dl_toa_mtx);
|
||||||
|
AssertFatal(rc == 0, "pthread_mutex_unlock() failed: errno %d, %s\n", errno, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
float get_prs_max_dl_toa(prs_meas_t *prs_meas)
|
||||||
|
{
|
||||||
|
float max = 0.0f;
|
||||||
|
int rc = pthread_mutex_lock(&prs_meas->dl_toa_mtx);
|
||||||
|
AssertFatal(rc == 0, "pthread_mutex_lock() failed: errno %d, %s\n", errno, strerror(errno));
|
||||||
|
for (int i = 0; i < sizeofArray(prs_meas->dl_toa); ++i) {
|
||||||
|
max = cmax(max, prs_meas->dl_toa[i]);
|
||||||
|
LOG_I(NR_PHY, "i %d dl_toa %.3f max %.3f\n", i, prs_meas->dl_toa[i], max);
|
||||||
|
}
|
||||||
|
rc = pthread_mutex_unlock(&prs_meas->dl_toa_mtx);
|
||||||
|
AssertFatal(rc == 0, "pthread_mutex_unlock() failed: errno %d, %s\n", errno, strerror(errno));
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
int nr_prs_channel_estimation(uint8_t gNB_id,
|
int nr_prs_channel_estimation(uint8_t gNB_id,
|
||||||
uint8_t rsc_id,
|
uint8_t rsc_id,
|
||||||
uint8_t rep_num,
|
uint8_t rep_num,
|
||||||
@@ -83,8 +109,8 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
|
|||||||
prs_config_t *prs_cfg = &ue->prs_vars[gNB_id]->prs_resource[rsc_id].prs_cfg;
|
prs_config_t *prs_cfg = &ue->prs_vars[gNB_id]->prs_resource[rsc_id].prs_cfg;
|
||||||
prs_meas_t **prs_meas = ue->prs_vars[gNB_id]->prs_resource[rsc_id].prs_meas;
|
prs_meas_t **prs_meas = ue->prs_vars[gNB_id]->prs_resource[rsc_id].prs_meas;
|
||||||
c16_t ch_tmp_buf[ ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32)));
|
c16_t ch_tmp_buf[ ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32)));
|
||||||
int32_t chF_interpol[frame_params->nb_antennas_rx][NR_PRS_IDFT_OVERSAMP_FACTOR*ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32)));
|
c16_t chF_interpol[frame_params->nb_antennas_rx][NR_PRS_IDFT_OVERSAMP_FACTOR*ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32)));
|
||||||
int32_t chT_interpol[frame_params->nb_antennas_rx][NR_PRS_IDFT_OVERSAMP_FACTOR*ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32)));
|
c16_t chT_interpol[frame_params->nb_antennas_rx][NR_PRS_IDFT_OVERSAMP_FACTOR*ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32)));
|
||||||
memset(ch_tmp_buf,0,sizeof(ch_tmp_buf));
|
memset(ch_tmp_buf,0,sizeof(ch_tmp_buf));
|
||||||
memset(chF_interpol,0,sizeof(chF_interpol));
|
memset(chF_interpol,0,sizeof(chF_interpol));
|
||||||
memset(chT_interpol,0,sizeof(chF_interpol));
|
memset(chT_interpol,0,sizeof(chF_interpol));
|
||||||
@@ -315,10 +341,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
|
|||||||
|
|
||||||
//Start pilot
|
//Start pilot
|
||||||
c16_t ch = c16MulConjShift(*pil, *rxF, 15);
|
c16_t ch = c16MulConjShift(*pil, *rxF, 15);
|
||||||
multadd_real_vector_complex_scalar(fl,
|
multadd_real_vector_complex_scalar(fl, ch, ch_tmp, 16);
|
||||||
ch,
|
|
||||||
ch_tmp,
|
|
||||||
16);
|
|
||||||
|
|
||||||
// SNR & RSRP estimation
|
// SNR & RSRP estimation
|
||||||
rsrp += squaredMod(*rxF);
|
rsrp += squaredMod(*rxF);
|
||||||
@@ -331,10 +354,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
|
|||||||
k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size;
|
k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size;
|
||||||
rxF = &rxdataF[rxAnt][l * frame_params->ofdm_symbol_size + k];
|
rxF = &rxdataF[rxAnt][l * frame_params->ofdm_symbol_size + k];
|
||||||
ch = c16MulConjShift(*pil, *rxF, 15);
|
ch = c16MulConjShift(*pil, *rxF, 15);
|
||||||
multadd_real_vector_complex_scalar(fml,
|
multadd_real_vector_complex_scalar(fml, ch, ch_tmp, 16);
|
||||||
ch,
|
|
||||||
ch_tmp,
|
|
||||||
16);
|
|
||||||
|
|
||||||
// SNR & RSRP estimation
|
// SNR & RSRP estimation
|
||||||
rsrp += squaredMod(*rxF);
|
rsrp += squaredMod(*rxF);
|
||||||
@@ -352,10 +372,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
|
|||||||
for(int pIdx = 2; pIdx < num_pilots-2; pIdx++)
|
for(int pIdx = 2; pIdx < num_pilots-2; pIdx++)
|
||||||
{
|
{
|
||||||
c16_t ch = c16MulConjShift(*pil, *rxF, 15);
|
c16_t ch = c16MulConjShift(*pil, *rxF, 15);
|
||||||
multadd_real_vector_complex_scalar(fmm,
|
multadd_real_vector_complex_scalar(fmm, ch, ch_tmp, 16);
|
||||||
ch,
|
|
||||||
ch_tmp,
|
|
||||||
16);
|
|
||||||
|
|
||||||
// SNR & RSRP estimation
|
// SNR & RSRP estimation
|
||||||
rsrp += squaredMod(*rxF);
|
rsrp += squaredMod(*rxF);
|
||||||
@@ -372,10 +389,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
|
|||||||
|
|
||||||
//End pilot
|
//End pilot
|
||||||
ch = c16MulConjShift(*pil, *rxF, 15);
|
ch = c16MulConjShift(*pil, *rxF, 15);
|
||||||
multadd_real_vector_complex_scalar(fmr,
|
multadd_real_vector_complex_scalar(fmr, ch, ch_tmp, 16);
|
||||||
ch,
|
|
||||||
ch_tmp,
|
|
||||||
16);
|
|
||||||
|
|
||||||
// SNR & RSRP estimation
|
// SNR & RSRP estimation
|
||||||
rsrp += squaredMod(*rxF);
|
rsrp += squaredMod(*rxF);
|
||||||
@@ -388,10 +402,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
|
|||||||
k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size;
|
k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size;
|
||||||
rxF = &rxdataF[rxAnt][l * frame_params->ofdm_symbol_size + k];
|
rxF = &rxdataF[rxAnt][l * frame_params->ofdm_symbol_size + k];
|
||||||
ch = c16MulConjShift(*pil, *rxF, 15);
|
ch = c16MulConjShift(*pil, *rxF, 15);
|
||||||
multadd_real_vector_complex_scalar(fr,
|
multadd_real_vector_complex_scalar(fr, ch, ch_tmp, 16);
|
||||||
ch,
|
|
||||||
ch_tmp,
|
|
||||||
16);
|
|
||||||
|
|
||||||
// SNR & RSRP estimation
|
// SNR & RSRP estimation
|
||||||
rsrp += squaredMod(*rxF);
|
rsrp += squaredMod(*rxF);
|
||||||
@@ -435,9 +446,9 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
|
|||||||
|
|
||||||
// Place PRS channel estimates in FFT shifted format
|
// Place PRS channel estimates in FFT shifted format
|
||||||
if(first_half > 0)
|
if(first_half > 0)
|
||||||
memcpy((int16_t *)&chF_interpol[rxAnt][start_offset], &ch_tmp[0], first_half * sizeof(int32_t));
|
memcpy(&chF_interpol[rxAnt][start_offset], &ch_tmp[0], first_half * sizeof(c16_t));
|
||||||
if(second_half > 0)
|
if(second_half > 0)
|
||||||
memcpy((int16_t *)&chF_interpol[rxAnt][0], &ch_tmp[first_half << 1], second_half * sizeof(int32_t));
|
memcpy(&chF_interpol[rxAnt][0], &ch_tmp[first_half], second_half * sizeof(c16_t));
|
||||||
|
|
||||||
// Convert to time domain
|
// Convert to time domain
|
||||||
freq2time(NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size,
|
freq2time(NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size,
|
||||||
@@ -463,9 +474,9 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
|
|||||||
prs_meas[rxAnt]->slot = proc->nr_slot_rx;
|
prs_meas[rxAnt]->slot = proc->nr_slot_rx;
|
||||||
prs_meas[rxAnt]->rxAnt_idx = rxAnt;
|
prs_meas[rxAnt]->rxAnt_idx = rxAnt;
|
||||||
prs_meas[rxAnt]->dl_aoa = rsc_id;
|
prs_meas[rxAnt]->dl_aoa = rsc_id;
|
||||||
prs_meas[rxAnt]->dl_toa = prs_toa / (float)NR_PRS_IDFT_OVERSAMP_FACTOR;
|
float dl_toa = prs_toa / (float)NR_PRS_IDFT_OVERSAMP_FACTOR;
|
||||||
if ((frame_params->ofdm_symbol_size - prs_meas[rxAnt]->dl_toa) < frame_params->ofdm_symbol_size / 2)
|
if ((frame_params->ofdm_symbol_size - dl_toa) < frame_params->ofdm_symbol_size / 2)
|
||||||
prs_meas[rxAnt]->dl_toa -= (frame_params->ofdm_symbol_size);
|
dl_toa -= (frame_params->ofdm_symbol_size);
|
||||||
LOG_I(PHY,
|
LOG_I(PHY,
|
||||||
"[gNB %d][rsc %d][Rx %d][sfn %d][slot %d] DL PRS ToA ==> %.1f / %d samples, peak channel power %.1f dBm, SNR %+.1f dB, rsrp %+.1f dBm\n",
|
"[gNB %d][rsc %d][Rx %d][sfn %d][slot %d] DL PRS ToA ==> %.1f / %d samples, peak channel power %.1f dBm, SNR %+.1f dB, rsrp %+.1f dBm\n",
|
||||||
gNB_id,
|
gNB_id,
|
||||||
@@ -473,12 +484,14 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
|
|||||||
rxAnt,
|
rxAnt,
|
||||||
proc->frame_rx,
|
proc->frame_rx,
|
||||||
proc->nr_slot_rx,
|
proc->nr_slot_rx,
|
||||||
prs_meas[rxAnt]->dl_toa,
|
dl_toa,
|
||||||
frame_params->ofdm_symbol_size,
|
frame_params->ofdm_symbol_size,
|
||||||
ch_pwr_dbm,
|
ch_pwr_dbm,
|
||||||
prs_meas[rxAnt]->snr,
|
prs_meas[rxAnt]->snr,
|
||||||
prs_meas[rxAnt]->rsrp_dBm);
|
prs_meas[rxAnt]->rsrp_dBm);
|
||||||
|
|
||||||
|
set_prs_dl_toa(prs_meas[rxAnt], dl_toa);
|
||||||
|
|
||||||
#ifdef DEBUG_PRS_CHEST
|
#ifdef DEBUG_PRS_CHEST
|
||||||
sprintf(filename, "%s%i%s", "PRSpilot_", rxAnt, ".m");
|
sprintf(filename, "%s%i%s", "PRSpilot_", rxAnt, ".m");
|
||||||
LOG_M(filename, "prs_loc", mod_prs, num_pilots, 1, 1);
|
LOG_M(filename, "prs_loc", mod_prs, num_pilots, 1, 1);
|
||||||
@@ -496,7 +509,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
|
|||||||
// T tracer dump
|
// T tracer dump
|
||||||
T(T_UE_PHY_INPUT_SIGNAL, T_INT(gNB_id),
|
T(T_UE_PHY_INPUT_SIGNAL, T_INT(gNB_id),
|
||||||
T_INT(proc->frame_rx), T_INT(proc->nr_slot_rx),
|
T_INT(proc->frame_rx), T_INT(proc->nr_slot_rx),
|
||||||
T_INT(rxAnt), T_BUFFER(&rxdataF[rxAnt][0], frame_params->samples_per_slot_wCP*sizeof(int32_t)));
|
T_INT(rxAnt), T_BUFFER(&rxdataF[rxAnt][0], frame_params->samples_per_slot_wCP*sizeof(c16_t)));
|
||||||
|
|
||||||
T(T_UE_PHY_DL_CHANNEL_ESTIMATE_FREQ,
|
T(T_UE_PHY_DL_CHANNEL_ESTIMATE_FREQ,
|
||||||
T_INT(gNB_id),
|
T_INT(gNB_id),
|
||||||
@@ -504,7 +517,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
|
|||||||
T_INT(proc->frame_rx),
|
T_INT(proc->frame_rx),
|
||||||
T_INT(proc->nr_slot_rx),
|
T_INT(proc->nr_slot_rx),
|
||||||
T_INT(rxAnt),
|
T_INT(rxAnt),
|
||||||
T_BUFFER(&chF_interpol[rxAnt][0], NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size * sizeof(int32_t)));
|
T_BUFFER(&chF_interpol[rxAnt][0], NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size * sizeof(c16_t)));
|
||||||
|
|
||||||
T(T_UE_PHY_DL_CHANNEL_ESTIMATE,
|
T(T_UE_PHY_DL_CHANNEL_ESTIMATE,
|
||||||
T_INT(gNB_id),
|
T_INT(gNB_id),
|
||||||
@@ -512,7 +525,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
|
|||||||
T_INT(proc->frame_rx),
|
T_INT(proc->frame_rx),
|
||||||
T_INT(proc->nr_slot_rx),
|
T_INT(proc->nr_slot_rx),
|
||||||
T_INT(rxAnt),
|
T_INT(rxAnt),
|
||||||
T_BUFFER(&chT_interpol[rxAnt][0], NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size * sizeof(int32_t)));
|
T_BUFFER(&chT_interpol[rxAnt][0], NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size * sizeof(c16_t)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
|
|||||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||||
|
|
||||||
/* Generic function to find the peak of channel estimation buffer */
|
/* Generic function to find the peak of channel estimation buffer */
|
||||||
void peak_estimator(int32_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t *peak_val, int32_t mean_val);
|
void peak_estimator(c16_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t *peak_val, int32_t mean_val);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief This function performs channel estimation including frequency and temporal interpolation
|
\brief This function performs channel estimation including frequency and temporal interpolation
|
||||||
|
|||||||
@@ -38,6 +38,8 @@
|
|||||||
#include "impl_defs_nr.h"
|
#include "impl_defs_nr.h"
|
||||||
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
|
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
#define MAX_NUM_SUBCARRIER_SPACING 5
|
#define MAX_NUM_SUBCARRIER_SPACING 5
|
||||||
#define NR_MAX_OFDM_SYMBOL_SIZE 8192
|
#define NR_MAX_OFDM_SYMBOL_SIZE 8192
|
||||||
|
|
||||||
@@ -312,7 +314,10 @@ typedef struct {
|
|||||||
int32_t sfn;
|
int32_t sfn;
|
||||||
int8_t slot;
|
int8_t slot;
|
||||||
int8_t rxAnt_idx;
|
int8_t rxAnt_idx;
|
||||||
float dl_toa;
|
pthread_mutex_t dl_toa_mtx; // protect reading of max from write
|
||||||
|
// circular buffer to be able to read maximum of last estimations
|
||||||
|
float dl_toa[128]; // set through set_prs_dl_toa()
|
||||||
|
float *next_dl_toa;
|
||||||
int32_t dl_aoa;
|
int32_t dl_aoa;
|
||||||
float snr;
|
float snr;
|
||||||
float rsrp;
|
float rsrp;
|
||||||
|
|||||||
Reference in New Issue
Block a user