Merge remote-tracking branch 'origin/nr_prs' into integration_2022_wk40

This commit is contained in:
Robert Schmidt
2022-10-05 15:31:28 +02:00
57 changed files with 10077 additions and 138 deletions
+27
View File
@@ -713,6 +713,32 @@ file(GLOB F1AP_C_FILES ${F1AP_DIR}/*.c)
add_library(F1AP ${F1AP_C_FILES} )
# LPP
##############
set(LPP_DIR ${OPENAIR3_DIR}/LPP)
set(LPP_ASN_DIR ${LPP_DIR}/MESSAGES)
set(LPP_ASN_FILES
${LPP_ASN_DIR}/37355-g60.asn
)
set(LPP_ASN_GENERATED_C_DIR ${asn1_generated_dir}/LPP)
set(lpp_cmd ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "LPP_" "-findirect-choice -fno-include-deps" "${LPP_ASN_GENERATED_C_DIR}")
compile_asn1("${LPP_ASN_FILES}" "${lpp_cmd}" lpp_flag)
file(GLOB LPP_ASN_GENERATED_C_FILES ${LPP_ASN_GENERATED_C_DIR}/*.c)
add_library(LPP_LIB
${LPP_ASN_GENERATED_C_FILES}
)
add_dependencies (LPP_LIB lpp_flag)
include_directories ("${LPP_ASN_GENERATED_C_DIR}")
include_directories ("${LPP_DIR}")
#file(GLOB LPP_C_FILES ${LPP_DIR}/*.c)
#add_library(LPP ${LPP_C_FILES} )
# Hardware dependant options
###################################
add_list1_option(NB_ANTENNAS_RX "4" "Number of antennas in reception" "1" "2" "4")
@@ -1610,6 +1636,7 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/INIT/nr_init.c
${OPENAIR1_DIR}/PHY/INIT/nr_parms.c
${OPENAIR1_DIR}/PHY/MODULATION/nr_modulation.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prs.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_pss.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sss.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_pbch.c
+9 -1
View File
@@ -105,6 +105,10 @@ ID = GNB_PHY_PRACH_INPUT_SIGNAL
DESC = gNodeB input data in the time domain for slots with PRACH detection
GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB
FORMAT = int,frame : int,slot : int,antenna : buffer,rxdata
ID = GNB_PHY_DL_OUTPUT_SIGNAL
DESC = gNodeB output data in the freq domain for slots
GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB
FORMAT = int,gNB_ID : int,frame : int,slot : int,antenna : buffer,txdata
#MAC logs
ID = ENB_MAC_UE_DL_SDU
@@ -1305,7 +1309,11 @@ ID = UE_PHY_INPUT_SIGNAL
ID = UE_PHY_DL_CHANNEL_ESTIMATE
DESC = UE channel estimation in the time domain
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
FORMAT = int,eNB_ID : int,frame : int,subframe : int,antenna : buffer,chest_t
FORMAT = int,eNB_ID : int,rsc_id : int,frame : int,subframe : int,antenna : buffer,chest_t
ID = UE_PHY_DL_CHANNEL_ESTIMATE_FREQ
DESC = UE channel estimation in the frequency domain
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
FORMAT = int,eNB_ID : int,rsc_id : int,frame : int,subframe : int,antenna : buffer,chestF_t
ID = UE_PHY_PDCCH_IQ
DESC = UE PDCCH received IQ data
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
+54
View File
@@ -0,0 +1,54 @@
#!/bin/bash
: ${1?"Usage: $0 [-g num_gnb] [-n num_rsc] [-f filename] [-c count]"}
# Usage info
show_help()
{
echo "
Usage of script with arguments: [-g num_gnb] [-n num_rsc] [-f filename] [-c count]
-g num_gnb Number of active gNBs
-n num_rsc Number of PRS resources
-f filename T tracer recorded .raw filename
-c count Number of dump instances to be extacted
For Example: ./extract_prs_dumps.sh -g 1 -n 8 -f fr2_64_prbs.raw -c 100
-h Help
"
exit 0
}
while getopts g:n:f:c:h flag
do
case "${flag}" in
g) num_gnb=${OPTARG};;
n) num_rsc=${OPTARG};;
f) file=${OPTARG};;
c) count=${OPTARG};;
h) show_help;;
*) exit -1;;
esac
done
echo "num_gnb: $num_gnb";
echo "num_rsc: $num_rsc";
echo "filename: $file";
echo "count: $count";
for (( i = 0; i < $num_gnb; i++ ))
do
for (( j = 0; j < $num_rsc; j++ ))
do
name=chF_gnb${i}_${j}.raw
echo "Extracting $name"
./extract -d ../T_messages.txt $file UE_PHY_DL_CHANNEL_ESTIMATE_FREQ chestF_t -f eNB_ID $i -f rsc_id $j -o $name -count $count
name=chT_gnb${i}_${j}.raw
echo "Extracting $name"
./extract -d ../T_messages.txt $file UE_PHY_DL_CHANNEL_ESTIMATE chest_t -f eNB_ID $i -f rsc_id $j -o $name -count $count
done
done
# zip the extracted dumps
name=prs_dumps.tgz
tar cvzf $name chF_gnb* chT_gnb*
echo "created a zip file $name"
+17 -3
View File
@@ -664,10 +664,26 @@ void get_samplerate_and_bw(int mu,
}
} else if (mu == 3) {
switch(n_rb) {
case 66:
case 132:
case 128:
if (threequarter_fs) {
*sample_rate=184.32e6;
*samples_per_frame = 1843200;
*tx_bw = 200e6;
*rx_bw = 200e6;
} else {
*sample_rate = 245.76e6;
*samples_per_frame = 2457600;
*tx_bw = 200e6;
*rx_bw = 200e6;
}
break;
case 66:
case 64:
if (threequarter_fs) {
*sample_rate=92.16e6;
*samples_per_frame = 921600;
*tx_bw = 100e6;
*rx_bw = 100e6;
} else {
@@ -676,7 +692,6 @@ void get_samplerate_and_bw(int mu,
*tx_bw = 100e6;
*rx_bw = 100e6;
}
break;
case 32:
@@ -691,7 +706,6 @@ void get_samplerate_and_bw(int mu,
*tx_bw = 50e6;
*rx_bw = 50e6;
}
break;
default:
+9
View File
@@ -298,6 +298,10 @@ The following features are valid for the gNB and the 5G-NR UE.
- SRS signal reception
- Channel estimation (with T tracer real time monitoring)
- Power noise estimation
* NR-PRS
- Rel16 Positioning reference signal(PRS) generation and modulation
- Multiple PRS resources, one per beam is supported in FR2 TDD mode
- FR1 and FR2 support with config file
* NR-PRACH
- Formats 0,1,2,3, A1-A3, B1-B3
* Highly efficient 3GPP compliant LDPC encoder and decoder (BG1 and BG2 are supported)
@@ -459,6 +463,11 @@ The following features are valid for the gNB and the 5G-NR UE.
* NR-SRS
- Generation of sequence at PHY
- SRS signal transmission
* NR-PRS
- PRS based Channel estimation with T tracer dumps
- Time of arrival(ToA) estimation based on channel impulse response(CIR)
- Finer ToA estimation by 16x oversampled IDFT for CIR
- Support for multiple gNB reception with gNBs synced via GPSDO
* NR-PRACH
- Formats 0,1,2,3, A1-A3, B1-B3
* SS-RSRP
+190
View File
@@ -0,0 +1,190 @@
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<a href="http://www.openairinterface.org/">
<img src="./images/oai_final_logo.png" alt="" border=3 height=50 width=150>
</img>
</a>
</td>
<td style="border-collapse: collapse; border: none; vertical-align: center;">
<b><font size = "8">Running NR PRS with OAI gNB and nrUE</font></b>
</td>
</tr>
</table>
This page is valid on tags starting from **`2022.w37`**.
After you have [built the softmodem executables](BUILD.md), go to the build directory `openairinterface5g/cmake_targets/ran_build/build/` and start testing the Rel16 PRS usecases.
# PRS parameters and config files
| **Mode** | **gNB config** | **nrUE config** |
|----------------------------- |------------------------------------------------------------------------------------------- |--------------------------- |
| **FR1 40MHz<br>30kHz SCS** | gnb0.sa.band78.fr1.106PRB.prs.usrpx310.conf<br>gnb1.sa.band78.fr1.106PRB.prs.usrpx310.conf | ue.nr.prs.fr1.106prb.conf |
| **FR2 100MHz<br>120kHz SCS** | gnb0.sa.band261.fr2.64PRB.prs.usrpx310.conf<br>gnb1.sa.band261.fr2.64PRB.prs.usrpx310.conf | ue.nr.prs.fr2.64prb.conf |
Under gNB and nrUE config files, parameters are configured under `prs_config` section. nrUE is capable to receive downlink PRS signal from multiple gNB simultaneously and therefore nrUE config file contains multiple `prs_config` sections, corresponding to each gNB. These parameters can be changed as per the test scenario.
As of now, PRS **Comb size of 2 and 4** is supported and validated with R&S Spectrum analyzer. Also Muting is NOT supported yet. Sample configuration as below:
```
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;
}
);
```
To TURN OFF PRS, set `NumPRSResources=0` in gNB `prs_config` section. nrUE config has `Active_gNBs` to specify number of active gNBs transmitting PRS signal simultaneously. Find the help string for PRS parameters in `openair2/COMMON/prs_nr_paramdef.h` <br><br>
# gNB in `phy-test` mode
Note that `numactl` is only needed if you run on a NUMA architecture with more than 1 CPU. In this case it should be installed on Linux using command `sudo apt-get install -y numactl`
Also check the numa nodes USRP’s are connected to, using the following command:
```cat /sys/class/net/eth_if/device/numa_node```
Where `eth_if` has to be replaced with the name of the network interface the USRP is connected to.
In our case the output is 0 and hence we use `numactl --cpunodebind=0 --membind=0`
## FR1 test
Open a terminal on the host machine, and execute below command to launch gNB with **X310 USRPs**
```sudo numactl --cpunodebind=0 --membind=0 ./nr-softmodem -E -O../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.sa.band78.fr1.106PRB.prs.usrpx310.conf --phy-test```
If **N310 USRPs** are used, then run above command `without -E option` i.e without 3/4 sampling rate.<br><br>
To run using **rfsimulator**, execute following command:
```sudo RFSIMULATOR=server ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.sa.band78.fr1.106PRB.prs.usrpx310.conf --parallel-config PARALLEL_SINGLE_THREAD --noS1 --nokrnmod 1 --rfsim --phy-test --lowmem```
## FR2 test
In FR2 mode, we need RF beamforming module to transmit signal in mmWave frequency range. **X310 USRPs** can be used with BasicTx daughtercard to transmit baseband signal at **Intermediate Frequncy(IF)** and then RF beamforming module would perform beamforming and the upconversion to FR2 frequencies. IF can be specified using `if_freq` in the RU section of gNB config.
If RF beamforming module is NOT present, gNB can still be launched with USRP alone; to transmit at supported `if_freq`.
```sudo numactl --cpunodebind=0 --membind=0 ./nr-softmodem -E -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.sa.band261.fr2.64PRB.prs.usrpx310.conf --phy-test```<br><br>
To run using **rfsimulator**, execute following command:
```sudo RFSIMULATOR=server ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.sa.band261.fr2.64PRB.prs.usrpx310.conf --parallel-config PARALLEL_SINGLE_THREAD --noS1 --nokrnmod 1 --rfsim --phy-test --lowmem```
## Multiple gNB scenario
PRS is primarily used for positioning and localization of the UE with multiple gNBs transmitting simultaneously. OAI PRS implementation supports multiple gNB transmission provided all the gNBs are tightely synchronized using GPSDO clock. Therefore before running this scenario, make sure the USRPs has built-in GPSDO and the GPS antennas are connected with good satellite visibility. Also every time a gNB is launched, wait until `GPS LOCKED` is printed on the terminal during gNB startup. If USRP fails to lock with GPSDO, try again until its locked.
To use GPSDO, make sure to change `clock_source` and `time_source` to `gpsdo` in RU section of gNB config.
```sudo numactl --cpunodebind=0 --membind=0 ./nr-softmodem -E -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.band78.fr1.106PRB.prs.usrpx310.conf --phy-test```
```sudo numactl --cpunodebind=1 --membind=1 ./nr-softmodem -E -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb1.band78.fr1.106PRB.prs.usrpx310.conf --phy-test```<br><br>
# nrUE in `phy-test` mode
While running gNB and nrUE on the same host machine, `reconfig.raw` and `rbconfig.raw` files would be generated with the launch of gNB and and then nrUE would automatically source it from build directory. However, if gNB and nrUE are running on two different host machines, then run gNB first with the corresponding config and exit after few seconds. This would generate `reconfig.raw` and `rbconfig.raw` files.
After this, nrUE can be launched using one of the below commands depending on the test scenario. If UE is NOT able to connect to the gNB, then check the USRP connections or try increasing `--ue-rxgain` in steps of 10dB.
Also check the instructions on `numactl` in gNB test section as it applies for nrUE execution as well.
## FR1 test
Once gNB is up and running, open another terminal and execute below command to launch nrUE with **X310 USRPs**. Make sure to specify `IP_ADDR1` and `IP_ADDR2`(optional) correctly as per USRPs IP address
```sudo numactl --cpunodebind=0 --membind=0 ./nr-uesoftmodem -E --phy-test --usrp-args "addr=IP_ADDR1,second_addr=IP_ADDR2,time_source=internal,clock_source=internal" -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.nr.prs.fr1.106prb.conf --ue-rxgain 80 --ue-fo-compensation --non-stop```
If **N310 USRPs** are used, then run above command `without -E option` i.e without 3/4 sampling rate.<br><br>
To run using **rfsimulator** with local ETH IF `127.0.0.1`, execute following command:
```sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --nokrnmod 1 --rfsim --phy-test --noS1 -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.nr.prs.fr1.106prb.conf```
## FR2 test
Like gNB, RF beamforming module is receiving at mmWave frequencies and then **X310 USRPs** with BasicRx daughtercard to receive the signal at intermediate frequncy(IF) from RF beamforming module. IF can be specified using `--if_freq` option in nrUE command line.
If RF beamforming module is NOT present, nrUE can still be launched with USRP alone; to receive at `if_freq` and validation can be done. Make sure to specify `if_freq` in the range supported by USRP nrUE is running with.
```sudo numactl --cpunodebind=0 --membind=0 ./nr-uesoftmodem -E --phy-test -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.nr.prs.fr2.64prb.conf --usrp-args "addr=IP_ADDR1,second_addr=IP_ADDR2,time_source=internal,clock_source=internal" --ue-rxgain 80 --ue-fo-compensation --if_freq 50000000 --non-stop```<br><br>
To run using **rfsimulator** with local ETH IF `127.0.0.1`, execute following command:
```sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --nokrnmod 1 --rfsim --phy-test --noS1 -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.nr.prs.fr2.64prb.conf```
## Multiple gNB scenario
In nrUE prs config file, change `Active_gNBs` to the actual number of gNBs launched. Also verify the parameter in `prs_config` sections of nrUE config is matching with that of gNB config used. And launch nrUE using one of the above commands depending on FR1/FR2 test scenario.
After successful connection, UE starts estimating channel based on the downlink PRS pilots using Least-Squares(LS) method. In the frequency domain, linear interpolation is used to reconstruct the channel over entire PRS bandwidth using LS estimates at pilot locations. UE also measures Time of Arrival(ToA) based on the time domain impulse response. On the console, ToA measurement is printed for each PRS resource.
```
[PHY] [gNB 0][rsc 0][Rx 0][sfn 314][slot 2] DL PRS ToA ==> 1 / 1024 samples, peak channel power 15.6 dBm, SNR +4 dB
[PHY] [gNB 0][rsc 1][Rx 0][sfn 314][slot 12] DL PRS ToA ==> 1 / 1024 samples, peak channel power 15.6 dBm, SNR +4 dB
[PHY] [gNB 0][rsc 2][Rx 0][sfn 314][slot 22] DL PRS ToA ==> 1 / 1024 samples, peak channel power 15.6 dBm, SNR +4 dB
[PHY] [gNB 0][rsc 3][Rx 0][sfn 314][slot 32] DL PRS ToA ==> 1 / 1024 samples, peak channel power 15.6 dBm, SNR +4 dB
```
At UE side, T tracer is used to dump PRS channel estimates, both in time and frequency domain using `UE_PHY_DL_CHANNEL_ESTIMATE` and `UE_PHY_DL_CHANNEL_ESTIMATE_FREQ` respectively. These dumps can be enabled using options `--T_stdout 0` without console prints or `--T_stdout 2` with console prints; in above nrUE launch command.<br><br>
# Recording T tracer dumps
Once nrUE is launched with `--T_stdout 0 or 2` option, open another terminal. Navigate to T tracer directory ```common/utils/T/tracer/``` and build the T tracer binary using ```make```
Once the build is successful, execute following command to start recording the PRS channel estimates dumps
```./record -d ../T_messages.txt -on LEGACY_PHY_INFO -on UE_PHY_DL_CHANNEL_ESTIMATE -on UE_PHY_DL_CHANNEL_ESTIMATE_FREQ -o prs_dumps.raw```
Exit using `Ctrl+C` to stop recording, else it will keep running and take lot of disk space. Generally running it for 1-2 minutes should collect sufficient dumps.<br><br>
To check the contents of recorded .raw file, replay it by executing:
```./replay -i prs_dumps.raw```
and textlog it on another terminal with following command:
```./textlog -d ../T_messages.txt -ON -no-gui```<br><br>
# Extracting PRS channel estimates
Once T tracer dumps are recorded, PRS channel estimates can be extracted from .raw file using bash script `extract_prs_dumps.sh` in T tracer directory ```common/utils/T/tracer/```
```./extract_prs_dumps.sh -g <num_gnb> -n <num_resources> -f <recorded .raw file> -c <count>```
In the end, the script will zip all the extracted dumps to `prs_dumps.tgz`. Make sure to check help in running script using -h option:
```./extract_prs_dumps.sh -h```<br><br>
# Using Matlab/Octave script to visualize PRS channel estimates
We have developed `plot_prs_Ttracer_dumps.m` script to visualize the extracted PRS dumps offline in Matlab/Octave. Location of the script is `openair1/PHY/NR_UE_ESTIMATION/plot_prs_Ttracer_dumps.m`
Make sure to enter the parameters script asks as input like below:
```
Enter the directory path to T tracer dumps: '<workspace>/openairinterface5g/common/utils/T/tracer'
Enter the OFDM FFT size used for file parsing: <frame_parms->ofdm_symbol_size>
Enter number of PRS respurces: <NumPRSResources>
Enter number of active gNBs: <Active_gNBs>
```
This script will read the IQ data from extracted PRS dumps(chF_gnbX_Y.raw and chT_gnbX_Y.raw) and plot them like below
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<img src="./images/PRS_CFR_FR2_64PRB_8rsc.PNG" alt="" border=1 height=400 width=500>
<img src="./images/PRS_CIR_FR2_64PRB_8rsc.PNG" alt="" border=1 height=400 width=500>
</img>
<figcaption align = "center"><b>Fig.1 - FR2 100MHz test</b></figcaption>
</td>
</tr>
</table>
Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

+2
View File
@@ -99,6 +99,8 @@
#define CONFIG_HLP_DISABLNBIOT "disable nb-iot, even if defined in config\n"
#define CONFIG_HLP_LDPC_OFFLOAD "enable LDPC offload\n"
#define CONFIG_HLP_USRP_ARGS "set the arguments to identify USRP (same syntax as in UHD)\n"
#define CONFIG_HLP_TX_SUBDEV "set the arguments to select tx_subdev (same syntax as in UHD)\n"
#define CONFIG_HLP_RX_SUBDEV "set the arguments to select rx_subdev (same syntax as in UHD)\n"
#define CONFIG_HLP_FLOG "Enable online log \n"
#define CONFIG_HLP_LOGL "Set the global log level, valid options: (4:trace, 3:debug, 2:info, 1:warn, (0:error))\n"
+7 -6
View File
@@ -34,6 +34,7 @@
#include "LAYER2/nr_pdcp/nr_pdcp_entity.h"
#include "SCHED_NR_UE/pucch_uci_ue_nr.h"
#include "openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h"
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
/*
* NR SLOT PROCESSING SEQUENCE
@@ -595,13 +596,13 @@ static void UE_synch(void *arg) {
UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
}
break;
case si:
default:
break;
}
break;
case si:
default:
break;
}
}
+4
View File
@@ -117,6 +117,8 @@ int vcdflag = 0;
double rx_gain_off = 0.0;
char *usrp_args = NULL;
char *tx_subdev = NULL;
char *rx_subdev = NULL;
char *rrc_config_path = NULL;
char *uecap_file = NULL;
int dumpframe = 0;
@@ -359,6 +361,8 @@ void init_openair0(void) {
openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file;
if (usrp_args) openair0_cfg[card].sdr_addrs = usrp_args;
if (tx_subdev) openair0_cfg[card].tx_subdev = tx_subdev;
if (rx_subdev) openair0_cfg[card].rx_subdev = rx_subdev;
}
}
+2 -1
View File
@@ -30,6 +30,8 @@
/*------------------------------------------------------------------------------------------------------------------------------------------*/
#define CMDLINE_NRUEPARAMS_DESC { \
{"usrp-args", CONFIG_HLP_USRP_ARGS, 0, strptr:&usrp_args, defstrval:"type=b200", TYPE_STRING, 0}, \
{"tx_subdev", CONFIG_HLP_TX_SUBDEV, 0, strptr:&tx_subdev, defstrval:NULL, TYPE_STRING, 0}, \
{"rx_subdev", CONFIG_HLP_RX_SUBDEV, 0, strptr:&rx_subdev, defstrval:NULL, TYPE_STRING, 0}, \
{"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \
{"dlsch-parallel", CONFIG_HLP_DLSCH_PARA, 0, u8ptr:NULL, defintval:0, TYPE_UINT8, 0}, \
{"offset-divisor", CONFIG_HLP_OFFSET_DIV, 0, uptr:&nrUE_params.ofdm_offset_divisor, defuintval:8, TYPE_UINT32, 0}, \
@@ -97,5 +99,4 @@ extern void start_oai_nrue_threads(void);
void *UE_thread(void *arg);
void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id, uint8_t abstraction_flag);
void init_nrUE_standalone_thread(int ue_idx);
#endif
+14
View File
@@ -615,6 +615,9 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB,
gNB->nr_csi_info->csi_gold_init = cfg->cell_config.phy_cell_id.value;
nr_init_csi_rs(&gNB->frame_parms, gNB->nr_csi_info->nr_gold_csi_rs, cfg->cell_config.phy_cell_id.value);
//PRS init
nr_init_prs(gNB);
for (int id=0; id<NUMBER_OF_NR_SRS_MAX; id++) {
gNB->nr_srs_info[id] = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t));
gNB->nr_srs_info[id]->srs_generated_signal = (int32_t**)malloc16_clear(MAX_NUM_NR_SRS_AP*sizeof(int32_t*));
@@ -793,6 +796,17 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB)
free_and_zero(common_vars->beam_id[i]);
}
for (int rsc=0; rsc < gNB->prs_vars.NumPRSResources; rsc++) {
for (int slot=0; slot<fp->slots_per_frame; slot++) {
for (int symb=0; symb<fp->symbols_per_slot; symb++) {
free_and_zero(gNB->nr_gold_prs[rsc][slot][symb]);
}
free_and_zero(gNB->nr_gold_prs[rsc][slot]);
}
free_and_zero(gNB->nr_gold_prs[rsc]);
}
free_and_zero(gNB->nr_gold_prs);
/* Do NOT free per-antenna txdataF/rxdataF: the gNB gets a pointer to the
* RU's txdataF/rxdataF, and the RU will free that */
free_and_zero(common_vars->txdataF);
+198
View File
@@ -33,6 +33,7 @@
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
#include "PHY/NR_REFSIG/nr_refsig.h"
#include "PHY/MODULATION/nr_modulation.h"
#include "openair2/COMMON/prs_nr_paramdef.h"
extern uint16_t beta_cqi[16];
@@ -135,6 +136,164 @@ void phy_term_nr_ue__PDSCH(NR_UE_PDSCH* pdsch, const NR_DL_FRAME_PARMS *const fp
free_and_zero(pdsch->ptrs_re_per_slot);
}
void RCconfig_nrUE_prs(void *cfg)
{
int j = 0, k = 0, gNB_id = 0;
char aprefix[MAX_OPTNAME_SIZE*2 + 8];
char str[7][100] = {'\0'}; int16_t n[7] = {0};
PHY_VARS_NR_UE *ue = (PHY_VARS_NR_UE *)cfg;
prs_config_t *prs_config = NULL;
paramlist_def_t gParamList = {CONFIG_STRING_PRS_LIST,NULL,0};
paramdef_t gParams[] = PRS_GLOBAL_PARAMS_DESC;
config_getlist( &gParamList,gParams,sizeof(gParams)/sizeof(paramdef_t), NULL);
if (gParamList.numelt > 0)
{
ue->prs_active_gNBs = *(gParamList.paramarray[j][PRS_ACTIVE_GNBS_IDX].uptr);
}
else
{
LOG_E(PHY,"%s configuration NOT found..!! Skipped configuring UE for the PRS reception\n", CONFIG_STRING_PRS_CONFIG);
}
paramlist_def_t PRS_ParamList = {{0},NULL,0};
for(int i = 0; i < ue->prs_active_gNBs; i++)
{
paramdef_t PRS_Params[] = PRS_PARAMS_DESC;
sprintf(PRS_ParamList.listname, "%s%i", CONFIG_STRING_PRS_CONFIG, i);
sprintf(aprefix, "%s.[%i]", CONFIG_STRING_PRS_LIST, 0);
config_getlist( &PRS_ParamList,PRS_Params,sizeof(PRS_Params)/sizeof(paramdef_t), aprefix);
if (PRS_ParamList.numelt > 0) {
for (j = 0; j < PRS_ParamList.numelt; j++) {
gNB_id = *(PRS_ParamList.paramarray[j][PRS_GNB_ID].uptr);
if(gNB_id != i) gNB_id = i; // force gNB_id to avoid mismatch
memset(n,0,sizeof(n));
ue->prs_vars[gNB_id]->NumPRSResources = *(PRS_ParamList.paramarray[j][NUM_PRS_RESOURCES].uptr);
for (k = 0; k < ue->prs_vars[gNB_id]->NumPRSResources; k++)
{
prs_config = &ue->prs_vars[gNB_id]->prs_resource[k].prs_cfg;
prs_config->PRSResourceSetPeriod[0] = PRS_ParamList.paramarray[j][PRS_RESOURCE_SET_PERIOD_LIST].uptr[0];
prs_config->PRSResourceSetPeriod[1] = PRS_ParamList.paramarray[j][PRS_RESOURCE_SET_PERIOD_LIST].uptr[1];
// per PRS resources parameters
prs_config->SymbolStart = PRS_ParamList.paramarray[j][PRS_SYMBOL_START_LIST].uptr[k];
prs_config->NumPRSSymbols = PRS_ParamList.paramarray[j][PRS_NUM_SYMBOLS_LIST].uptr[k];
prs_config->REOffset = PRS_ParamList.paramarray[j][PRS_RE_OFFSET_LIST].uptr[k];
prs_config->NPRSID = PRS_ParamList.paramarray[j][PRS_ID_LIST].uptr[k];
prs_config->PRSResourceOffset = PRS_ParamList.paramarray[j][PRS_RESOURCE_OFFSET_LIST].uptr[k];
// Common parameters to all PRS resources
prs_config->NumRB = *(PRS_ParamList.paramarray[j][PRS_NUM_RB].uptr);
prs_config->RBOffset = *(PRS_ParamList.paramarray[j][PRS_RB_OFFSET].uptr);
prs_config->CombSize = *(PRS_ParamList.paramarray[j][PRS_COMB_SIZE].uptr);
prs_config->PRSResourceRepetition = *(PRS_ParamList.paramarray[j][PRS_RESOURCE_REPETITION].uptr);
prs_config->PRSResourceTimeGap = *(PRS_ParamList.paramarray[j][PRS_RESOURCE_TIME_GAP].uptr);
prs_config->MutingBitRepetition = *(PRS_ParamList.paramarray[j][PRS_MUTING_BIT_REPETITION].uptr);
for (int l = 0; l < PRS_ParamList.paramarray[j][PRS_MUTING_PATTERN1_LIST].numelt; l++)
{
prs_config->MutingPattern1[l] = PRS_ParamList.paramarray[j][PRS_MUTING_PATTERN1_LIST].uptr[l];
if (k == 0) // print only for 0th resource
n[5] += snprintf(str[5]+n[5],sizeof(str[5]),"%d, ",prs_config->MutingPattern1[l]);
}
for (int l = 0; l < PRS_ParamList.paramarray[j][PRS_MUTING_PATTERN2_LIST].numelt; l++)
{
prs_config->MutingPattern2[l] = PRS_ParamList.paramarray[j][PRS_MUTING_PATTERN2_LIST].uptr[l];
if (k == 0) // print only for 0th resource
n[6] += snprintf(str[6]+n[6],sizeof(str[6]),"%d, ",prs_config->MutingPattern2[l]);
}
// print to buffer
n[0] += snprintf(str[0]+n[0],sizeof(str[0]),"%d, ",prs_config->SymbolStart);
n[1] += snprintf(str[1]+n[1],sizeof(str[1]),"%d, ",prs_config->NumPRSSymbols);
n[2] += snprintf(str[2]+n[2],sizeof(str[2]),"%d, ",prs_config->REOffset);
n[3] += snprintf(str[3]+n[3],sizeof(str[3]),"%d, ",prs_config->PRSResourceOffset);
n[4] += snprintf(str[4]+n[4],sizeof(str[4]),"%d, ",prs_config->NPRSID);
} // for k
prs_config = &ue->prs_vars[gNB_id]->prs_resource[0].prs_cfg;
LOG_I(PHY, "-----------------------------------------\n");
LOG_I(PHY, "PRS Config for gNB_id %d @ %p\n", gNB_id, prs_config);
LOG_I(PHY, "-----------------------------------------\n");
LOG_I(PHY, "NumPRSResources \t%d\n", ue->prs_vars[gNB_id]->NumPRSResources);
LOG_I(PHY, "PRSResourceSetPeriod \t[%d, %d]\n", prs_config->PRSResourceSetPeriod[0], prs_config->PRSResourceSetPeriod[1]);
LOG_I(PHY, "NumRB \t\t\t%d\n", prs_config->NumRB);
LOG_I(PHY, "RBOffset \t\t%d\n", prs_config->RBOffset);
LOG_I(PHY, "CombSize \t\t%d\n", prs_config->CombSize);
LOG_I(PHY, "PRSResourceRepetition \t%d\n", prs_config->PRSResourceRepetition);
LOG_I(PHY, "PRSResourceTimeGap \t%d\n", prs_config->PRSResourceTimeGap);
LOG_I(PHY, "MutingBitRepetition \t%d\n", prs_config->MutingBitRepetition);
LOG_I(PHY, "SymbolStart \t\t[%s\b\b]\n", str[0]);
LOG_I(PHY, "NumPRSSymbols \t\t[%s\b\b]\n", str[1]);
LOG_I(PHY, "REOffset \t\t[%s\b\b]\n", str[2]);
LOG_I(PHY, "PRSResourceOffset \t[%s\b\b]\n", str[3]);
LOG_I(PHY, "NPRS_ID \t\t[%s\b\b]\n", str[4]);
LOG_I(PHY, "MutingPattern1 \t\t[%s\b\b]\n", str[5]);
LOG_I(PHY, "MutingPattern2 \t\t[%s\b\b]\n", str[6]);
LOG_I(PHY, "-----------------------------------------\n");
}
}
else
{
LOG_E(PHY,"No %s configuration found..!!\n", PRS_ParamList.listname);
}
}
}
void init_nr_prs_ue_vars(PHY_VARS_NR_UE *ue)
{
NR_UE_PRS **const prs_vars = ue->prs_vars;
NR_DL_FRAME_PARMS *const fp = &ue->frame_parms;
// PRS vars init
for(int idx = 0; idx < NR_MAX_PRS_COMB_SIZE; idx++)
{
prs_vars[idx] = (NR_UE_PRS *)malloc16_clear(sizeof(NR_UE_PRS));
// PRS channel estimates
for(int k = 0; k < NR_MAX_PRS_RESOURCES_PER_SET; k++)
{
prs_vars[idx]->prs_resource[k].prs_meas = (prs_meas_t **)malloc16_clear( fp->nb_antennas_rx*sizeof(prs_meas_t *) );
AssertFatal((prs_vars[idx]->prs_resource[k].prs_meas!=NULL), "%s: PRS measurements malloc failed for gNB_id %d\n", __FUNCTION__, idx);
for (int j=0; j<fp->nb_antennas_rx; j++) {
prs_vars[idx]->prs_resource[k].prs_meas[j] = (prs_meas_t *)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);
}
}
}
// load the config file params
RCconfig_nrUE_prs(ue);
//PRS sequence init
ue->nr_gold_prs = (uint32_t *****)malloc16(ue->prs_active_gNBs*sizeof(uint32_t ****));
uint32_t *****prs = ue->nr_gold_prs;
AssertFatal(prs!=NULL, "%s: positioning reference signal malloc failed\n", __FUNCTION__);
for (int gnb = 0; gnb < ue->prs_active_gNBs; gnb++) {
prs[gnb] = (uint32_t ****)malloc16(ue->prs_vars[gnb]->NumPRSResources*sizeof(uint32_t ***));
AssertFatal(prs[gnb]!=NULL, "%s: positioning reference signal for gnb %d - malloc failed\n", __FUNCTION__, gnb);
for (int rsc = 0; rsc < ue->prs_vars[gnb]->NumPRSResources; rsc++) {
prs[gnb][rsc] = (uint32_t ***)malloc16(fp->slots_per_frame*sizeof(uint32_t **));
AssertFatal(prs[gnb][rsc]!=NULL, "%s: positioning reference signal for gnb %d rsc %d- malloc failed\n", __FUNCTION__, gnb, rsc);
for (int slot=0; slot<fp->slots_per_frame; slot++) {
prs[gnb][rsc][slot] = (uint32_t **)malloc16(fp->symbols_per_slot*sizeof(uint32_t *));
AssertFatal(prs[gnb][rsc][slot]!=NULL, "%s: positioning reference signal for gnb %d rsc %d slot %d - malloc failed\n", __FUNCTION__, gnb, rsc, slot);
for (int symb=0; symb<fp->symbols_per_slot; symb++) {
prs[gnb][rsc][slot][symb] = (uint32_t *)malloc16(NR_MAX_PRS_INIT_LENGTH_DWORD*sizeof(uint32_t));
AssertFatal(prs[gnb][rsc][slot][symb]!=NULL, "%s: positioning reference signal for gnb %d rsc %d slot %d symbol %d - malloc failed\n", __FUNCTION__, gnb, rsc, slot, symb);
} // for symb
} // for slot
} // for rsc
} // for gnb
init_nr_gold_prs(ue);
}
int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
{
// create shortcuts
@@ -193,6 +352,14 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
///////////
////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////// PRS init /////////////////////////
///////////
init_nr_prs_ue_vars(ue);
///////////
////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////PUSCH DMRS init/////////////////////////
///////////
@@ -482,6 +649,37 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
free_and_zero(ue->prach_vars[gNB_id]);
}
for (int gnb = 0; gnb < ue->prs_active_gNBs; gnb++)
{
for (int rsc = 0; rsc < ue->prs_vars[gnb]->NumPRSResources; rsc++)
{
for (int slot=0; slot<fp->slots_per_frame; slot++)
{
for (int symb=0; symb<fp->symbols_per_slot; symb++)
{
free_and_zero(ue->nr_gold_prs[gnb][rsc][slot][symb]);
}
free_and_zero(ue->nr_gold_prs[gnb][rsc][slot]);
}
free_and_zero(ue->nr_gold_prs[gnb][rsc]);
}
free_and_zero(ue->nr_gold_prs[gnb]);
}
free_and_zero(ue->nr_gold_prs);
for(int idx = 0; idx < NR_MAX_PRS_COMB_SIZE; idx++)
{
for(int k = 0; k < NR_MAX_PRS_RESOURCES_PER_SET; k++)
{
for (int j=0; j<fp->nb_antennas_rx; j++)
{
free_and_zero(ue->prs_vars[idx]->prs_resource[k].prs_meas[j]);
}
free_and_zero(ue->prs_vars[idx]->prs_resource[k].prs_meas);
}
free_and_zero(ue->prs_vars[idx]);
}
free_and_zero(ue->sinr_CQI_dB);
}
+2 -2
View File
@@ -212,12 +212,12 @@ uint32_t get_samples_per_slot(int slot, NR_DL_FRAME_PARMS* fp)
uint32_t get_slot_from_timestamp(openair0_timestamp timestamp_rx, NR_DL_FRAME_PARMS* fp)
{
uint32_t slot_idx = 0;
int samples_till_the_slot = 0;
int samples_till_the_slot = fp->get_samples_per_slot(slot_idx,fp)-1;
timestamp_rx = timestamp_rx%fp->samples_per_frame;
while (timestamp_rx > samples_till_the_slot) {
samples_till_the_slot += fp->get_samples_per_slot(slot_idx,fp);
slot_idx++;
samples_till_the_slot += fp->get_samples_per_slot(slot_idx,fp);
}
return slot_idx;
}
+3
View File
@@ -416,6 +416,9 @@ void fill_subframe_mask(PHY_VARS_eNB *eNB);
void init_DLSCH_struct(PHY_VARS_gNB *gNB, processingData_L1tx_t *msg);
void reset_DLSCH_struct(const PHY_VARS_gNB *gNB, processingData_L1tx_t *msg);
void RCconfig_nrUE_prs(void *cfg);
void init_nr_prs_ue_vars(PHY_VARS_NR_UE *ue);
/** @} */
#endif
@@ -701,7 +701,7 @@ int lte_dl_channel_estimation(PHY_VARS_UE *ue,
}
}
T(T_UE_PHY_DL_CHANNEL_ESTIMATE, T_INT(eNB_id),
T(T_UE_PHY_DL_CHANNEL_ESTIMATE, T_INT(eNB_id), T_INT(0),
T_INT(ue->proc.proc_rxtx[ue->current_thread_id[Ns>>1]].frame_rx%1024), T_INT(ue->proc.proc_rxtx[ue->current_thread_id[Ns>>1]].subframe_rx),
T_INT(0), T_BUFFER(&ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].dl_ch_estimates_time[eNB_offset][0][0], 512 * 4));
return(0);
+3 -21
View File
@@ -131,14 +131,6 @@ void lte_sync_time_free(void) {
}
static inline int abs32(int x) {
return (((int)((short*)&x)[0])*((int)((short*)&x)[0]) + ((int)((short*)&x)[1])*((int)((short*)&x)[1]));
}
static inline double absF(struct complexd x) {
return x.r*x.r+x.i*x.i;
}
#define complexNull(c) bzero((void*) &(c), sizeof(c))
#define SHIFT 17
@@ -196,16 +188,12 @@ int lte_sync_time(int **rxdata, ///rx data in time domain
// calculate the absolute value of sync_corr[n]
for (s=0; s<3; s++) {
double tmp = absF(sync_out[s]) + absF(sync_out2[s]);
double tmp = squaredMod(sync_out[s]) + squaredMod(sync_out2[s]);
if (tmp>peak_val) {
peak_val = tmp;
peak_pos = n;
sync_source = s;
/*
printf("s %d: n %d sync_out %d, sync_out2 %d (sync_corr %d,%d), (%d,%d) (%d,%d)\n",s,n,abs32(sync_out[s]),abs32(sync_out2[s]),sync_corr_ue0[n],
sync_corr_ue0[n+length],((int16_t*)&sync_out[s])[0],((int16_t*)&sync_out[s])[1],((int16_t*)&sync_out2[s])[0],((int16_t*)&sync_out2[s])[1]);
*/
}
}
}
@@ -337,7 +325,7 @@ int lte_sync_time_eNB(int32_t **rxdata, ///rx data in time domain
result = dot_product((short *)primary_synch_time, (short *) &(rxdata[ar][n]), frame_parms->ofdm_symbol_size, SHIFT);
//((short*)sync_corr)[2*n] += ((short*) &result)[0];
//((short*)sync_corr)[2*n+1] += ((short*) &result)[1];
sync_corr_eNB[n] += abs32(result);
sync_corr_eNB[n] += squaredMod(*(c16_t*)&result);
}
}
@@ -368,12 +356,6 @@ int lte_sync_time_eNB(int32_t **rxdata, ///rx data in time domain
}
static inline int64_t abs64(int64_t x) {
return (((int64_t)((int32_t *)&x)[0])*((int64_t)((int32_t *)&x)[0]) + ((int64_t)
((int32_t *)&x)[1])*((int64_t)((int32_t *)&x)[1]));
}
int ru_sync_time(RU_t *ru,
int64_t *lev,
int64_t *avg) {
@@ -426,7 +408,7 @@ int ru_sync_time(RU_t *ru,
shift);
}
dmrs_corr += abs64(result);
dmrs_corr += squaredMod(*(c32_t*)&result);
}
if (ru->dmrs_corr != NULL)
+4
View File
@@ -153,6 +153,10 @@ void PHY_ofdm_mod(int *input, /// pointer to complex input
idftsize = IDFT_512;
break;
case 768:
idftsize = IDFT_768;
break;
case 1024:
idftsize = IDFT_1024;
break;
+53
View File
@@ -123,3 +123,56 @@ void nr_gold_pusch(PHY_VARS_gNB* gNB, int nscid, uint32_t nid) {
}
}
}
void nr_init_prs(PHY_VARS_gNB* gNB)
{
unsigned int x1, x2;
uint16_t Nid;
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
gNB->nr_gold_prs = (uint32_t ****)malloc16(gNB->prs_vars.NumPRSResources*sizeof(uint32_t ***));
uint32_t ****prs = gNB->nr_gold_prs;
AssertFatal(prs!=NULL, "NR init: positioning reference signal malloc failed\n");
for (int rsc=0; rsc < gNB->prs_vars.NumPRSResources; rsc++) {
prs[rsc] = (uint32_t ***)malloc16(fp->slots_per_frame*sizeof(uint32_t **));
AssertFatal(prs[rsc]!=NULL, "NR init: positioning reference signal for rsc %d - malloc failed\n", rsc);
for (int slot=0; slot<fp->slots_per_frame; slot++) {
prs[rsc][slot] = (uint32_t **)malloc16(fp->symbols_per_slot*sizeof(uint32_t *));
AssertFatal(prs[rsc][slot]!=NULL, "NR init: positioning reference signal for slot %d - malloc failed\n", slot);
for (int symb=0; symb<fp->symbols_per_slot; symb++) {
prs[rsc][slot][symb] = (uint32_t *)malloc16(NR_MAX_PRS_INIT_LENGTH_DWORD*sizeof(uint32_t));
AssertFatal(prs[rsc][slot][symb]!=NULL, "NR init: positioning reference signal for rsc %d slot %d symbol %d - malloc failed\n", rsc, slot, symb);
}
}
}
uint8_t reset;
uint8_t slotNum, symNum, rsc_id;
for (rsc_id = 0; rsc_id < gNB->prs_vars.NumPRSResources; rsc_id++) {
Nid = gNB->prs_vars.prs_cfg[rsc_id].NPRSID; // seed value
LOG_I(PHY, "Initiaized NR-PRS sequence with PRS_ID %3d for resource %d\n", Nid, rsc_id);
for (slotNum = 0; slotNum < fp->slots_per_frame; slotNum++) {
for (symNum = 0; symNum < fp->symbols_per_slot ; symNum++) {
reset = 1;
// initial x2 for prs as ts138.211
uint32_t c_init1, c_init2, c_init3;
uint32_t pow22=1<<22;
uint32_t pow10=1<<10;
c_init1 = pow22*ceil(Nid/1024);
c_init2 = pow10*(slotNum+symNum+1)*(2*(Nid%1024)+1);
c_init3 = Nid%1024;
x2 = c_init1 + c_init2 + c_init3;
for (uint8_t n=0; n<NR_MAX_PRS_INIT_LENGTH_DWORD; n++) {
gNB->nr_gold_prs[rsc_id][slotNum][symNum][n] = lte_gold_generic(&x1, &x2, reset);
reset = 0;
//printf("%d \n",gNB->nr_gold_prs[slotNum][symNum][n]);
}
}
}
}
}
+37
View File
@@ -124,3 +124,40 @@ void nr_init_pusch_dmrs(PHY_VARS_NR_UE* ue,
}
}
}
void init_nr_gold_prs(PHY_VARS_NR_UE* ue)
{
unsigned int x1, x2;
uint16_t Nid;
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
uint8_t reset;
uint8_t slotNum, symNum, gnb, rsc;
for(gnb = 0; gnb < ue->prs_active_gNBs; gnb++) {
for(rsc = 0; rsc < ue->prs_vars[gnb]->NumPRSResources; rsc++) {
Nid = ue->prs_vars[gnb]->prs_resource[rsc].prs_cfg.NPRSID; // seed value
LOG_I(PHY,"Initialised NR-PRS sequence with PRS_ID %3d for resource %d\n",Nid, rsc);
for (slotNum = 0; slotNum < fp->slots_per_frame; slotNum++) {
for (symNum = 0; symNum < fp->symbols_per_slot ; symNum++) {
reset = 1;
// initial x2 for prs as ts138.211
uint32_t c_init1, c_init2, c_init3;
uint32_t pow22=1<<22;
uint32_t pow10=1<<10;
c_init1 = pow22*ceil(Nid/1024);
c_init2 = pow10*(slotNum+symNum+1)*(2*(Nid%1024)+1);
c_init3 = Nid%1024;
x2 = c_init1 + c_init2 + c_init3;
for (uint8_t n=0; n<NR_MAX_PRS_INIT_LENGTH_DWORD; n++) {
ue->nr_gold_prs[gnb][rsc][slotNum][symNum][n] = lte_gold_generic(&x1, &x2, reset);
reset = 0;
//printf("%d \n",gNB->nr_gold_prs[slotNum][symNum][n]);
}
}
}
} // for rsc
} // for gnb
}
+7
View File
@@ -32,6 +32,13 @@
@param PHY_VARS_gNB* gNB structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables
*/
void nr_init_pbch_dmrs(PHY_VARS_gNB* gNB);
/*
This function generates NR Gold Sequence(ts 138.211) for the PRS.
@param PHY_VARS_gNB* gNB structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables
*/
void nr_init_prs(PHY_VARS_gNB* gNB);
/*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PDCCH DMRS.
@param PHY_VARS_gNB* gNB structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables
@param Nid is used for the initialization of x2, Physical cell Id by default or upper layer configured pdcch_scrambling_ID
+1
View File
@@ -68,5 +68,6 @@ void nr_init_pusch_dmrs(PHY_VARS_NR_UE* ue,
uint8_t n_scid);
void nr_init_csi_rs(const NR_DL_FRAME_PARMS *fp, uint32_t ***csi_rs, uint32_t Nid);
void init_nr_gold_prs(PHY_VARS_NR_UE* ue);
#endif
+77
View File
@@ -0,0 +1,77 @@
#include "PHY/defs_gNB.h"
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
#include "PHY/LTE_REFSIG/lte_refsig.h"
#include "PHY/NR_REFSIG/nr_refsig.h"
#include "PHY/sse_intrin.h"
//#define DEBUG_PRS_MOD
//#define DEBUG_PRS_MAP
extern short nr_qpsk_mod_table[8];
int nr_generate_prs(uint32_t **nr_gold_prs,
int32_t *txdataF,
int16_t amp,
prs_config_t *prs_cfg,
nfapi_nr_config_request_scf_t *config,
NR_DL_FRAME_PARMS *frame_parms)
{
int k_prime = 0, k = 0, idx;
int16_t mod_prs[NR_MAX_PRS_LENGTH<<1];
int16_t k_prime_table[K_PRIME_TABLE_ROW_SIZE][K_PRIME_TABLE_COL_SIZE] = PRS_K_PRIME_TABLE;
// PRS resource mapping with combsize=k which means PRS symbols exist in every k-th subcarrier in frequency domain
// According to ts138.211 sec.7.4.1.7.2
for (int l = prs_cfg->SymbolStart; l < prs_cfg->SymbolStart + prs_cfg->NumPRSSymbols; l++) {
int symInd = l-prs_cfg->SymbolStart;
if (prs_cfg->CombSize == 2) {
k_prime = k_prime_table[0][symInd];
}
else if (prs_cfg->CombSize == 4){
k_prime = k_prime_table[1][symInd];
}
else if (prs_cfg->CombSize == 6){
k_prime = k_prime_table[2][symInd];
}
else if (prs_cfg->CombSize == 12){
k_prime = k_prime_table[3][symInd];
}
k = (prs_cfg->REOffset+k_prime) % prs_cfg->CombSize + prs_cfg->RBOffset*12 + frame_parms->first_carrier_offset;
// QPSK modulation
for (int m = 0; m < (12/prs_cfg->CombSize) * prs_cfg->NumRB; m++) {
idx = (((nr_gold_prs[l][(m<<1)>>5])>>((m<<1)&0x1f))&3);
mod_prs[m<<1] = nr_qpsk_mod_table[idx<<1];
mod_prs[(m<<1)+1] = nr_qpsk_mod_table[(idx<<1) + 1];
#ifdef DEBUG_PRS_MOD
LOG_D("m %d idx %d gold seq %d mod_prs %d %d\n", m, idx, nr_gold_prs[l][(m<<1)>>5], mod_prs[m<<1], mod_prs[(m<<1)+1]);
#endif
#ifdef DEBUG_PRS_MAP
LOG_D("m %d at k %d of l %d reIdx %d\n", m, k, l, (l*frame_parms->ofdm_symbol_size + k)<<1);
#endif
((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_prs[m<<1]) >> 15;
((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_prs[(m<<1) + 1]) >> 15;
#ifdef DEBUG_PRS_MAP
LOG_D("(%d,%d)\n",
((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1],
((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1)+1]);
#endif
k = k + prs_cfg->CombSize;
if (k >= frame_parms->ofdm_symbol_size)
k-=frame_parms->ofdm_symbol_size;
}
}
#ifdef DEBUG_PRS_MAP
LOG_M("nr_prs.m", "prs",(int16_t *)&txdataF[prs_cfg->SymbolStart*frame_parms->ofdm_symbol_size],prs_cfg->NumPRSSymbols*frame_parms->ofdm_symbol_size, 1, 1);
#endif
return 0;
}
@@ -38,6 +38,14 @@
#define NR_PBCH_PDU_BITS 24
int nr_generate_prs(uint32_t **nr_gold_prs,
int32_t *txdataF,
int16_t amp,
prs_config_t *prs_cfg,
nfapi_nr_config_request_scf_t *config,
NR_DL_FRAME_PARMS *frame_parms);
/*!
\fn int nr_generate_pss
\brief Generation of the NR PSS
@@ -23,6 +23,9 @@
short filt16a_l0[16] = {
16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0,0};
short filt16a_mm0[16] = {
0,4096,8192,12288,16384,12288,8192,4096,0,0,0,0,0,0,0,0};
short filt16a_r0[16] = {
0,0,0,0,0,4096,8192,12288,16384,20480,24576,28672,0,0,0,0};
@@ -32,6 +35,15 @@ short filt16a_m0[16] = {
short filt16a_l1[16] = {
20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0};
short filt16a_mm1[16] = {
0,0,4096,8192,12288,16384,12288,8192,4096,0,0,0,0,0,0,0};
short filt16a_ml1[16] = {
-4096,0,4096,8192,12288,16384,12288,8192,4096,0,0,0,0,0,0,0};
short filt16a_mr1[16] = {
0,0,4096,8192,12288,16384,12288,8192,4096,0,-4096,-8192,0,0,0,0};
short filt16a_r1[16] = {
0,0,0,0,0,0,4096,8192,12288,16384,20480,24576,0,0,0,0};
@@ -41,6 +53,15 @@ short filt16a_m1[16] = {
short filt16a_l2[16] = {
24576,20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0};
short filt16a_mm2[16] = {
0,0,0,4096,8192,12288,16384,12288,8192,4096,0,0,0,0,0,0};
short filt16a_ml2[16] = {
-8192,-4096,0,4096,8192,12288,16384,12288,8192,4096,0,0,0,0,0,0};
short filt16a_mr2[16] = {
0,0,0,4096,8192,12288,16384,12288,8192,4096,0,-4096,0,0,0,0};
short filt16a_r2[16] = {
0,0,0,0,0,0,0,4096,8192,12288,16384,20480,0,0,0,0};
@@ -50,6 +71,12 @@ short filt16a_m2[16] = {
short filt16a_l3[16] = {
28672,24576,20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0};
short filt16a_mm3[16] = {
0,0,0,0,4096,8192,12288,16384,12288,8192,4096,0,0,0,0,0};
short filt16a_ml3[16] = {
-12288,-8192,-4096,0,4096,8192,12288,16384,12288,8192,4096,0,0,0,0,0};
short filt16a_r3[16] = {
0,0,0,0,0,0,0,0,4096,8192,12288,16384,0,0,0,0};
@@ -28,24 +28,42 @@ extern short filt16a_r0[16];
extern short filt16a_m0[16];
extern short filt16a_mm0[16];
extern short filt16a_l1[16];
extern short filt16a_r1[16];
extern short filt16a_m1[16];
extern short filt16a_mm1[16];
extern short filt16a_mr1[16];
extern short filt16a_ml1[16];
extern short filt16a_l2[16];
extern short filt16a_r2[16];
extern short filt16a_m2[16];
extern short filt16a_mm2[16];
extern short filt16a_mr2[16];
extern short filt16a_ml2[16];
extern short filt16a_l3[16];
extern short filt16a_r3[16];
extern short filt16a_m3[16];
extern short filt16a_mm3[16];
extern short filt16a_ml3[16];
extern short filt16a_l0_dc[16];
extern short filt16a_r0_dc[16];
@@ -28,12 +28,542 @@
#include "PHY/NR_REFSIG/dmrs_nr.h"
#include "PHY/NR_REFSIG/ptrs_nr.h"
#include "PHY/NR_TRANSPORT/nr_sch_dmrs.h"
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
#include "common/utils/nr/nr_common.h"
#include "filt16a_32.h"
#include "T.h"
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
//#define DEBUG_PDSCH
//#define DEBUG_PDCCH
//#define DEBUG_PBCH
//#define DEBUG_PRS_CHEST // To enable PRS Matlab dumps
//#define DEBUG_PRS_PRINTS // To enable PRS channel estimation debug logs
extern short nr_qpsk_mod_table[8];
int nr_prs_channel_estimation(uint8_t gNB_id,
uint8_t rsc_id,
uint8_t rep_num,
PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
NR_DL_FRAME_PARMS *frame_params)
{
uint8_t rxAnt = 0, idx = 0;
int32_t **rxdataF = ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF;
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;
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)));
int32_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(chF_interpol,0,sizeof(chF_interpol));
memset(chT_interpol,0,sizeof(chF_interpol));
int slot_prs = (proc->nr_slot_rx - rep_num*prs_cfg->PRSResourceTimeGap + frame_params->slots_per_frame)%frame_params->slots_per_frame;
uint32_t **nr_gold_prs = ue->nr_gold_prs[gNB_id][rsc_id][slot_prs];
int16_t *rxF, *pil, *fl, *fm, *fmm, *fml, *fmr, *fr, mod_prs[NR_MAX_PRS_LENGTH<<1];
int16_t ch[2] = {0}, noiseFig[2] = {0};
int16_t k_prime = 0, k = 0, re_offset = 0, first_half = 0, second_half = 0;
int32_t ch_pwr = 0, snr = 0;
#ifdef DEBUG_PRS_CHEST
char filename[64] = {0}, varname[64] = {0};
#endif
int16_t *ch_tmp = (int16_t *)ch_tmp_buf;
int16_t scale_factor = (1.0f/(float)(prs_cfg->NumPRSSymbols))*(1<<15);
int16_t num_pilots = (12/prs_cfg->CombSize)*prs_cfg->NumRB;
int16_t start_offset = (NR_PRS_IDFT_OVERSAMP_FACTOR-1)*frame_params->ofdm_symbol_size>>1;
int16_t k_prime_table[K_PRIME_TABLE_ROW_SIZE][K_PRIME_TABLE_COL_SIZE] = PRS_K_PRIME_TABLE;
for(int l = prs_cfg->SymbolStart; l < prs_cfg->SymbolStart+prs_cfg->NumPRSSymbols; l++)
{
int symInd = l-prs_cfg->SymbolStart;
if (prs_cfg->CombSize == 2) {
k_prime = k_prime_table[0][symInd];
}
else if (prs_cfg->CombSize == 4){
k_prime = k_prime_table[1][symInd];
}
else if (prs_cfg->CombSize == 6){
k_prime = k_prime_table[2][symInd];
}
else if (prs_cfg->CombSize == 12){
k_prime = k_prime_table[3][symInd];
}
#ifdef DEBUG_PRS_PRINTS
printf("[gNB %d][rsc %d] PRS config l %d k_prime %d:\nprs_cfg->SymbolStart %d\nprs_cfg->NumPRSSymbols %d\nprs_cfg->NumRB %d\nprs_cfg->CombSize %d\n", gNB_id, rsc_id, l, k_prime, prs_cfg->SymbolStart, prs_cfg->NumPRSSymbols, prs_cfg->NumRB, prs_cfg->CombSize);
#endif
// Pilots generation and modulation
for (int m = 0; m < num_pilots; m++)
{
idx = (((nr_gold_prs[l][(m<<1)>>5])>>((m<<1)&0x1f))&3);
mod_prs[m<<1] = nr_qpsk_mod_table[idx<<1];
mod_prs[(m<<1)+1] = nr_qpsk_mod_table[(idx<<1) + 1];
}
for (rxAnt=0; rxAnt < frame_params->nb_antennas_rx; rxAnt++)
{
snr = 0;
// calculate RE offset
k = re_offset = (prs_cfg->REOffset+k_prime) % prs_cfg->CombSize + prs_cfg->RBOffset*12 + frame_params->first_carrier_offset;
// Channel estimation and interpolation
pil = (int16_t *)&mod_prs[0];
rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k];
if(prs_cfg->CombSize == 2)
{
// Choose the interpolation filters
switch (k_prime) {
case 0:
fl = filt8_l0;
fml = filt8_m0;
fmm = filt8_mm0;
fmr = filt8_mr0;
fm = filt8_m0;
fr = filt8_r0;
break;
case 1:
fl = filt8_l1;
fmm = filt8_mm1;
fml = filt8_ml1;
fmr = fmm;
fm = filt8_m1;
fr = filt8_r1;
break;
default:
LOG_I(PHY, "%s: ERROR!! Invalid k_prime=%d for PRS comb_size %d, symbol %d\n",__FUNCTION__, k_prime, prs_cfg->CombSize, l);
return(-1);
break;
}
//Start pilot
ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15);
ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15);
multadd_real_vector_complex_scalar(fl,
ch,
ch_tmp,
8);
//SNR estimation
noiseFig[0] = rxF[0] - (int16_t)(((int32_t)ch[0]*pil[0] - (int32_t)ch[1]*pil[1])>>15);
noiseFig[1] = rxF[1] - (int16_t)(((int32_t)ch[1]*pil[0] + (int32_t)ch[0]*pil[1])>>15);
snr += 10*log10(squaredMod(*(c16_t*)rxF) - squaredMod(*(c16_t*)noiseFig)) - 10*log10(squaredMod(*(c16_t*)noiseFig));
#ifdef DEBUG_PRS_PRINTS
printf("[Rx %d] pilot %3d, SNR %+2d dB: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, %+d) \n", rxAnt, 0, snr, rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]);
#endif
pil +=2;
k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size;
rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k];
//Middle pilots
for(int pIdx = 1; pIdx < num_pilots-1; pIdx+=2)
{
ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15);
ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15);
if(pIdx == 1) // 2nd pilot
{
multadd_real_vector_complex_scalar(fml,
ch,
ch_tmp,
8);
}
else
{
multadd_real_vector_complex_scalar(fm,
ch,
ch_tmp,
8);
}
//SNR estimation
noiseFig[0] = rxF[0] - (int16_t)(((int32_t)ch[0]*pil[0] - (int32_t)ch[1]*pil[1])>>15);
noiseFig[1] = rxF[1] - (int16_t)(((int32_t)ch[1]*pil[0] + (int32_t)ch[0]*pil[1])>>15);
snr += 10*log10(squaredMod(*(c16_t*)rxF) - squaredMod(*(c16_t*)noiseFig)) - 10*log10(squaredMod(*(c16_t*)noiseFig));
#ifdef DEBUG_PRS_PRINTS
printf("[Rx %d] pilot %3d, SNR %+2d dB: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, %+d) \n", rxAnt, pIdx, snr/(pIdx+1), rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]);
#endif
pil +=2;
k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size;
rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k];
ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15);
ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15);
if(pIdx == (num_pilots-3)) // 2nd last pilot
{
multadd_real_vector_complex_scalar(fmr,
ch,
ch_tmp,
8);
}
else
{
multadd_real_vector_complex_scalar(fmm,
ch,
ch_tmp,
8);
}
//SNR estimation
noiseFig[0] = rxF[0] - (int16_t)(((int32_t)ch[0]*pil[0] - (int32_t)ch[1]*pil[1])>>15);
noiseFig[1] = rxF[1] - (int16_t)(((int32_t)ch[1]*pil[0] + (int32_t)ch[0]*pil[1])>>15);
snr += 10*log10(squaredMod(*((c16_t*)rxF)) - squaredMod(*((c16_t*)noiseFig))) - 10*log10(squaredMod(*((c16_t*)noiseFig)));
#ifdef DEBUG_PRS_PRINTS
printf("[Rx %d] pilot %3d, SNR %+2d dB: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, %+d) \n", rxAnt, pIdx+1, snr/(pIdx+2), rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]);
#endif
pil +=2;
k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size;
rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k];
ch_tmp +=8;
}
//End pilot
ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15);
ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15);
multadd_real_vector_complex_scalar(fr,
ch,
ch_tmp,
8);
//SNR estimation
noiseFig[0] = rxF[0] - (int16_t)(((int32_t)ch[0]*pil[0] - (int32_t)ch[1]*pil[1])>>15);
noiseFig[1] = rxF[1] - (int16_t)(((int32_t)ch[1]*pil[0] + (int32_t)ch[0]*pil[1])>>15);
snr += 10*log10(squaredMod(*((c16_t*)rxF)) - squaredMod(*((c16_t*)noiseFig))) - 10*log10(squaredMod(*((c16_t*)noiseFig)));
#ifdef DEBUG_PRS_PRINTS
printf("[Rx %d] pilot %3d, SNR %+2d dB: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, %+d) \n", rxAnt, num_pilots-1, snr/num_pilots, rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]);
#endif
// average out the SNR computed
snr = snr/num_pilots;
prs_meas[rxAnt]->snr = snr;
}
else if(prs_cfg->CombSize == 4)
{
// Choose the interpolation filters
switch (k_prime) {
case 0:
fl = filt16a_l0;
fml = filt16a_mm0;
fmm = filt16a_mm0;
fmr = filt16a_m0;
fm = filt16a_m0;
fr = filt16a_r0;
break;
case 1:
fl = filt16a_l1;
fml = filt16a_ml1;
fmm = filt16a_mm1;
fmr = filt16a_mr1;
fm = filt16a_m1;
fr = filt16a_r1;
break;
case 2:
fl = filt16a_l2;
fml = filt16a_ml2;
fmm = filt16a_mm2;
fmr = filt16a_mr2;
fm = filt16a_m2;
fr = filt16a_r2;
break;
case 3:
fl = filt16a_l3;
fml = filt16a_ml3;
fmm = filt16a_mm3;
fmr = filt16a_mm3;
fm = filt16a_m3;
fr = filt16a_r3;
break;
default:
LOG_I(PHY, "%s: ERROR!! Invalid k_prime=%d for PRS comb_size %d, symbol %d\n",__FUNCTION__, k_prime, prs_cfg->CombSize, l);
return(-1);
break;
}
//Start pilot
ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15);
ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15);
multadd_real_vector_complex_scalar(fl,
ch,
ch_tmp,
16);
//SNR estimation
noiseFig[0] = rxF[0] - (int16_t)(((int32_t)ch[0]*pil[0] - (int32_t)ch[1]*pil[1])>>15);
noiseFig[1] = rxF[1] - (int16_t)(((int32_t)ch[1]*pil[0] + (int32_t)ch[0]*pil[1])>>15);
snr += 10*log10(squaredMod(*((c16_t*)rxF)) - squaredMod(*((c16_t*)noiseFig))) - 10*log10(squaredMod(*((c16_t*)noiseFig)));
#ifdef DEBUG_PRS_PRINTS
printf("[Rx %d] pilot %3d, SNR %+2d dB: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, %+d) \n", rxAnt, 0, snr, rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]);
#endif
pil +=2;
k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size;
rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k];
ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15);
ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15);
multadd_real_vector_complex_scalar(fml,
ch,
ch_tmp,
16);
//SNR estimation
noiseFig[0] = rxF[0] - (int16_t)(((int32_t)ch[0]*pil[0] - (int32_t)ch[1]*pil[1])>>15);
noiseFig[1] = rxF[1] - (int16_t)(((int32_t)ch[1]*pil[0] + (int32_t)ch[0]*pil[1])>>15);
snr += 10*log10(squaredMod(*((c16_t*)rxF)) - squaredMod(*((c16_t*)noiseFig))) - 10*log10(squaredMod(*((c16_t*)noiseFig)));
#ifdef DEBUG_PRS_PRINTS
printf("[Rx %d] pilot %3d, SNR %+2d dB: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, %+d) \n", rxAnt, 1, snr/2, rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]);
#endif
pil +=2;
k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size;
rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k];
ch_tmp +=8;
//Middle pilots
for(int pIdx = 2; pIdx < num_pilots-2; pIdx++)
{
ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15);
ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15);
multadd_real_vector_complex_scalar(fmm,
ch,
ch_tmp,
16);
//SNR estimation
noiseFig[0] = rxF[0] - (int16_t)(((int32_t)ch[0]*pil[0] - (int32_t)ch[1]*pil[1])>>15);
noiseFig[1] = rxF[1] - (int16_t)(((int32_t)ch[1]*pil[0] + (int32_t)ch[0]*pil[1])>>15);
snr += 10*log10(squaredMod(*((c16_t*)rxF)) - squaredMod(*((c16_t*)noiseFig))) - 10*log10(squaredMod(*((c16_t*)noiseFig)));
#ifdef DEBUG_PRS_PRINTS
printf("[Rx %d] pilot %3d, SNR %+2d dB: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, %+d) \n", rxAnt, pIdx, snr/(pIdx+1), rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]);
#endif
pil +=2;
k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size;
rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k];
ch_tmp +=8;
}
//End pilot
ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15);
ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15);
multadd_real_vector_complex_scalar(fmr,
ch,
ch_tmp,
16);
//SNR estimation
noiseFig[0] = rxF[0] - (int16_t)(((int32_t)ch[0]*pil[0] - (int32_t)ch[1]*pil[1])>>15);
noiseFig[1] = rxF[1] - (int16_t)(((int32_t)ch[1]*pil[0] + (int32_t)ch[0]*pil[1])>>15);
snr += 10*log10(squaredMod(*((c16_t*)rxF)) - squaredMod(*((c16_t*)noiseFig))) - 10*log10(squaredMod(*((c16_t*)noiseFig)));
#ifdef DEBUG_PRS_PRINTS
printf("[Rx %d] pilot %3d, SNR %+2d dB: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, %+d) \n", rxAnt, num_pilots-2, snr/(num_pilots-1), rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]);
#endif
pil +=2;
k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size;
rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k];
ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15);
ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15);
multadd_real_vector_complex_scalar(fr,
ch,
ch_tmp,
16);
//SNR estimation
noiseFig[0] = rxF[0] - (int16_t)(((int32_t)ch[0]*pil[0] - (int32_t)ch[1]*pil[1])>>15);
noiseFig[1] = rxF[1] - (int16_t)(((int32_t)ch[1]*pil[0] + (int32_t)ch[0]*pil[1])>>15);
snr += 10*log10(squaredMod(*((c16_t*)rxF)) - squaredMod(*((c16_t*)noiseFig))) - 10*log10(squaredMod(*((c16_t*)noiseFig)));
#ifdef DEBUG_PRS_PRINTS
printf("[Rx %d] pilot %3d, SNR %+2d dB: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, +%d) \n", rxAnt, num_pilots-1, snr/num_pilots, rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]);
#endif
// average out the SNR computed
snr = snr/num_pilots;
prs_meas[rxAnt]->snr = snr;
}
else
{
AssertFatal((prs_cfg->CombSize == 2)||(prs_cfg->CombSize == 4), "[%s] DL PRS CombSize other than 2 and 4 are NOT supported currently. Exiting!!!", __FUNCTION__);
}
//reset channel pointer
ch_tmp = (int16_t*)ch_tmp_buf;
} // for rxAnt
} //for l
for (rxAnt=0; rxAnt < frame_params->nb_antennas_rx; rxAnt++)
{
// scale by averaging factor 1/NumPrsSymbols
multadd_complex_vector_real_scalar(ch_tmp,
scale_factor,
ch_tmp,
1,
frame_params->ofdm_symbol_size);
#ifdef DEBUG_PRS_PRINTS
for (int rb = 0; rb < prs_cfg->NumRB; rb++)
{
printf("================================================================\n");
printf("\t\t\t[gNB %d][Rx %d][RB %d]\n", gNB_id, rxAnt, rb);
printf("================================================================\n");
idx = (12*rb)<<1;
printf("%4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d\n", ch_tmp[idx], ch_tmp[idx+1], ch_tmp[idx+2], ch_tmp[idx+3], ch_tmp[idx+4], ch_tmp[idx+5], ch_tmp[idx+6], ch_tmp[idx+7], ch_tmp[idx+8], ch_tmp[idx+9], ch_tmp[idx+10], ch_tmp[idx+11]);
printf("%4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d\n", ch_tmp[idx+12], ch_tmp[idx+13], ch_tmp[idx+14], ch_tmp[idx+15], ch_tmp[idx+16], ch_tmp[idx+17], ch_tmp[idx+18], ch_tmp[idx+19], ch_tmp[idx+20], ch_tmp[idx+21], ch_tmp[idx+22], ch_tmp[idx+23]);
printf("\n");
}
#endif
// Place PRS channel estimates in FFT shifted format
first_half = frame_params->ofdm_symbol_size - re_offset;
second_half = (prs_cfg->NumRB*12) - first_half;
if(first_half > 0)
memcpy((int16_t *)&chF_interpol[rxAnt][start_offset+re_offset], &ch_tmp[0], first_half*sizeof(int32_t));
if(second_half > 0)
memcpy((int16_t *)&chF_interpol[rxAnt][start_offset], &ch_tmp[(first_half<<1)], second_half*sizeof(int32_t));
// Time domain IMPULSE response
idft_size_idx_t idftsizeidx;
switch (NR_PRS_IDFT_OVERSAMP_FACTOR*frame_params->ofdm_symbol_size) {
case 128:
idftsizeidx = IDFT_128;
break;
case 256:
idftsizeidx = IDFT_256;
break;
case 512:
idftsizeidx = IDFT_512;
break;
case 768:
idftsizeidx = IDFT_768;
break;
case 1024:
idftsizeidx = IDFT_1024;
break;
case 1536:
idftsizeidx = IDFT_1536;
break;
case 2048:
idftsizeidx = IDFT_2048;
break;
case 3072:
idftsizeidx = IDFT_3072;
break;
case 4096:
idftsizeidx = IDFT_4096;
break;
// 16x IDFT oversampling
case 8192:
idftsizeidx = IDFT_8192;
break;
case 12288:
idftsizeidx = IDFT_12288;
break;
case 16384:
idftsizeidx = IDFT_16384;
break;
case 24576:
idftsizeidx = IDFT_24576;
break;
case 32768:
idftsizeidx = IDFT_32768;
break;
case 49152:
idftsizeidx = IDFT_49152;
break;
case 65536:
idftsizeidx = IDFT_65536;
break;
default:
LOG_I(PHY, "%s: unsupported ofdm symbol size \n", __FUNCTION__);
assert(0);
}
idft(idftsizeidx,
(int16_t *)&chF_interpol[rxAnt][0],
(int16_t *)&chT_interpol[rxAnt][0],1);
// peak estimator
peak_estimator(&chT_interpol[rxAnt][start_offset],
frame_params->ofdm_symbol_size,
&prs_meas[rxAnt]->dl_toa,
&ch_pwr);
//prs measurements
prs_meas[rxAnt]->gNB_id = gNB_id;
prs_meas[rxAnt]->sfn = proc->frame_rx;
prs_meas[rxAnt]->slot = proc->nr_slot_rx;
prs_meas[rxAnt]->rxAnt_idx = rxAnt;
prs_meas[rxAnt]->dl_aoa = rsc_id;
LOG_I(PHY, "[gNB %d][rsc %d][Rx %d][sfn %d][slot %d] DL PRS ToA ==> %d / %d samples, peak channel power %.1f dBm, SNR %+2d dB\n", gNB_id, rsc_id, rxAnt, proc->frame_rx, proc->nr_slot_rx, prs_meas[rxAnt]->dl_toa, frame_params->ofdm_symbol_size, 10*log10(ch_pwr/frame_params->ofdm_symbol_size)-30, prs_meas[rxAnt]->snr);
#ifdef DEBUG_PRS_CHEST
sprintf(filename, "%s%i%s", "PRSpilot_", rxAnt, ".m");
LOG_M(filename, "prs_loc", &mod_prs[0], num_pilots,1,1);
sprintf(filename, "%s%i%s", "rxSigF_", rxAnt, ".m");
sprintf(varname, "%s%i", "rxF_", rxAnt);
LOG_M(filename, varname, &rxdataF[rxAnt][0], prs_cfg->NumPRSSymbols*frame_params->ofdm_symbol_size,1,1);
sprintf(filename, "%s%i%s", "prsChestF_", rxAnt, ".m");
sprintf(varname, "%s%i", "prsChF_", rxAnt);
LOG_M(filename, varname, &chF_interpol[rxAnt][start_offset], frame_params->ofdm_symbol_size,1,1);
sprintf(filename, "%s%i%s", "prsChestT_", rxAnt, ".m");
sprintf(varname, "%s%i", "prsChT_", rxAnt);
LOG_M(filename, varname, &chT_interpol[rxAnt][start_offset], frame_params->ofdm_symbol_size,1,1);
#endif
// T tracer dump
T(T_UE_PHY_INPUT_SIGNAL, T_INT(gNB_id),
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(T_UE_PHY_DL_CHANNEL_ESTIMATE_FREQ, T_INT(gNB_id), T_INT(rsc_id),
T_INT(proc->frame_rx), T_INT(proc->nr_slot_rx),
T_INT(rxAnt), T_BUFFER(&chF_interpol[rxAnt][start_offset], frame_params->ofdm_symbol_size*sizeof(int32_t)));
T(T_UE_PHY_DL_CHANNEL_ESTIMATE, T_INT(gNB_id), T_INT(rsc_id),
T_INT(proc->frame_rx), T_INT(proc->nr_slot_rx),
T_INT(rxAnt), T_BUFFER(&chT_interpol[rxAnt][start_offset], frame_params->ofdm_symbol_size*sizeof(int32_t)));
}
return(0);
}
#define CH_INTERP 0
#define NO_INTERP 1
/* 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 max_val = 0, max_idx = 0, abs_val = 0;
for(int k = 0; k < buf_len; k++)
{
abs_val = squaredMod(((c16_t*)buffer)[k]);
if(abs_val > max_val)
{
max_val = abs_val;
max_idx = k;
}
}
*peak_val = max_val;
*peak_idx = max_idx;
}
#define CH_INTERP 0
#define NO_INTERP 1
@@ -72,7 +602,7 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
k = nushift;
#ifdef DEBUG_CH
#ifdef DEBUG_PBCH
printf("PBCH DMRS Correlation : ThreadId %d, gNB_id %d , OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n",proc->thread_id, gNB_id,ue->frame_parms.ofdm_symbol_size,
ue->frame_parms.Ncp,Ns,k, symbol);
#endif
@@ -86,7 +616,7 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
pil = (int16_t *)&pilot[0];
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
#ifdef DEBUG_CH
#ifdef DEBUG_PBCH
printf("pbch ch est pilot addr %p RB_DL %d\n",&pilot[0], ue->frame_parms.N_RB_DL);
printf("k %d, first_carrier %d\n",k,ue->frame_parms.first_carrier_offset);
printf("rxF addr %p\n", rxF);
@@ -100,7 +630,7 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
current_ssb->c_re += ch[0];
current_ssb->c_im += ch[1];
#ifdef DEBUG_CH
#ifdef DEBUG_PBCH
printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1]));
printf("pilot 0 : rxF - > (%d,%d) addr %p ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]);
#endif
@@ -116,7 +646,7 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
current_ssb->c_re += ch[0];
current_ssb->c_im += ch[1];
#ifdef DEBUG_CH
#ifdef DEBUG_PBCH
printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
#endif
@@ -127,7 +657,7 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
current_ssb->c_re += ch[0];
current_ssb->c_im += ch[1];
#ifdef DEBUG_CH
#ifdef DEBUG_PBCH
printf("pilot 2 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
#endif
@@ -152,7 +682,7 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
current_ssb->c_re += ch[0];
current_ssb->c_im += ch[1];
#ifdef DEBUG_CH
#ifdef DEBUG_PBCH
printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
#endif
@@ -167,7 +697,7 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
current_ssb->c_re += ch[0];
current_ssb->c_im += ch[1];
#ifdef DEBUG_CH
#ifdef DEBUG_PBCH
printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
#endif
pil += 2;
@@ -181,7 +711,7 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
current_ssb->c_re += ch[0];
current_ssb->c_im += ch[1];
#ifdef DEBUG_CH
#ifdef DEBUG_PBCH
printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+2,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
#endif
@@ -237,7 +767,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
k = nushift;
#ifdef DEBUG_CH
#ifdef DEBUG_PBCH
printf("PBCH Channel Estimation : ThreadId %d, gNB_id %d ch_offset %d, OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n",proc->thread_id, gNB_id,ch_offset,ue->frame_parms.ofdm_symbol_size,
ue->frame_parms.Ncp,Ns,k, symbol);
#endif
@@ -288,6 +818,10 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
idftsizeidx = IDFT_512;
break;
case 768:
idftsizeidx = IDFT_768;
break;
case 1024:
idftsizeidx = IDFT_1024;
break;
@@ -325,7 +859,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
memset(dl_ch,0,sizeof(struct complex16)*(ue->frame_parms.ofdm_symbol_size));
#ifdef DEBUG_CH
#ifdef DEBUG_PBCH
printf("pbch ch est pilot addr %p RB_DL %d\n",&pilot[0], ue->frame_parms.N_RB_DL);
printf("k %d, first_carrier %d\n",k,ue->frame_parms.first_carrier_offset);
printf("rxF addr %p\n", rxF);
@@ -337,7 +871,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
#ifdef DEBUG_CH
#ifdef DEBUG_PBCH
printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1]));
printf("pilot 0 : rxF - > (%d,%d) addr %p ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]);
#endif
@@ -356,7 +890,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
#ifdef DEBUG_CH
#ifdef DEBUG_PBCH
printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
#endif
multadd_real_vector_complex_scalar(fm,
@@ -370,7 +904,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
#ifdef DEBUG_CH
#ifdef DEBUG_PBCH
printf("pilot 2 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
#endif
@@ -398,7 +932,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
#ifdef DEBUG_CH
#ifdef DEBUG_PBCH
printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
#endif
multadd_real_vector_complex_scalar(fl,
@@ -417,7 +951,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
#ifdef DEBUG_CH
#ifdef DEBUG_PBCH
printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
#endif
multadd_real_vector_complex_scalar(fm,
@@ -427,12 +961,11 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
pil += 2;
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
#ifdef DEBUG_CH
#ifdef DEBUG_PBCH
printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+2,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
#endif
@@ -32,6 +32,17 @@
/*!\brief Timing drift hysterisis in samples*/
#define SYNCH_HYST 2
/* A function to perform the channel estimation of DL PRS signal */
int nr_prs_channel_estimation(uint8_t gNB_id,
uint8_t rsc_id,
uint8_t rep_num,
PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
NR_DL_FRAME_PARMS *frame_params);
/* 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);
/*!
\brief This function performs channel estimation including frequency and temporal interpolation
\param ue Pointer to UE PHY variables
@@ -0,0 +1,52 @@
clc; clear all;
dir = input('Enter the directory path to T tracer dumps: ');
fft_size = input('Enter the OFDM FFT size used for file parsing: ');
num_resources = input('Enter number of PRS respurces: ');
num_gnb = input('Enter number of active gNBs: ');
num_prs_symb = 1;
start_resource = 0;
buff_offset = start_resource*2*fft_size;
%% Channel Impulse Response(CIR)
figure, hold on;
for i=0:num_gnb-1
for j=0:num_resources-1
file = [dir '/chT_gnb', num2str(i), '_', num2str(j), '.raw'];
fid = fopen(file, 'r');
if (fid > 0)
x = fread(fid, Inf, 'int16');
else
disp(['Failed to open the file ', file, '..!!'])
return;
end
fclose(fid);
y = x(buff_offset+1:2:num_prs_symb*2*fft_size) + 1j*x(buff_offset+2:2:num_prs_symb*2*fft_size);
plot(abs(fftshift(y)));
end
end
xlabel('FFT Index'); ylabel('ABS');
title('CHANNEL IMPULSE RESPONSE');
hold off;
%% Channel Frequncy Response(CFR)
figure, hold on;
for i=0:num_gnb-1
for j=0:num_resources-1
file = [dir '/chF_gnb', num2str(i), '_', num2str(j), '.raw'];
fid = fopen(file, 'r');
if (fid > 0)
x = fread(fid, Inf, 'int16');
else
disp(['Failed to open the file ', file, '..!!'])
return;
end
fclose(fid);
y = x(buff_offset+1:2:num_prs_symb*2*fft_size) + 1j*x(buff_offset+2:2:num_prs_symb*2*fft_size);
plot(abs(y));
end
end
xlabel('FFT Index'); ylabel('ABS');
title('CHANNEL FREQUENCY RESPONSE');
hold off;
+1 -19
View File
@@ -600,24 +600,6 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change)
}
static inline int abs32(int x)
{
return (((int)((short*)&x)[0])*((int)((short*)&x)[0]) + ((int)((short*)&x)[1])*((int)((short*)&x)[1]));
}
static inline int64_t abs64(int64_t x)
{
return (((int64_t)((int32_t*)&x)[0])*((int64_t)((int32_t*)&x)[0]) + ((int64_t)((int32_t*)&x)[1])*((int64_t)((int32_t*)&x)[1]));
}
static inline double angle64(int64_t x)
{
double re=((int32_t*)&x)[0];
double im=((int32_t*)&x)[1];
return (atan2(im,re));
}
/*******************************************************************
*
@@ -726,7 +708,7 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain
(short*)&(rxdata[ar][n+is*frame_parms->samples_per_frame]),
frame_parms->ofdm_symbol_size,
shift);
pss_corr_ue += abs64(result);
pss_corr_ue += squaredMod(*(c32_t*)&result);
//((short*)pss_corr_ue[pss_index])[2*n] += ((short*) &result)[0]; /* real part */
//((short*)pss_corr_ue[pss_index])[2*n+1] += ((short*) &result)[1]; /* imaginary part */
//((short*)&synchro_out)[0] += ((int*) &result)[0]; /* real part */
+1 -1
View File
@@ -1,5 +1,5 @@
oai_dfts_sse4: oai_dfts.c
gcc-7 -O3 -std=gnu99 -msse4.1 -o oai_dfts_sse4 oai_dfts.c time_meas.c ../../SIMULATION/TOOLS/taus.c -I$$OPENAIR_HOME -I$$OPENAIR1_DIR -I$$OPENAIR_TARGETS -I$$OPENAIR_TARGETS/COMMON -I$$OPENAIR_HOME/sdr/COMMON -I$$OPENAIR2_DIR -I$$OPENAIR2_DIR/COMMON -I$$OPENAIR_HOME/common/utils -I$$OPENAIR_HOME/common/utils/T -I$$OPENAIR_HOME/common/utils/msc -I$$OPENAIR_HOME/nfapi/open-nFAPI/nfapi/public_inc -DMR_MAIN -DNB_ANTENNAS_RX=1 -lm -lpthread # -DD256STATS #-DD64STATS
gcc -O3 -std=gnu99 -msse4.1 -o oai_dfts_sse4 oai_dfts.c time_meas.c ../../SIMULATION/TOOLS/taus.c -I$$OPENAIR_HOME -I$$OPENAIR1_DIR -I$$OPENAIR_TARGETS -I$$OPENAIR_TARGETS/COMMON -I$$OPENAIR_HOME/sdr/COMMON -I$$OPENAIR2_DIR -I$$OPENAIR2_DIR/COMMON -I$$OPENAIR_HOME/common/utils -I$$OPENAIR_HOME/common/utils/T -I$$OPENAIR_HOME/common/utils/msc -I$$OPENAIR_HOME/nfapi/open-nFAPI/nfapi/public_inc -DMR_MAIN -DNB_ANTENNAS_RX=1 -lm -lpthread # -DD256STATS #-DD64STATS
oai_dfts_avx2: oai_dfts.c
gcc -O2 -std=gnu99 -mavx2 -g -ggdb -o oai_dfts_avx2 oai_dfts.c time_meas.c ../../SIMULATION/TOOLS/taus.c $$OPENAIR_HOME/common/utils/backtrace.c -I$$OPENAIR_HOME -I$$OPENAIR1_DIR -I$$OPENAIR_TARGETS -I$$OPENAIR_TARGETS/COMMON -I$$OPENAIR_HOME/sdr/COMMON -I$$OPENAIR2_DIR -I$$OPENAIR2_DIR/COMMON -I$$OPENAIR_HOME/common/utils -I$$OPENAIR_HOME/common/utils/T -I$$OPENAIR_HOME/common/utils/msc -I$$OPENAIR_HOME/nfapi/open-nFAPI/nfapi/public_inc -DMR_MAIN -DNB_ANTENNAS_RX=1 -lm -lpthread # -DD256STATS #-DD64STATS
+303 -9
View File
@@ -5362,7 +5362,7 @@ void idft8192(int16_t *x,int16_t *y,unsigned char scale)
#endif
int16_t tw16384[3*2*4096];
int16_t tw16384[3*2*4096] __attribute__((aligned(32)));
#ifndef __AVX2__
void dft16384(int16_t *x,int16_t *y,unsigned char scale)
@@ -5961,6 +5961,124 @@ void idft32768(int16_t *x,int16_t *y,unsigned char scale)
#endif
int16_t twa768[512],twb768[512];
// 256 x 3
void idft768(int16_t *input, int16_t *output, unsigned char scale)
{
int i,i2,j;
uint32_t tmp[3][256]__attribute__((aligned(32)));
uint32_t tmpo[3][256] __attribute__((aligned(32)));
simd_q15_t *y128p=(simd_q15_t*)output;
simd_q15_t ONE_OVER_SQRT3_Q15_128 = set1_int16(ONE_OVER_SQRT3_Q15);
for (i=0,j=0; i<256; i++) {
tmp[0][i] = ((uint32_t *)input)[j++];
tmp[1][i] = ((uint32_t *)input)[j++];
tmp[2][i] = ((uint32_t *)input)[j++];
}
idft256((int16_t*)(tmp[0]),(int16_t*)(tmpo[0]),1);
idft256((int16_t*)(tmp[1]),(int16_t*)(tmpo[1]),1);
idft256((int16_t*)(tmp[2]),(int16_t*)(tmpo[2]),1);
for (i=0,i2=0; i<512; i+=8,i2+=4) {
ibfly3((simd_q15_t*)(&tmpo[0][i2]),(simd_q15_t*)(&tmpo[1][i2]),((simd_q15_t*)&tmpo[2][i2]),
(simd_q15_t*)(output+i),(simd_q15_t*)(output+512+i),(simd_q15_t*)(output+1024+i),
(simd_q15_t*)(twa768+i),(simd_q15_t*)(twb768+i));
}
if (scale==1) {
for (i=0; i<12; i++) {
y128p[0] = mulhi_int16(y128p[0],ONE_OVER_SQRT3_Q15_128);
y128p[1] = mulhi_int16(y128p[1],ONE_OVER_SQRT3_Q15_128);
y128p[2] = mulhi_int16(y128p[2],ONE_OVER_SQRT3_Q15_128);
y128p[3] = mulhi_int16(y128p[3],ONE_OVER_SQRT3_Q15_128);
y128p[4] = mulhi_int16(y128p[4],ONE_OVER_SQRT3_Q15_128);
y128p[5] = mulhi_int16(y128p[5],ONE_OVER_SQRT3_Q15_128);
y128p[6] = mulhi_int16(y128p[6],ONE_OVER_SQRT3_Q15_128);
y128p[7] = mulhi_int16(y128p[7],ONE_OVER_SQRT3_Q15_128);
y128p[8] = mulhi_int16(y128p[8],ONE_OVER_SQRT3_Q15_128);
y128p[9] = mulhi_int16(y128p[9],ONE_OVER_SQRT3_Q15_128);
y128p[10] = mulhi_int16(y128p[10],ONE_OVER_SQRT3_Q15_128);
y128p[11] = mulhi_int16(y128p[11],ONE_OVER_SQRT3_Q15_128);
y128p[12] = mulhi_int16(y128p[12],ONE_OVER_SQRT3_Q15_128);
y128p[13] = mulhi_int16(y128p[13],ONE_OVER_SQRT3_Q15_128);
y128p[14] = mulhi_int16(y128p[14],ONE_OVER_SQRT3_Q15_128);
y128p[15] = mulhi_int16(y128p[15],ONE_OVER_SQRT3_Q15_128);
y128p+=16;
}
}
_mm_empty();
_m_empty();
}
void dft768(int16_t *input, int16_t *output, unsigned char scale)
{
int i,i2,j;
uint32_t tmp[3][256] __attribute__((aligned(32)));
uint32_t tmpo[3][256] __attribute__((aligned(32)));
simd_q15_t *y128p=(simd_q15_t*)output;
simd_q15_t ONE_OVER_SQRT3_Q15_128 = set1_int16(ONE_OVER_SQRT3_Q15);
for (i=0,j=0; i<256; i++) {
tmp[0][i] = ((uint32_t *)input)[j++];
tmp[1][i] = ((uint32_t *)input)[j++];
tmp[2][i] = ((uint32_t *)input)[j++];
}
dft256((int16_t*)(tmp[0]),(int16_t*)(tmpo[0]),1);
dft256((int16_t*)(tmp[1]),(int16_t*)(tmpo[1]),1);
dft256((int16_t*)(tmp[2]),(int16_t*)(tmpo[2]),1);
/*
for (i=1; i<512; i++) {
tmpo[0][i] = tmpo[0][i<<1];
tmpo[1][i] = tmpo[1][i<<1];
tmpo[2][i] = tmpo[2][i<<1];
}*/
#ifndef MR_MAIN
if (LOG_DUMPFLAG(DEBUG_DFT)) {
LOG_M("dft768out0.m","o0",tmpo[0],1024,1,1);
LOG_M("dft768out1.m","o1",tmpo[1],1024,1,1);
LOG_M("dft768out2.m","o2",tmpo[2],1024,1,1);
}
#endif
for (i=0,i2=0; i<512; i+=8,i2+=4) {
bfly3((simd_q15_t*)(&tmpo[0][i2]),(simd_q15_t*)(&tmpo[1][i2]),(simd_q15_t*)(&tmpo[2][i2]),
(simd_q15_t*)(output+i),(simd_q15_t*)(output+512+i),(simd_q15_t*)(output+1024+i),
(simd_q15_t*)(twa768+i),(simd_q15_t*)(twb768+i));
}
if (scale==1) {
for (i=0; i<12; i++) {
y128p[0] = mulhi_int16(y128p[0],ONE_OVER_SQRT3_Q15_128);
y128p[1] = mulhi_int16(y128p[1],ONE_OVER_SQRT3_Q15_128);
y128p[2] = mulhi_int16(y128p[2],ONE_OVER_SQRT3_Q15_128);
y128p[3] = mulhi_int16(y128p[3],ONE_OVER_SQRT3_Q15_128);
y128p[4] = mulhi_int16(y128p[4],ONE_OVER_SQRT3_Q15_128);
y128p[5] = mulhi_int16(y128p[5],ONE_OVER_SQRT3_Q15_128);
y128p[6] = mulhi_int16(y128p[6],ONE_OVER_SQRT3_Q15_128);
y128p[7] = mulhi_int16(y128p[7],ONE_OVER_SQRT3_Q15_128);
y128p[8] = mulhi_int16(y128p[8],ONE_OVER_SQRT3_Q15_128);
y128p[9] = mulhi_int16(y128p[9],ONE_OVER_SQRT3_Q15_128);
y128p[10] = mulhi_int16(y128p[10],ONE_OVER_SQRT3_Q15_128);
y128p[11] = mulhi_int16(y128p[11],ONE_OVER_SQRT3_Q15_128);
y128p[12] = mulhi_int16(y128p[12],ONE_OVER_SQRT3_Q15_128);
y128p[13] = mulhi_int16(y128p[13],ONE_OVER_SQRT3_Q15_128);
y128p[14] = mulhi_int16(y128p[14],ONE_OVER_SQRT3_Q15_128);
y128p[15] = mulhi_int16(y128p[15],ONE_OVER_SQRT3_Q15_128);
y128p+=16;
}
}
_mm_empty();
_m_empty();
}
int16_t twa1536[1024],twb1536[1024];
// 512 x 3
@@ -6894,6 +7012,122 @@ void idft49152(int16_t *input, int16_t *output,uint8_t scale) {
_m_empty();
}
int16_t tw65536[3*2*16384] __attribute__((aligned(32)));
#ifndef __AVX2__
void idft65536(int16_t *x,int16_t *y,unsigned char scale)
{
simd_q15_t xtmp[16384],ytmp[16384],*tw65536_128p=(simd_q15_t *)tw65536,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y;
simd_q15_t *ytmpp = &ytmp[0];
int i,j;
for (i=0,j=0; i<16384; i+=4,j++) {
transpose16_ooff(x128+i,xtmp+j,4096);
}
idft16384((int16_t*)(xtmp),(int16_t*)(ytmp),1);
idft16384((int16_t*)(xtmp+4096),(int16_t*)(ytmp+4096),1);
idft16384((int16_t*)(xtmp+8192),(int16_t*)(ytmp+8192),1);
idft16384((int16_t*)(xtmp+12288),(int16_t*)(ytmp+12288),1);
for (i=0; i<4096; i++) {
ibfly4(ytmpp,ytmpp+4096,ytmpp+8192,ytmpp+12288,
y128p,y128p+4096,y128p+8192,y128p+12288,
tw65536_128p,tw63536_128p+4096,tw65536_128p+8192);
tw65536_128p++;
y128p++;
ytmpp++;
}
if (scale>0) {
for (i=0; i<1024; i++) {
y128[0] = shiftright_int16(y128[0],scale);
y128[1] = shiftright_int16(y128[1],scale);
y128[2] = shiftright_int16(y128[2],scale);
y128[3] = shiftright_int16(y128[3],scale);
y128[4] = shiftright_int16(y128[4],scale);
y128[5] = shiftright_int16(y128[5],scale);
y128[6] = shiftright_int16(y128[6],scale);
y128[7] = shiftright_int16(y128[7],scale);
y128[8] = shiftright_int16(y128[8],scale);
y128[9] = shiftright_int16(y128[9],scale);
y128[10] = shiftright_int16(y128[10],scale);
y128[11] = shiftright_int16(y128[11],scale);
y128[12] = shiftright_int16(y128[12],scale);
y128[13] = shiftright_int16(y128[13],scale);
y128[14] = shiftright_int16(y128[14],scale);
y128[15] = shiftright_int16(y128[15],scale);
y128+=16;
}
}
_mm_empty();
_m_empty();
}
#else // __AVX2__
void idft65536(int16_t *x,int16_t *y,unsigned char scale)
{
simd256_q15_t xtmp[8192],ytmp[8192],*tw65536_256p=(simd256_q15_t *)tw65536,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y;
simd256_q15_t *ytmpp = &ytmp[0];
int i,j;
for (i=0,j=0; i<8192; i+=4,j++) {
transpose16_ooff_simd256(x256+i,xtmp+j,2048);
}
idft16384((int16_t*)(xtmp),(int16_t*)(ytmp),1);
idft16384((int16_t*)(xtmp+2048),(int16_t*)(ytmp+2048),1);
idft16384((int16_t*)(xtmp+4096),(int16_t*)(ytmp+4096),1);
idft16384((int16_t*)(xtmp+6144),(int16_t*)(ytmp+6144),1);
for (i=0; i<2048; i++) {
ibfly4_256(ytmpp,ytmpp+2048,ytmpp+4096,ytmpp+6144,
y256p,y256p+2048,y256p+4096,y256p+6144,
tw65536_256p,tw65536_256p+4096,tw65536_256p+8192);
tw65536_256p++;
y256p++;
ytmpp++;
}
if (scale>0) {
for (i=0; i<512; i++) {
y256[0] = shiftright_int16_simd256(y256[0],scale);
y256[1] = shiftright_int16_simd256(y256[1],scale);
y256[2] = shiftright_int16_simd256(y256[2],scale);
y256[3] = shiftright_int16_simd256(y256[3],scale);
y256[4] = shiftright_int16_simd256(y256[4],scale);
y256[5] = shiftright_int16_simd256(y256[5],scale);
y256[6] = shiftright_int16_simd256(y256[6],scale);
y256[7] = shiftright_int16_simd256(y256[7],scale);
y256[8] = shiftright_int16_simd256(y256[8],scale);
y256[9] = shiftright_int16_simd256(y256[9],scale);
y256[10] = shiftright_int16_simd256(y256[10],scale);
y256[11] = shiftright_int16_simd256(y256[11],scale);
y256[12] = shiftright_int16_simd256(y256[12],scale);
y256[13] = shiftright_int16_simd256(y256[13],scale);
y256[14] = shiftright_int16_simd256(y256[14],scale);
y256[15] = shiftright_int16_simd256(y256[15],scale);
y256+=16;
}
}
_mm_empty();
_m_empty();
}
#endif //__AVX2__
int16_t twa73728[49152] __attribute__((aligned(32)));
int16_t twb73728[49152] __attribute__((aligned(32)));
// 24576 x 3
@@ -8676,6 +8910,7 @@ void dft384(int16_t *x,int16_t *y,unsigned char scale_flag) // 96 x 4
};
static int16_t twa432[107*2*4];
static int16_t twb432[107*2*4];
static int16_t twc432[107*2*4];
@@ -9049,18 +9284,18 @@ void dft720(int16_t *x,int16_t *y,unsigned char scale_flag) // 180 x 4
};
static int16_t twa768[191*2*4];
static int16_t twb768[191*2*4];
static int16_t twc768[191*2*4];
static int16_t twa768p[191*2*4];
static int16_t twb768p[191*2*4];
static int16_t twc768p[191*2*4];
void dft768(int16_t *x,int16_t *y,unsigned char scale_flag) { // 192x 4;
void dft768p(int16_t *x,int16_t *y,unsigned char scale_flag) { // 192x 4;
int i,j;
simd_q15_t *x128=(simd_q15_t *)x;
simd_q15_t *y128=(simd_q15_t *)y;
simd_q15_t *twa128=(simd_q15_t *)&twa768[0];
simd_q15_t *twb128=(simd_q15_t *)&twb768[0];
simd_q15_t *twc128=(simd_q15_t *)&twc768[0];
simd_q15_t *twa128=(simd_q15_t *)&twa768p[0];
simd_q15_t *twb128=(simd_q15_t *)&twb768p[0];
simd_q15_t *twc128=(simd_q15_t *)&twc768p[0];
simd_q15_t x2128[768];// = (simd_q15_t *)&x2128array[0];
simd_q15_t ytmp128[768];//=&ytmp128array2[0];
@@ -9105,10 +9340,66 @@ void dft768(int16_t *x,int16_t *y,unsigned char scale_flag) { // 192x 4;
_mm_empty();
_m_empty();
}
static int16_t twa384i[256];
static int16_t twb384i[256];
// 128 x 3
void idft384(int16_t *input, int16_t *output, unsigned char scale)
{
int i,i2,j;
uint32_t tmp[3][128]__attribute__((aligned(32)));
uint32_t tmpo[3][128] __attribute__((aligned(32)));
simd_q15_t *y128p=(simd_q15_t*)output;
simd_q15_t ONE_OVER_SQRT3_Q15_128 = set1_int16(ONE_OVER_SQRT3_Q15);
for (i=0,j=0; i<128; i++) {
tmp[0][i] = ((uint32_t *)input)[j++];
tmp[1][i] = ((uint32_t *)input)[j++];
tmp[2][i] = ((uint32_t *)input)[j++];
}
idft128((int16_t*)(tmp[0]),(int16_t*)(tmpo[0]),1);
idft128((int16_t*)(tmp[1]),(int16_t*)(tmpo[1]),1);
idft128((int16_t*)(tmp[2]),(int16_t*)(tmpo[2]),1);
for (i=0,i2=0; i<256; i+=8,i2+=4) {
ibfly3((simd_q15_t*)(&tmpo[0][i2]),(simd_q15_t*)(&tmpo[1][i2]),(simd_q15_t*)(&tmpo[2][i2]),
(simd_q15_t*)(output+i),(simd_q15_t*)(output+256+i),(simd_q15_t*)(output+512+i),
(simd_q15_t*)(twa384+i),(simd_q15_t*)(twb384+i));
}
if (scale==1) {
for (i=0; i<6; i++) {
y128p[0] = mulhi_int16(y128p[0],ONE_OVER_SQRT3_Q15_128);
y128p[1] = mulhi_int16(y128p[1],ONE_OVER_SQRT3_Q15_128);
y128p[2] = mulhi_int16(y128p[2],ONE_OVER_SQRT3_Q15_128);
y128p[3] = mulhi_int16(y128p[3],ONE_OVER_SQRT3_Q15_128);
y128p[4] = mulhi_int16(y128p[4],ONE_OVER_SQRT3_Q15_128);
y128p[5] = mulhi_int16(y128p[5],ONE_OVER_SQRT3_Q15_128);
y128p[6] = mulhi_int16(y128p[6],ONE_OVER_SQRT3_Q15_128);
y128p[7] = mulhi_int16(y128p[7],ONE_OVER_SQRT3_Q15_128);
y128p[8] = mulhi_int16(y128p[8],ONE_OVER_SQRT3_Q15_128);
y128p[9] = mulhi_int16(y128p[9],ONE_OVER_SQRT3_Q15_128);
y128p[10] = mulhi_int16(y128p[10],ONE_OVER_SQRT3_Q15_128);
y128p[11] = mulhi_int16(y128p[11],ONE_OVER_SQRT3_Q15_128);
y128p[12] = mulhi_int16(y128p[12],ONE_OVER_SQRT3_Q15_128);
y128p[13] = mulhi_int16(y128p[13],ONE_OVER_SQRT3_Q15_128);
y128p[14] = mulhi_int16(y128p[14],ONE_OVER_SQRT3_Q15_128);
y128p[15] = mulhi_int16(y128p[15],ONE_OVER_SQRT3_Q15_128);
y128p+=16;
}
}
_mm_empty();
_m_empty();
}
static int16_t twa864[287*2*4];
static int16_t twb864[287*2*4];
@@ -10532,7 +10823,10 @@ int dfts_autoinit(void)
init_rad2(8192,tw8192);
init_rad4(16384,tw16384);
init_rad2(32768,tw32768);
init_rad4(65536,tw65536);
init_rad3(384,twa384i,twb384i);
init_rad3(768,twa768,twb768);
init_rad3(1536,twa1536,twb1536);
init_rad3(3072,twa3072,twb3072);
init_rad3(6144,twa6144,twb6144);
@@ -10569,7 +10863,7 @@ int dfts_autoinit(void)
init_rad2_rep(600,twa600);
init_rad3_rep(648,twa648,twb648);
init_rad4_rep(720,twa720,twb720,twc720);
init_rad4_rep(768,twa768,twb768,twc768);
init_rad4_rep(768,twa768p,twb768p,twc768p);
init_rad3_rep(864,twa864,twb864);
init_rad3_rep(900,twa900,twb900);
init_rad4_rep(960,twa960,twb960,twc960);
+8
View File
@@ -436,6 +436,7 @@ This function performs optimized fixed-point radix-2 FFT/IFFT.
SZ_DEF(128) \
SZ_DEF(256) \
SZ_DEF(512) \
SZ_DEF(768) \
SZ_DEF(1024) \
SZ_DEF(1536) \
SZ_DEF(2048) \
@@ -445,10 +446,13 @@ This function performs optimized fixed-point radix-2 FFT/IFFT.
SZ_DEF(8192) \
SZ_DEF(9216) \
SZ_DEF(12288) \
SZ_DEF(16384) \
SZ_DEF(18432) \
SZ_DEF(24576) \
SZ_DEF(32768) \
SZ_DEF(36864) \
SZ_DEF(49152) \
SZ_DEF(65536) \
SZ_DEF(73728) \
SZ_DEF(98304)
@@ -507,6 +511,8 @@ dft_size_idx_t get_dft(int ofdm_symbol_size)
return DFT_256;
case 512:
return DFT_512;
case 768:
return DFT_768;
case 1024:
return DFT_1024;
case 1536:
@@ -591,6 +597,8 @@ idft_size_idx_t get_idft(int ofdm_symbol_size)
return IDFT_256;
case 512:
return IDFT_512;
case 768:
return IDFT_768;
case 1024:
return IDFT_1024;
case 1536:
+9
View File
@@ -225,6 +225,11 @@ typedef struct {
gNB_PRACH_list_t list[NUMBER_OF_NR_PRACH_MAX];
} NR_gNB_PRACH;
typedef struct {
uint8_t NumPRSResources;
prs_config_t prs_cfg[NR_MAX_PRS_RESOURCES_PER_SET];
} NR_gNB_PRS;
typedef struct {
/// Nfapi ULSCH PDU
nfapi_nr_pusch_pdu_t ulsch_pdu;
@@ -737,6 +742,7 @@ typedef struct PHY_VARS_gNB_s {
NR_gNB_PBCH pbch;
NR_gNB_COMMON common_vars;
NR_gNB_PRACH prach_vars;
NR_gNB_PRS prs_vars;
NR_gNB_PUSCH *pusch_vars[NUMBER_OF_NR_ULSCH_MAX];
NR_gNB_PUCCH_t *pucch[NUMBER_OF_NR_PUCCH_MAX];
NR_gNB_SRS_t *srs[NUMBER_OF_NR_SRS_MAX];
@@ -790,6 +796,9 @@ typedef struct PHY_VARS_gNB_s {
// Mask of occupied RBs, per symbol and PRB
uint32_t rb_mask_ul[14][9];
/// PRS sequence
uint32_t ****nr_gold_prs;
/// Indicator set to 0 after first SR
uint8_t first_sr[NUMBER_OF_NR_SR_MAX];
+18 -1
View File
@@ -347,6 +347,18 @@ typedef struct {
int32_t **ptrs_re_per_slot;
} NR_UE_PDSCH;
#define NR_PRS_IDFT_OVERSAMP_FACTOR 1 // IDFT oversampling factor for NR PRS channel estimates in time domain, ALLOWED value 16x, and 1x is default(ie. IDFT size is frame_params->ofdm_symbol_size)
typedef struct {
prs_config_t prs_cfg;
int32_t reserved;
prs_meas_t **prs_meas;
} NR_PRS_RESOURCE_t;
typedef struct {
uint8_t NumPRSResources;
NR_PRS_RESOURCE_t prs_resource[NR_MAX_PRS_RESOURCES_PER_SET];
} NR_UE_PRS;
#define NR_PDCCH_DEFS_NR_UE
#define NR_NBR_CORESET_ACT_BWP 3 // The number of CoreSets per BWP is limited to 3 (including initial CORESET: ControlResourceId 0)
#define NR_NBR_SEARCHSPACE_ACT_BWP 10 // The number of SearchSpaces per BWP is limited to 10 (including initial SEARCHSPACE: SearchSpaceId 0)
@@ -723,7 +735,9 @@ typedef struct {
NR_UE_DLSCH_t *dlsch_ra[NUMBER_OF_CONNECTED_gNB_MAX];
NR_UE_DLSCH_t *dlsch_p[NUMBER_OF_CONNECTED_gNB_MAX];
NR_UE_DLSCH_t *dlsch_MCH[NUMBER_OF_CONNECTED_gNB_MAX];
NR_UE_PRS *prs_vars[NR_MAX_PRS_COMB_SIZE];
uint8_t prs_active_gNBs;
//Paging parameters
uint32_t IMSImod1024;
uint32_t PF;
@@ -767,6 +781,9 @@ typedef struct {
/// PUSCH DMRS sequence
uint32_t ****nr_gold_pusch_dmrs;
// PRS sequence per gNB, per resource
uint32_t *****nr_gold_prs;
uint32_t X_u[64][839];
// flag to activate PRB based averaging of channel estimates
+43 -2
View File
@@ -63,13 +63,19 @@
#define NR_PSS_LENGTH 127
#define NR_SSS_LENGTH 127
#define NR_MAX_PRS_LENGTH 3264 //272*6(max allocation per RB)*2(QPSK)
#define NR_MAX_PRS_INIT_LENGTH_DWORD 102 // ceil(NR_MAX_CSI_RS_LENGTH/32)
#define NR_MAX_NUM_PRS_SYMB 12
#define NR_MAX_PRS_COMB_SIZE 12
#define NR_MAX_PRS_RESOURCES_PER_SET 64
#define NR_MAX_PRS_MUTING_PATTERN_LENGTH 32
#define NR_PBCH_DMRS_LENGTH 144 // in mod symbols
#define NR_PBCH_DMRS_LENGTH_DWORD 10 // ceil(2(QPSK)*NR_PBCH_DMRS_LENGTH/32)
/*used for the resource mapping*/
#define NR_MAX_PDCCH_DMRS_LENGTH 576 // 16(L)*2(QPSK)*3(3 DMRS symbs per REG)*6(REG per CCE)
#define NR_MAX_PDCCH_SIZE 8192 // It seems it is the max polar coded block size
#define NR_MAX_PDCCH_SIZE 8192 // It seems it is the max polar coded block size
#define NR_MAX_DCI_PAYLOAD_SIZE 64
#define NR_MAX_DCI_SIZE 1728 //16(L)*2(QPSK)*9(12 RE per REG - 3(DMRS))*6(REG per CCE)
#define NR_MAX_DCI_SIZE_DWORD 54 // ceil(NR_MAX_DCI_SIZE/32)
@@ -383,7 +389,42 @@ struct NR_DL_FRAME_PARMS {
uint32_t ofdm_offset_divisor;
};
// PRS config structures
typedef struct {
uint16_t PRSResourceSetPeriod[2]; // [slot period, slot offset] of a PRS resource set
uint16_t PRSResourceOffset; // Slot offset of each PRS resource defined relative to the slot offset of the PRS resource set (0...511)
uint8_t PRSResourceRepetition; // Repetition factor for all PRS resources in resource set (1 /*default*/, 2, 4, 6, 8, 16, 32)
uint8_t PRSResourceTimeGap; // Slot offset between two consecutive repetition indices of all PRS resources in a PRS resource set (1 /*default*/, 2, 4, 6, 8, 16, 32)
uint16_t NumRB; // Number of PRBs allocated to all PRS resources in a PRS resource set (<= 272 and multiples of 4)
uint8_t NumPRSSymbols; // Number of OFDM symbols in a slot allocated to each PRS resource in a PRS resource set
uint8_t SymbolStart; // Starting OFDM symbol of each PRS resource in a PRS resource set
uint16_t RBOffset; // Starting PRB index of all PRS resources in a PRS resource set
uint8_t CombSize; // RE density of all PRS resources in a PRS resource set (2, 4, 6, 12)
uint8_t REOffset; // Starting RE offset in the first OFDM symbol of each PRS resource in a PRS resource set
uint32_t MutingPattern1[32]; // Muting bit pattern option-1, specified as [] or a binary-valued vector of length 2, 4, 6, 8, 16, or 32
uint32_t MutingPattern2[32]; // Muting bit pattern option-2, specified as [] or a binary-valued vector of length 2, 4, 6, 8, 16, or 32
uint8_t MutingBitRepetition; // Muting bit repetition factor, specified as 1, 2, 4, or 8
uint16_t NPRSID; // Sequence identity of each PRS resource in a PRS resource set, specified in the range [0, 4095]
} prs_config_t;
typedef struct {
int8_t gNB_id;
int32_t sfn;
int8_t slot;
int8_t rxAnt_idx;
int32_t dl_toa;
int32_t dl_aoa;
int32_t snr;
int32_t reserved;
} prs_meas_t;
// rel16 prs k_prime table as per ts138.211 sec.7.4.1.7.2
#define K_PRIME_TABLE_ROW_SIZE 4
#define K_PRIME_TABLE_COL_SIZE 12
#define PRS_K_PRIME_TABLE { {0,1,0,1,0,1,0,1,0,1,0,1}, \
{0,2,1,3,0,2,1,3,0,2,1,3}, \
{0,3,1,4,2,5,0,3,1,4,2,5}, \
{0,6,3,9,1,7,4,10,2,8,5,11} };
#define KHz (1000UL)
#define MHz (1000*KHz)
+21 -1
View File
@@ -121,8 +121,9 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
PHY_VARS_gNB *gNB = msgTx->gNB;
NR_DL_FRAME_PARMS *fp=&gNB->frame_parms;
nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
int offset = gNB->CC_id;
int offset = gNB->CC_id, slot_prs;
int txdataF_offset = slot*fp->samples_per_slot_wCP;
prs_config_t *prs_config = NULL;
if ((cfg->cell_config.frame_duplex_type.value == TDD) &&
(nr_slot_select(cfg,frame,slot) == NR_UPLINK_SLOT)) return;
@@ -135,6 +136,21 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
memset(&gNB->common_vars.beam_id[aa][slot*fp->symbols_per_slot],255,fp->symbols_per_slot*sizeof(uint8_t));
}
// Check for PRS slot - section 7.4.1.7.4 in 3GPP rel16 38.211
for(int rsc_id = 0; rsc_id < gNB->prs_vars.NumPRSResources; rsc_id++)
{
prs_config = &gNB->prs_vars.prs_cfg[rsc_id];
for (int i = 0; i < prs_config->PRSResourceRepetition; i++)
{
if( (((frame*fp->slots_per_frame + slot) - (prs_config->PRSResourceSetPeriod[1] + prs_config->PRSResourceOffset)+prs_config->PRSResourceSetPeriod[0])%prs_config->PRSResourceSetPeriod[0]) == i*prs_config->PRSResourceTimeGap )
{
slot_prs = (slot - i*prs_config->PRSResourceTimeGap + fp->slots_per_frame)%fp->slots_per_frame;
LOG_D(PHY,"gNB_TX: frame %d, slot %d, slot_prs %d, PRS Resource ID %d\n",frame, slot, slot_prs, rsc_id);
nr_generate_prs(gNB->nr_gold_prs[rsc_id][slot_prs],&gNB->common_vars.txdataF[0][txdataF_offset], AMP, prs_config, cfg, fp);
}
}
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,1);
for (int i=0; i<fp->Lmax; i++) {
if (msgTx->ssb[i].active) {
@@ -182,6 +198,10 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
//apply the OFDM symbol rotation here
for (aa=0; aa<cfg->carrier_config.num_tx_ant.value; aa++) {
apply_nr_rotation(fp,(int16_t*) &gNB->common_vars.txdataF[aa][txdataF_offset],slot,0,fp->Ncp==EXTENDED?12:14);
T(T_GNB_PHY_DL_OUTPUT_SIGNAL, T_INT(0),
T_INT(frame), T_INT(slot),
T_INT(aa), T_BUFFER(&gNB->common_vars.txdataF[aa][txdataF_offset], fp->samples_per_slot_wCP*sizeof(int32_t)));
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX+offset,0);
+23 -1
View File
@@ -1331,7 +1331,6 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
int frame_rx = proc->frame_rx;
int nr_slot_rx = proc->nr_slot_rx;
fapi_nr_config_request_t *cfg = &ue->nrUE_config;
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_IN);
@@ -1410,6 +1409,29 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
}
}
// Check for PRS slot - section 7.4.1.7.4 in 3GPP rel16 38.211
for(int gNB_id = 0; gNB_id < ue->prs_active_gNBs; gNB_id++)
{
for(int rsc_id = 0; rsc_id < ue->prs_vars[gNB_id]->NumPRSResources; rsc_id++)
{
prs_config_t *prs_config = &ue->prs_vars[gNB_id]->prs_resource[rsc_id].prs_cfg;
for (int i = 0; i < prs_config->PRSResourceRepetition; i++)
{
if( (((frame_rx*fp->slots_per_frame + nr_slot_rx) - (prs_config->PRSResourceSetPeriod[1] + prs_config->PRSResourceOffset) + prs_config->PRSResourceSetPeriod[0])%prs_config->PRSResourceSetPeriod[0]) == i*prs_config->PRSResourceTimeGap)
{
for(int j = prs_config->SymbolStart; j < (prs_config->SymbolStart+prs_config->NumPRSSymbols); j++)
{
nr_slot_fep(ue,
proc,
(j%fp->symbols_per_slot),
nr_slot_rx);
}
nr_prs_channel_estimation(gNB_id,rsc_id,i,ue,proc,fp);
}
} // for i
} // for rsc_id
} // for gNB_id
if ((frame_rx%64 == 0) && (nr_slot_rx==0)) {
LOG_I(NR_PHY,"============================================\n");
// fixed text + 8 HARQs rounds à 10 ("999999999/") + NULL
+136
View File
@@ -0,0 +1,136 @@
/*
* 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
*/
/*! \file openair2/COMMON/prs_nr_paramdef.f
* \brief definition of configuration parameters for PRS
* \author
* \date 2022
* \version 0.1
* \company EURECOM
* \email:
* \note
* \warning
*/
#ifndef __PRS_NR_PARAMDEF__H__
#define __PRS_NR_PARAMDEF__H__
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/* PRS configuration section names */
#define CONFIG_STRING_PRS_LIST "PRSs"
#define CONFIG_STRING_PRS_CONFIG "prs_config"
/* Global parameters */
#define CONFIG_STRING_ACTIVE_GNBs "Active_gNBs"
#define HELP_STRING_ACTIVE_GNBs "Number of active gNBs simultaneously transmitting PRS signal to a UE\n"
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
/* PRS configuration parameters */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
#define PRS_GLOBAL_PARAMS_DESC { \
{CONFIG_STRING_ACTIVE_GNBs, HELP_STRING_ACTIVE_GNBs, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0} \
}
#define PRS_ACTIVE_GNBS_IDX 0
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
/* PRS configuration parameters names */
#define CONFIG_STRING_GNB_ID "gNB_id"
#define CONFIG_STRING_NUM_PRS_RESOURCES "NumPRSResources"
#define CONFIG_STRING_PRS_RESOURCE_SET_PERIOD_LIST "PRSResourceSetPeriod"
#define CONFIG_STRING_PRS_SYMBOL_START_LIST "SymbolStart"
#define CONFIG_STRING_PRS_NUM_SYMBOLS_LIST "NumPRSSymbols"
#define CONFIG_STRING_PRS_NUM_RB "NumRB"
#define CONFIG_STRING_PRS_RB_OFFSET "RBOffset"
#define CONFIG_STRING_PRS_COMB_SIZE "CombSize"
#define CONFIG_STRING_PRS_RE_OFFSET_LIST "REOffset"
#define CONFIG_STRING_PRS_RESOURCE_OFFSET_LIST "PRSResourceOffset"
#define CONFIG_STRING_PRS_RESOURCE_REPETITION "PRSResourceRepetition"
#define CONFIG_STRING_PRS_RESOURCE_TIME_GAP "PRSResourceTimeGap"
#define CONFIG_STRING_PRS_ID_LIST "NPRS_ID"
#define CONFIG_STRING_PRS_MUTING_PATTERN1_LIST "MutingPattern1"
#define CONFIG_STRING_PRS_MUTING_PATTERN2_LIST "MutingPattern2"
#define CONFIG_STRING_PRS_MUTING_BIT_REPETITION "MutingBitRepetition"
/* Help string for PRS parameters */
#define HELP_STRING_GNB_ID "gNB index for UE (<= CombSize)\n"
#define HELP_STRING_NUM_PRS_RESOURCES "Number of PRS resources in a PRS resource set\n"
#define HELP_STRING_PRS_RESOURCE_SET_PERIOD_LIST "[slot period, slot offset] of a PRS resource set\n"
#define HELP_STRING_PRS_SYMBOL_START_LIST "Starting OFDM symbol of each PRS resource in a PRS resource set\n"
#define HELP_STRING_PRS_NUM_SYMBOLS_LIST "Number of OFDM symbols in a slot for each PRS resource in a PRS resource set\n"
#define HELP_STRING_PRS_NUM_RB "Number of PRBs allocated to all PRS resources in a PRS resource set (<= 272 and multiples of 4)\n"
#define HELP_STRING_PRS_RB_OFFSET "Starting PRB index of all PRS resources in a PRS resource set\n"
#define HELP_STRING_PRS_COMB_SIZE "RE density of all PRS resources in a PRS resource set (2, 4, 6, 12)\n"
#define HELP_STRING_PRS_RE_OFFSET_LIST "Starting RE offset in the first OFDM symbol of each PRS resource in a PRS resource set\n"
#define HELP_STRING_PRS_RESOURCE_OFFSET_LIST "Slot offset of each PRS resource defined relative to the slot offset of the PRS resource set (0...511)\n"
#define HELP_STRING_PRS_RESOURCE_REPETITION "Repetition factor for all PRS resources in resource set (1 /*default*/, 2, 4, 6, 8, 16, 32)\n"
#define HELP_STRING_PRS_RESOURCE_TIME_GAP "Slot offset between two consecutive repetition indices of all PRS resources in a PRS resource set (1 /*default*/, 2, 4, 6, 8, 16, 32)\n"
#define HELP_STRING_PRS_ID_LIST "Sequence identity of each PRS resource in a PRS resource set, specified in the range [0, 4095]\n"
#define HELP_STRING_PRS_MUTING_PATTERN1_LIST "Muting bit pattern option-1, specified as [] or a binary-valued vector of length 2, 4, 6, 8, 16, or 32\n"
#define HELP_STRING_PRS_MUTING_PATTERN2_LIST "Muting bit pattern option-2, specified as [] or a binary-valued vector of length 2, 4, 6, 8, 16, or 32\n"
#define HELP_STRING_PRS_MUTING_BIT_REPETITION "Muting bit repetition factor, specified as 1, 2, 4, or 8\n"
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/* PRS configuration parameters */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#define PRS_PARAMS_DESC { \
{CONFIG_STRING_GNB_ID, HELP_STRING_GNB_ID, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
{CONFIG_STRING_NUM_PRS_RESOURCES, HELP_STRING_NUM_PRS_RESOURCES, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
{CONFIG_STRING_PRS_RESOURCE_SET_PERIOD_LIST, HELP_STRING_PRS_RESOURCE_SET_PERIOD_LIST, 0, uptr:NULL, defintarrayval:0, TYPE_UINTARRAY, 0}, \
{CONFIG_STRING_PRS_SYMBOL_START_LIST, HELP_STRING_PRS_SYMBOL_START_LIST, 0, uptr:NULL, defintarrayval:0, TYPE_UINTARRAY, 0}, \
{CONFIG_STRING_PRS_NUM_SYMBOLS_LIST, HELP_STRING_PRS_NUM_SYMBOLS_LIST, 0, uptr:NULL, defintarrayval:0, TYPE_UINTARRAY, 0}, \
{CONFIG_STRING_PRS_NUM_RB, HELP_STRING_PRS_NUM_RB, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
{CONFIG_STRING_PRS_RB_OFFSET, HELP_STRING_PRS_RB_OFFSET, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
{CONFIG_STRING_PRS_COMB_SIZE, HELP_STRING_PRS_COMB_SIZE, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
{CONFIG_STRING_PRS_RE_OFFSET_LIST, HELP_STRING_PRS_RE_OFFSET_LIST, 0, uptr:NULL, defintarrayval:0, TYPE_UINTARRAY, 0}, \
{CONFIG_STRING_PRS_RESOURCE_OFFSET_LIST, HELP_STRING_PRS_RESOURCE_OFFSET_LIST, 0, uptr:NULL, defintarrayval:0, TYPE_UINTARRAY, 0}, \
{CONFIG_STRING_PRS_RESOURCE_REPETITION, HELP_STRING_PRS_RESOURCE_REPETITION, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
{CONFIG_STRING_PRS_RESOURCE_TIME_GAP, HELP_STRING_PRS_RESOURCE_TIME_GAP, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
{CONFIG_STRING_PRS_ID_LIST, HELP_STRING_PRS_ID_LIST, 0, uptr:NULL, defintarrayval:0, TYPE_UINTARRAY, 0}, \
{CONFIG_STRING_PRS_MUTING_PATTERN1_LIST, HELP_STRING_PRS_MUTING_PATTERN1_LIST, 0, uptr:NULL, defintarrayval:0, TYPE_UINTARRAY, 0}, \
{CONFIG_STRING_PRS_MUTING_PATTERN2_LIST, HELP_STRING_PRS_MUTING_PATTERN2_LIST, 0, uptr:NULL, defintarrayval:0, TYPE_UINTARRAY, 0}, \
{CONFIG_STRING_PRS_MUTING_BIT_REPETITION, HELP_STRING_PRS_MUTING_BIT_REPETITION, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0} \
}
#define PRS_GNB_ID 0
#define NUM_PRS_RESOURCES 1
#define PRS_RESOURCE_SET_PERIOD_LIST 2
#define PRS_SYMBOL_START_LIST 3
#define PRS_NUM_SYMBOLS_LIST 4
#define PRS_NUM_RB 5
#define PRS_RB_OFFSET 6
#define PRS_COMB_SIZE 7
#define PRS_RE_OFFSET_LIST 8
#define PRS_RESOURCE_OFFSET_LIST 9
#define PRS_RESOURCE_REPETITION 10
#define PRS_RESOURCE_TIME_GAP 11
#define PRS_ID_LIST 12
#define PRS_MUTING_PATTERN1_LIST 13
#define PRS_MUTING_PATTERN2_LIST 14
#define PRS_MUTING_BIT_REPETITION 15
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
#endif
+12 -6
View File
@@ -103,6 +103,8 @@ typedef enum {
#define CONFIG_STRING_RU_SL_AHEAD "sl_ahead"
#define CONFIG_STRING_RU_NR_FLAG "nr_flag"
#define CONFIG_STRING_RU_NR_SCS_FOR_RASTER "nr_scs_for_raster"
#define CONFIG_STRING_RU_TX_SUBDEV "tx_subdev"
#define CONFIG_STRING_RU_RX_SUBDEV "rx_subdev"
#define CONFIG_STRING_RU_RXFH_CORE_ID "rxfh_core_id"
#define CONFIG_STRING_RU_TXFH_CORE_ID "txfh_core_id"
#define CONFIG_STRING_RU_TP_CORES "tp_cores"
@@ -154,12 +156,14 @@ typedef enum {
#define RU_SL_AHEAD 30
#define RU_NR_FLAG 31
#define RU_NR_SCS_FOR_RASTER 32
#define RU_RXFH_CORE_ID 33
#define RU_TXFH_CORE_ID 34
#define RU_TP_CORES 35
#define RU_NUM_TP_CORES 36
#define RU_NUM_INTERFACES 37
#define RU_HALF_SLOT_PARALLELIZATION 38
#define RU_TX_SUBDEV 33
#define RU_RX_SUBDEV 34
#define RU_RXFH_CORE_ID 35
#define RU_TXFH_CORE_ID 36
#define RU_TP_CORES 37
#define RU_NUM_TP_CORES 38
#define RU_NUM_INTERFACES 39
#define RU_HALF_SLOT_PARALLELIZATION 40
/*-----------------------------------------------------------------------------------------------------------------------------------------*/
/* RU configuration parameters */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
@@ -198,6 +202,8 @@ typedef enum {
{CONFIG_STRING_RU_SL_AHEAD, HLP_RU_SL_AHEAD, 0, iptr:NULL, defintval:6, TYPE_INT, 0}, \
{CONFIG_STRING_RU_NR_FLAG, HLP_RU_NR_FLAG, 0, iptr:NULL, defintval:0, TYPE_INT, 0}, \
{CONFIG_STRING_RU_NR_SCS_FOR_RASTER, HLP_RU_NR_SCS_FOR_RASTER, 0, iptr:NULL, defintval:1, TYPE_INT, 0}, \
{CONFIG_STRING_RU_TX_SUBDEV, NULL, 0, strptr:NULL, defstrval:"", TYPE_STRING, 0}, \
{CONFIG_STRING_RU_RX_SUBDEV, NULL, 0, strptr:NULL, defstrval:"", TYPE_STRING, 0}, \
{CONFIG_STRING_RU_RXFH_CORE_ID, HLP_RU_RXFH_CORE_ID, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \
{CONFIG_STRING_RU_TXFH_CORE_ID, HLP_RU_TXFH_CORE_ID, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \
{CONFIG_STRING_RU_TP_CORES, HLP_RU_TP_CORES, 0, uptr:NULL, defintarrayval:DEFRUTPCORES, TYPE_INTARRAY, 8}, \
+1
View File
@@ -155,6 +155,7 @@ void *gNB_app_task(void *args_p)
LOG_I(PHY, "%s() Task ready initialize structures\n", __FUNCTION__);
RCconfig_NR_L1();
RCconfig_nr_prs();
if (RC.nb_nr_macrlc_inst>0) RCconfig_nr_macrlc();
+96
View File
@@ -55,6 +55,7 @@
#include "nfapi_pnf.h"
//#include "L1_paramdef.h"
#include "prs_nr_paramdef.h"
#include "L1_nr_paramdef.h"
#include "MACRLC_nr_paramdef.h"
#include "common/config/config_userapi.h"
@@ -671,6 +672,100 @@ void RCconfig_nr_flexran()
}
}
void RCconfig_nr_prs(void)
{
uint16_t j = 0, k = 0;
prs_config_t *prs_config = NULL;
char str[7][100] = {0};
paramdef_t PRS_Params[] = PRS_PARAMS_DESC;
paramlist_def_t PRS_ParamList = {CONFIG_STRING_PRS_CONFIG,NULL,0};
if (RC.gNB == NULL) {
RC.gNB = (PHY_VARS_gNB **)malloc((1+NUMBER_OF_gNB_MAX)*sizeof(PHY_VARS_gNB*));
LOG_I(NR_PHY,"RC.gNB = %p\n",RC.gNB);
memset(RC.gNB,0,(1+NUMBER_OF_gNB_MAX)*sizeof(PHY_VARS_gNB*));
}
config_getlist( &PRS_ParamList,PRS_Params,sizeof(PRS_Params)/sizeof(paramdef_t), NULL);
if (PRS_ParamList.numelt > 0) {
for (j = 0; j < RC.nb_nr_L1_inst; j++) {
if (RC.gNB[j] == NULL) {
RC.gNB[j] = (PHY_VARS_gNB *)malloc(sizeof(PHY_VARS_gNB));
LOG_I(NR_PHY,"RC.gNB[%d] = %p\n",j,RC.gNB[j]);
memset(RC.gNB[j],0,sizeof(PHY_VARS_gNB));
RC.gNB[j]->Mod_id = j;
}
RC.gNB[j]->prs_vars.NumPRSResources = *(PRS_ParamList.paramarray[j][NUM_PRS_RESOURCES].uptr);
for (k = 0; k < RC.gNB[j]->prs_vars.NumPRSResources; k++)
{
prs_config = &RC.gNB[j]->prs_vars.prs_cfg[k];
prs_config->PRSResourceSetPeriod[0] = PRS_ParamList.paramarray[j][PRS_RESOURCE_SET_PERIOD_LIST].uptr[0];
prs_config->PRSResourceSetPeriod[1] = PRS_ParamList.paramarray[j][PRS_RESOURCE_SET_PERIOD_LIST].uptr[1];
// per PRS resources parameters
prs_config->SymbolStart = PRS_ParamList.paramarray[j][PRS_SYMBOL_START_LIST].uptr[k];
prs_config->NumPRSSymbols = PRS_ParamList.paramarray[j][PRS_NUM_SYMBOLS_LIST].uptr[k];
prs_config->REOffset = PRS_ParamList.paramarray[j][PRS_RE_OFFSET_LIST].uptr[k];
prs_config->PRSResourceOffset = PRS_ParamList.paramarray[j][PRS_RESOURCE_OFFSET_LIST].uptr[k];
prs_config->NPRSID = PRS_ParamList.paramarray[j][PRS_ID_LIST].uptr[k];
// Common parameters to all PRS resources
prs_config->NumRB = *(PRS_ParamList.paramarray[j][PRS_NUM_RB].uptr);
prs_config->RBOffset = *(PRS_ParamList.paramarray[j][PRS_RB_OFFSET].uptr);
prs_config->CombSize = *(PRS_ParamList.paramarray[j][PRS_COMB_SIZE].uptr);
prs_config->PRSResourceRepetition = *(PRS_ParamList.paramarray[j][PRS_RESOURCE_REPETITION].uptr);
prs_config->PRSResourceTimeGap = *(PRS_ParamList.paramarray[j][PRS_RESOURCE_TIME_GAP].uptr);
prs_config->MutingBitRepetition = *(PRS_ParamList.paramarray[j][PRS_MUTING_BIT_REPETITION].uptr);
for (int l = 0; l < PRS_ParamList.paramarray[j][PRS_MUTING_PATTERN1_LIST].numelt; l++)
{
prs_config->MutingPattern1[l] = PRS_ParamList.paramarray[j][PRS_MUTING_PATTERN1_LIST].uptr[l];
if (k == 0) // print only for 0th resource
snprintf(str[5]+strlen(str[5]),sizeof(str[5])-strlen(str[5]),"%d, ",prs_config->MutingPattern1[l]);
}
for (int l = 0; l < PRS_ParamList.paramarray[j][PRS_MUTING_PATTERN2_LIST].numelt; l++)
{
prs_config->MutingPattern2[l] = PRS_ParamList.paramarray[j][PRS_MUTING_PATTERN2_LIST].uptr[l];
if (k == 0) // print only for 0th resource
snprintf(str[6]+strlen(str[6]),sizeof(str[6])-strlen(str[6]),"%d, ",prs_config->MutingPattern2[l]);
}
// print to buffer
snprintf(str[0]+strlen(str[0]),sizeof(str[0])-strlen(str[0]),"%d, ",prs_config->SymbolStart);
snprintf(str[1]+strlen(str[1]),sizeof(str[1])-strlen(str[1]),"%d, ",prs_config->NumPRSSymbols);
snprintf(str[2]+strlen(str[2]),sizeof(str[2])-strlen(str[2]),"%d, ",prs_config->REOffset);
snprintf(str[3]+strlen(str[3]),sizeof(str[3])-strlen(str[3]),"%d, ",prs_config->PRSResourceOffset);
snprintf(str[4]+strlen(str[4]),sizeof(str[4])-strlen(str[4]),"%d, ",prs_config->NPRSID);
} // for k
prs_config = &RC.gNB[j]->prs_vars.prs_cfg[0];
LOG_I(PHY, "-----------------------------------------\n");
LOG_I(PHY, "PRS Config for gNB_id %d @ %p\n", j, prs_config);
LOG_I(PHY, "-----------------------------------------\n");
LOG_I(PHY, "NumPRSResources \t%d\n", RC.gNB[j]->prs_vars.NumPRSResources);
LOG_I(PHY, "PRSResourceSetPeriod \t[%d, %d]\n", prs_config->PRSResourceSetPeriod[0], prs_config->PRSResourceSetPeriod[1]);
LOG_I(PHY, "NumRB \t\t\t%d\n", prs_config->NumRB);
LOG_I(PHY, "RBOffset \t\t%d\n", prs_config->RBOffset);
LOG_I(PHY, "CombSize \t\t%d\n", prs_config->CombSize);
LOG_I(PHY, "PRSResourceRepetition \t%d\n", prs_config->PRSResourceRepetition);
LOG_I(PHY, "PRSResourceTimeGap \t%d\n", prs_config->PRSResourceTimeGap);
LOG_I(PHY, "MutingBitRepetition \t%d\n", prs_config->MutingBitRepetition);
LOG_I(PHY, "SymbolStart \t\t[%s\b\b]\n", str[0]);
LOG_I(PHY, "NumPRSSymbols \t\t[%s\b\b]\n", str[1]);
LOG_I(PHY, "REOffset \t\t[%s\b\b]\n", str[2]);
LOG_I(PHY, "PRSResourceOffset \t[%s\b\b]\n", str[3]);
LOG_I(PHY, "NPRS_ID \t\t[%s\b\b]\n", str[4]);
LOG_I(PHY, "MutingPattern1 \t\t[%s\b\b]\n", str[5]);
LOG_I(PHY, "MutingPattern2 \t\t[%s\b\b]\n", str[6]);
LOG_I(PHY, "-----------------------------------------\n");
} // for j
}
else
{
LOG_E(PHY,"No " CONFIG_STRING_PRS_CONFIG " configuration found..!!\n");
}
}
void RCconfig_NR_L1(void) {
int j;
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
@@ -2264,6 +2359,7 @@ void nr_read_config_and_init(void) {
uint32_t gnb_nb = RC.nb_nr_inst;
RCconfig_NR_L1();
RCconfig_nr_prs();
RCconfig_nr_macrlc();
LOG_I(PHY, "%s() RC.nb_nr_L1_inst:%d\n", __FUNCTION__, RC.nb_nr_L1_inst);
+1
View File
@@ -92,6 +92,7 @@ typedef struct ru_config_s {
*/
extern void NRRCconfig_RU(void);
extern void RCconfig_nr_flexran(void);
extern void RCconfig_nr_prs(void);
extern void RCconfig_NR_L1(void);
extern void RCconfig_nr_macrlc(void);
extern int RCconfig_nr_gtpu(void );
+1 -1
View File
@@ -73,7 +73,7 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB,
nfapi_nr_dl_tti_request_t *DL_req = &gNB->DL_req[0];
nfapi_nr_dl_tti_pdcch_pdu_rel15_t **pdcch = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t **)gNB->pdcch_pdu_idx[CC_idP];
nfapi_nr_ul_tti_request_t *future_ul_tti_req =
&gNB->UL_tti_req_ahead[CC_idP][(slotP + num_slots - 1) % num_slots];
&gNB->UL_tti_req_ahead[CC_idP][(slotP + num_slots - 1) % num_slots];
nfapi_nr_ul_dci_request_t *UL_dci_req = &gNB->UL_dci_req[0];
nfapi_nr_tx_data_request_t *TX_req = &gNB->TX_req[0];
@@ -47,14 +47,14 @@ static void nr_fill_nfapi_pucch(gNB_MAC_INST *nrmac,
{
nfapi_nr_ul_tti_request_t *future_ul_tti_req =
&nrmac->UL_tti_req_ahead[0][pucch->ul_slot];
AssertFatal(future_ul_tti_req->SFN == pucch->frame
&& future_ul_tti_req->Slot == pucch->ul_slot,
"Current %4d.%2d : future UL_tti_req's frame.slot %4d.%2d does not match PUCCH %4d.%2d\n",
frame,slot,
future_ul_tti_req->SFN,
future_ul_tti_req->Slot,
pucch->frame,
pucch->ul_slot);
if (future_ul_tti_req->SFN != pucch->frame || future_ul_tti_req->Slot != pucch->ul_slot)
LOG_W(MAC,
"Current %d.%d : future UL_tti_req's frame.slot %4d.%2d does not match PUCCH %4d.%2d\n",
frame,slot,
future_ul_tti_req->SFN,
future_ul_tti_req->Slot,
pucch->frame,
pucch->ul_slot);
// n_pdus is number of pdus, so, in the array, it is the index of the next free element
if (future_ul_tti_req->n_pdus >= sizeofArray(future_ul_tti_req->pdus_list) ) {
LOG_E(NR_MAC,"future_ul_tti_req->n_pdus %d is full, slot: %d, sr flag %d dropping request\n",
@@ -2062,17 +2062,18 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot)
/* PUSCH in a later slot, but corresponding DCI now! */
nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[module_id]->UL_tti_req_ahead[0][sched_pusch->slot];
AssertFatal(future_ul_tti_req->SFN == sched_pusch->frame
&& future_ul_tti_req->Slot == sched_pusch->slot,
"%d.%d future UL_tti_req's frame.slot %d.%d does not match PUSCH %d.%d\n",
frame, slot,
future_ul_tti_req->SFN,
future_ul_tti_req->Slot,
sched_pusch->frame,
sched_pusch->slot);
if (future_ul_tti_req->SFN != sched_pusch->frame || future_ul_tti_req->Slot != sched_pusch->slot)
LOG_W(MAC,
"%d.%d future UL_tti_req's frame.slot %d.%d does not match PUSCH %d.%d\n",
frame, slot,
future_ul_tti_req->SFN,
future_ul_tti_req->Slot,
sched_pusch->frame,
sched_pusch->slot);
AssertFatal(future_ul_tti_req->n_pdus <
sizeof(future_ul_tti_req->pdus_list) / sizeof(future_ul_tti_req->pdus_list[0]),
"Invalid future_ul_tti_req->n_pdus %d\n", future_ul_tti_req->n_pdus);
future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE;
future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t);
nfapi_nr_pusch_pdu_t *pusch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pusch_pdu;
@@ -284,5 +284,6 @@ int handle_bcch_dlsch(module_id_t module_id, int cc_id, unsigned int gNB_index,
int handle_dci(module_id_t module_id, int cc_id, unsigned int gNB_index, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci);
#endif
File diff suppressed because it is too large Load Diff
+5 -1
View File
@@ -187,7 +187,11 @@ typedef struct {
int rx_num_channels;
//! number of TX channels (=TX antennas)
int tx_num_channels;
//! \brief RX base addresses for mmapped_dma or direct access
//! rx daughter card
char* rx_subdev;
//! tx daughter card
char* tx_subdev;
//! \brief RX base addresses for mmapped_dma
int32_t *rxbase[4];
//! \brief RX buffer size for direct access
int rxsize;
+77 -28
View File
@@ -203,8 +203,9 @@ static int sync_to_gps(openair0_device *device) {
//Set to GPS time
uhd::time_spec_t gps_time = uhd::time_spec_t(time_t(s->usrp->get_mboard_sensor("gps_time", mboard).to_int()));
//s->usrp->set_time_next_pps(gps_time+1.0, mboard);
s->usrp->set_time_next_pps(uhd::time_spec_t(0.0));
s->usrp->set_time_next_pps(gps_time+1.0, mboard);
//s->usrp->set_time_next_pps(uhd::time_spec_t(0.0));
//Wait for it to apply
//The wait is 2 seconds because N-Series has a known issue where
//the time at the last PPS does not properly update at the PPS edge
@@ -215,10 +216,10 @@ static int sync_to_gps(openair0_device *device) {
uhd::time_spec_t time_last_pps = s->usrp->get_time_last_pps(mboard);
std::cout << "USRP time: " << (boost::format("%0.9f") % time_last_pps.get_real_secs()) << std::endl;
std::cout << "GPSDO time: " << (boost::format("%0.9f") % gps_time.get_real_secs()) << std::endl;
//if (gps_time.get_real_secs() == time_last_pps.get_real_secs())
// std::cout << std::endl << "SUCCESS: USRP time synchronized to GPS time" << std::endl << std::endl;
//else
// std::cerr << std::endl << "ERROR: Failed to synchronize USRP time to GPS time" << std::endl << std::endl;
if (gps_time.get_real_secs() == time_last_pps.get_real_secs())
std::cout << std::endl << "SUCCESS: USRP time synchronized to GPS time" << std::endl << std::endl;
else
std::cerr << std::endl << "ERROR: Failed to synchronize USRP time to GPS time" << std::endl << std::endl;
}
if (num_gps_locked == num_mboards and num_mboards > 1) {
@@ -295,15 +296,18 @@ static int trx_usrp_start(openair0_device *device) {
//s->first_rx = 1;
s->rx_timestamp = 0;
s->usrp->set_time_next_pps(uhd::time_spec_t(0.0));
// wait for the pps to change
uhd::time_spec_t time_last_pps = s->usrp->get_time_last_pps();
while (time_last_pps == s->usrp->get_time_last_pps()) {
//wait for next pps
uhd::time_spec_t last_pps = s->usrp->get_time_last_pps();
uhd::time_spec_t current_pps = s->usrp->get_time_last_pps();
while(current_pps == last_pps) {
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
current_pps = s->usrp->get_time_last_pps();
}
LOG_I(HW,"current pps at %f, starting streaming at %f\n",current_pps.get_real_secs(),current_pps.get_real_secs()+1.0);
uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
cmd.time_spec = uhd::time_spec_t(1.0);
cmd.time_spec = uhd::time_spec_t(current_pps+1.0);
cmd.stream_now = false; // start at constant delay
s->rx_stream->issue_stream_cmd(cmd);
@@ -440,7 +444,14 @@ static int trx_usrp_write(openair0_device *device,
for (int j=0; j<nsamps2; j++) {
#if defined(__x86_64__) || defined(__i386__)
#ifdef __AVX2__
buff_tx[i][j] = _mm256_slli_epi16(((__m256i *)buff[i])[j],4);
if ((((uintptr_t) buff[i])&0x1F)==0) {
buff_tx[i][j] = _mm256_slli_epi16(((__m256i *)buff[i])[j],4);
}
else
{
__m256i tmp=_mm256_loadu_si256(((__m256i *)buff[i])+j);
buff_tx[i][j] = _mm256_slli_epi16(tmp,4);
}
#else
buff_tx[i][j] = _mm_slli_epi16(((__m128i *)buff[i])[j],4);
#endif
@@ -580,7 +591,14 @@ void *trx_usrp_write_thread(void * arg){
for (int j=0; j<nsamps2; j++) {
#if defined(__x86_64__) || defined(__i386__)
#ifdef __AVX2__
buff_tx[i][j] = _mm256_slli_epi16(((__m256i *)buff[i])[j],4);
if ((((uintptr_t) buff[i])&0x1F)==0) {
buff_tx[i][j] = _mm256_slli_epi16(((__m256i *)buff[i])[j],4);
}
else
{
__m256i tmp=_mm256_loadu_si256(((__m256i *)buff[i])+j);
buff_tx[i][j] = _mm256_slli_epi16(tmp,4);
}
#else
buff_tx[i][j] = _mm_slli_epi16(((__m128i *)buff[i])[j],4);
#endif
@@ -727,17 +745,18 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
// bring RX data into 12 LSBs for softmodem RX
for (int i=0; i<cc; i++) {
for (int j=0; j<nsamps2; j++) {
#if defined(__x86_64__) || defined(__i386__)
#ifdef __AVX2__
// FK: in some cases the buffer might not be 32 byte aligned, so we cannot use avx2
if ((((uintptr_t) buff[i])&0x1F)==0) {
for (int j=0; j<nsamps2; j++)
((__m256i *)buff[i])[j] = _mm256_srai_epi16(buff_tmp[i][j],rxshift);
((__m256i *)buff[i])[j] = _mm256_srai_epi16(buff_tmp[i][j],rxshift);
} else {
for (int j=0; j<(nsamps2<<1); j++)
((__m128i *)buff[i])[j] = _mm_srai_epi16(((__m128i *)buff_tmp[i])[j],rxshift);
__m256i tmp=_mm256_srai_epi16(buff_tmp[i][j],rxshift);
_mm256_storeu_si256(((__m256i *)buff[i])+j, tmp);
}
}
#else
for (int j=0; j<nsamps2; j++)
((__m128i *)buff[i])[j] = _mm_srai_epi16(buff_tmp[i][j],rxshift);
@@ -1048,7 +1067,7 @@ extern "C" {
sscanf(uhd::get_version_string().c_str(),"%d.%d.%d",&vers,&subvers,&subsubvers);
LOG_I(HW,"UHD version %s (%d.%d.%d)\n",
uhd::get_version_string().c_str(),vers,subvers,subsubvers);
std::string args;
std::string args,tx_subdev,rx_subdev;
if (openair0_cfg[0].sdr_addrs == NULL) {
args = "type=b200";
@@ -1169,12 +1188,16 @@ extern "C" {
LOG_I(HW,"USRP fails to sync with GPS. Exiting.\n");
exit(EXIT_FAILURE);
}
} else if (s->usrp->get_clock_source(0) == "external") {
if (check_ref_locked(s,0)) {
LOG_I(HW,"USRP locked to external reference!\n");
} else {
LOG_I(HW,"Failed to lock to external reference. Exiting.\n");
exit(EXIT_FAILURE);
} else {
s->usrp->set_time_next_pps(uhd::time_spec_t(0.0));
if (s->usrp->get_clock_source(0) == "external") {
if (check_ref_locked(s,0)) {
LOG_I(HW,"USRP locked to external reference!\n");
} else {
LOG_I(HW,"Failed to lock to external reference. Exiting.\n");
exit(EXIT_FAILURE);
}
}
}
@@ -1198,6 +1221,12 @@ extern "C" {
LOG_I(HW,"%s() sample_rate:%u\n", __FUNCTION__, (int)openair0_cfg[0].sample_rate);
switch ((int)openair0_cfg[0].sample_rate) {
case 184320000:
// from usrp_time_offset
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 15; //to be checked
break;
case 122880000:
// from usrp_time_offset
//openair0_cfg[0].samples_per_packet = 2048;
@@ -1210,8 +1239,8 @@ extern "C" {
// from usrp_time_offset
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 15; //to be checked
openair0_cfg[0].tx_bw = 80e6;
openair0_cfg[0].rx_bw = 80e6;
//openair0_cfg[0].tx_bw = 80e6;
//openair0_cfg[0].rx_bw = 80e6;
break;
case 61440000:
@@ -1237,6 +1266,13 @@ extern "C" {
openair0_cfg[0].rx_bw = 20e6;
break;
case 23040000:
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 15;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
case 15360000:
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 45;
@@ -1338,6 +1374,18 @@ extern "C" {
openair0_cfg[0].iq_txshift = 4;//shift
openair0_cfg[0].iq_rxrescale = 15;//rescale iqs
if(openair0_cfg[0].tx_subdev!=NULL){
LOG_I(HW, "openair0_cfg[0].tx_subdev == %s\n", openair0_cfg[0].tx_subdev);
tx_subdev = openair0_cfg[0].tx_subdev;
s->usrp->set_tx_subdev_spec(tx_subdev);
}
if(openair0_cfg[0].rx_subdev!=NULL){
LOG_I(HW, "openair0_cfg[0].rx_subdev == %s\n", openair0_cfg[0].rx_subdev);
rx_subdev = openair0_cfg[0].rx_subdev;
s->usrp->set_rx_subdev_spec(rx_subdev);
}
for(int i=0; i<((int) s->usrp->get_rx_num_channels()); i++) {
if (i<openair0_cfg[0].rx_num_channels) {
s->usrp->set_rx_rate(openair0_cfg[0].sample_rate,i+choffset);
@@ -1383,7 +1431,7 @@ extern "C" {
LOG_I(HW,"Actual master clock: %fMHz...\n",s->usrp->get_master_clock_rate()/1e6);
LOG_I(HW,"Actual clock source %s...\n",s->usrp->get_clock_source(0).c_str());
LOG_I(HW,"Actual time source %s...\n",s->usrp->get_time_source(0).c_str());
sleep(1);
// create tx & rx streamer
uhd::stream_args_t stream_args_rx("sc16", "sc16");
int samples=openair0_cfg[0].sample_rate;
@@ -1437,6 +1485,7 @@ extern "C" {
LOG_I(HW," Actual TX packet size: %lu\n",s->tx_stream->get_max_num_samps());
}
std::cout << boost::format("Using Device: %s") % s->usrp->get_pp_string() << std::endl;
LOG_I(HW,"Device timestamp: %f...\n", s->usrp->get_time_now().get_real_secs());
device->trx_write_func = trx_usrp_write;
device->trx_read_func = trx_usrp_read;
@@ -0,0 +1,290 @@
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 = 311; mnc = 480; mnc_length = 3;});
tr_s_preference = "local_mac"
////////// Physical parameters:
min_rxtxtime = 6;
servingCellConfigCommon = (
{
# spCellConfigCommon
physCellId = 0;
# downlinkConfigCommon
#frequencyInfoDL
# this is pointA + 23 PRBs@120kHz SCS (same as initial BWP)
absoluteFrequencySSB = 2071241;
dl_frequencyBand = 261;
# this is 27.900 GHz
dl_absoluteFrequencyPointA = 2070833;
#scs-SpecificCarrierList
dl_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
dl_subcarrierSpacing = 3;
dl_carrierBandwidth = 64;
#initialDownlinkBWP
#genericParameters
# this is RBstart=0,L=32 (275*(L-1))+RBstart
initialDLBWPlocationAndBandwidth = 8525;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialDLBWPsubcarrierSpacing = 3;
#pdcch-ConfigCommon
initialDLBWPcontrolResourceSetZero = 12;
initialDLBWPsearchSpaceZero = 0;
#uplinkConfigCommon
#frequencyInfoUL
ul_frequencyBand = 261;
#scs-SpecificCarrierList
ul_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
ul_subcarrierSpacing = 3;
ul_carrierBandwidth = 64;
pMax = 20;
#initialUplinkBWP
#genericParameters
initialULBWPlocationAndBandwidth = 8525;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialULBWPsubcarrierSpacing = 3;
#rach-ConfigCommon
#rach-ConfigGeneric
prach_ConfigurationIndex = 52;
#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 = 7;
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
#0=oneeighth,1=onefourth,2=half,3=one,4=two,5=four,6=eight,7=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4;
#oneHalf (0..15) 4,8,12,16,...60,64
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 7;
#ra_ContentionResolutionTimer
#(0..7) 8,16,24,32,40,48,56,64
ra_ContentionResolutionTimer = 7;
rsrp_ThresholdSSB = 19;
#prach-RootSequenceIndex_PR
#1 = 839, 2 = 139
prach_RootSequenceIndex_PR = 2;
prach_RootSequenceIndex = 1;
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
#
msg1_SubcarrierSpacing = 3,
# restrictedSetConfig
# 0=unrestricted, 1=restricted type A, 2=restricted type B
restrictedSetConfig = 0,
msg3_DeltaPreamble = 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 = 3;
ssb_PositionsInBurst_Bitmap = 0x0001000100010001L;
# ssb_periodicityServingCell
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
ssb_periodicityServingCell = 1;
# dmrs_TypeA_position
# 0 = pos2, 1 = pos3
dmrs_TypeA_Position = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
subcarrierSpacing = 3;
#tdd-UL-DL-ConfigurationCommon
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
referenceSubcarrierSpacing = 3;
# pattern1
# dl_UL_TransmissionPeriodicity
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
dl_UL_TransmissionPeriodicity = 3;
nrofDownlinkSlots = 7;
nrofDownlinkSymbols = 6;
nrofUplinkSlots = 2;
nrofUplinkSymbols = 4;
ssPBCH_BlockPower = 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.18.99";
ipv6 = "192:168:30::17";
active = "yes";
preference = "ipv4";
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
t_dc_prep = 1000; /* unit: millisecond */
t_dc_overall = 2000; /* unit: millisecond */
target_enb_x2_ip_address = (
{ ipv4 = "192.168.18.199";
ipv6 = "192:168:30::17";
preference = "ipv4";
}
);
NETWORK_INTERFACES :
{
GNB_INTERFACE_NAME_FOR_S1_MME = "eth0";
GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.18.198/24";
GNB_INTERFACE_NAME_FOR_S1U = "eth0";
GNB_IPV4_ADDRESS_FOR_S1U = "192.168.18.198/24";
GNB_PORT_FOR_S1U = 2152; # Spec 2152
GNB_IPV4_ADDRESS_FOR_X2C = "192.168.18.198/24";
GNB_PORT_FOR_X2C = 36422; # Spec 36422
};
}
);
MACRLCs = (
{
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
pusch_TargetSNRx10 = 200;
pucch_TargetSNRx10 = 200;
}
);
prs_config = (
{
NumPRSResources = 8;
PRSResourceSetPeriod = [80, 2];
SymbolStart = [8,8,8,8,8,8,8,8];
NumPRSSymbols = [6,6,6,6,6,6,6,6];
NumRB = 64;
RBOffset = 0;
CombSize = 4;
REOffset = [0,0,0,0,0,0,0,0];
PRSResourceOffset = [0,10,20,30,40,50,60,70];
PRSResourceRepetition = 1;
PRSResourceTimeGap = 1;
NPRS_ID = [0,1,2,3,4,5,6,7];
MutingPattern1 = [];
MutingPattern2 = [];
MutingBitRepetition = 1;
}
);
L1s = (
{
num_cc = 1;
tr_n_preference = "local_mac";
ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0
}
);
RUs = (
{
local_rf = "yes"
nb_tx = 1;
nb_rx = 1;
att_tx = 0;
att_rx = 0;
bands = [7];
sl_ahead = 12;
max_pdschReferenceSignalPower = -27;
max_rxgain = 75;
eNB_instances = [0];
sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2,clock_source=gpsdo,time_source=gpsdo";
if_freq = 50000000L;
}
);
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";
}
);
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";
};
@@ -0,0 +1,334 @@
Active_gNBs = ( "gNB-OAI");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
gNBs =
(
{
////////// Identification parameters:
gNB_CU_ID = 0xe00;
# cell_type = "CELL_MACRO_GNB";
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;
snssaiList = (
{
sst = 1;
sd = 0x010203; // 0 false, else true
},
{
sst = 1;
sd = 0x112233; // 0 false, else true
}
);
});
nr_cellid = 12345678L
# tr_s_preference = "local_mac"
////////// Physical parameters:
#pusch_TargetSNRx10 = 200;
#pucch_TargetSNRx10 = 200;
ul_prbblacklist = "51,52,53,54"
min_rxtxtime = 6;
do_SRS = 0;
pdcch_ConfigSIB1 = (
{
controlResourceSetZero = 11;
searchSpaceZero = 0;
}
);
servingCellConfigCommon = (
{
#spCellConfigCommon
physCellId = 0;
# downlinkConfigCommon
#frequencyInfoDL
# this is 3301.68 MHz + 22*12*30e-3 MHz = 3309.6
#absoluteFrequencySSB = 620640;
# this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68
absoluteFrequencySSB = 621312;
# this is 3503.28 MHz + 22*12*30e-3 MHz = 3511.2
#absoluteFrequencySSB = 634080;
# this is 3600.48 MHz
#absoluteFrequencySSB = 640032;
#dl_frequencyBand = 78;
# this is 3301.68 MHz
#dl_absoluteFrequencyPointA = 620112;
# this is 3300.60 MHz
dl_absoluteFrequencyPointA = 620040;
# this is 3502.56 MHz
#dl_absoluteFrequencyPointA = 633552;
# this is 3600.48 MHz
#dl_absoluteFrequencyPointA = 640032;
#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;
#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 = 3;
#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,
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=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";
ipv6 = "192:168:30::17";
active = "yes";
preference = "ipv4";
}
);
NETWORK_INTERFACES :
{
GNB_INTERFACE_NAME_FOR_NG_AMF = "em1";
GNB_IPV4_ADDRESS_FOR_NG_AMF = "CI_GNB_IP_ADDR";
GNB_INTERFACE_NAME_FOR_NGU = "em1";
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;
ulsch_max_frame_inactivity = 1;
}
);
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;
#pucch0_dtx_threshold = 150;
}
);
RUs = (
{
local_rf = "yes"
nb_tx = 1
nb_rx = 1
att_tx = 0
att_rx = 0;
bands = [78];
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];
sf_extension = 0
sdr_addrs = "mgmt_addr=172.21.19.14,addr=192.168.10.2,second_addr=192.168.20.2,clock_source=internal,time_source=internal"
}
);
THREAD_STRUCT = (
{
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
parallel_config = "PARALLEL_SINGLE_THREAD";
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
worker_config = "WORKER_ENABLE";
}
);
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,290 @@
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 = 311; mnc = 480; mnc_length = 3;});
tr_s_preference = "local_mac"
////////// Physical parameters:
min_rxtxtime = 6;
servingCellConfigCommon = (
{
# spCellConfigCommon
physCellId = 0;
# downlinkConfigCommon
#frequencyInfoDL
# this is pointA + 23 PRBs@120kHz SCS (same as initial BWP)
absoluteFrequencySSB = 2071241;
dl_frequencyBand = 261;
# this is 27.900 GHz
dl_absoluteFrequencyPointA = 2070833;
#scs-SpecificCarrierList
dl_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
dl_subcarrierSpacing = 3;
dl_carrierBandwidth = 64;
#initialDownlinkBWP
#genericParameters
# this is RBstart=0,L=32 (275*(L-1))+RBstart
initialDLBWPlocationAndBandwidth = 8525;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialDLBWPsubcarrierSpacing = 3;
#pdcch-ConfigCommon
initialDLBWPcontrolResourceSetZero = 12;
initialDLBWPsearchSpaceZero = 0;
#uplinkConfigCommon
#frequencyInfoUL
ul_frequencyBand = 261;
#scs-SpecificCarrierList
ul_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
ul_subcarrierSpacing = 3;
ul_carrierBandwidth = 64;
pMax = 20;
#initialUplinkBWP
#genericParameters
initialULBWPlocationAndBandwidth = 8525;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialULBWPsubcarrierSpacing = 3;
#rach-ConfigCommon
#rach-ConfigGeneric
prach_ConfigurationIndex = 52;
#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 = 7;
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
#0=oneeighth,1=onefourth,2=half,3=one,4=two,5=four,6=eight,7=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4;
#oneHalf (0..15) 4,8,12,16,...60,64
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 7;
#ra_ContentionResolutionTimer
#(0..7) 8,16,24,32,40,48,56,64
ra_ContentionResolutionTimer = 7;
rsrp_ThresholdSSB = 19;
#prach-RootSequenceIndex_PR
#1 = 839, 2 = 139
prach_RootSequenceIndex_PR = 2;
prach_RootSequenceIndex = 1;
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
#
msg1_SubcarrierSpacing = 3,
# restrictedSetConfig
# 0=unrestricted, 1=restricted type A, 2=restricted type B
restrictedSetConfig = 0,
msg3_DeltaPreamble = 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 = 3;
ssb_PositionsInBurst_Bitmap = 0x0002000200020002L;
# ssb_periodicityServingCell
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
ssb_periodicityServingCell = 1;
# dmrs_TypeA_position
# 0 = pos2, 1 = pos3
dmrs_TypeA_Position = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
subcarrierSpacing = 3;
#tdd-UL-DL-ConfigurationCommon
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
referenceSubcarrierSpacing = 3;
# pattern1
# dl_UL_TransmissionPeriodicity
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
dl_UL_TransmissionPeriodicity = 3;
nrofDownlinkSlots = 7;
nrofDownlinkSymbols = 6;
nrofUplinkSlots = 2;
nrofUplinkSymbols = 4;
ssPBCH_BlockPower = 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.18.99";
ipv6 = "192:168:30::17";
active = "yes";
preference = "ipv4";
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
t_dc_prep = 1000; /* unit: millisecond */
t_dc_overall = 2000; /* unit: millisecond */
target_enb_x2_ip_address = (
{ ipv4 = "192.168.18.199";
ipv6 = "192:168:30::17";
preference = "ipv4";
}
);
NETWORK_INTERFACES :
{
GNB_INTERFACE_NAME_FOR_S1_MME = "eth0";
GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.18.198/24";
GNB_INTERFACE_NAME_FOR_S1U = "eth0";
GNB_IPV4_ADDRESS_FOR_S1U = "192.168.18.198/24";
GNB_PORT_FOR_S1U = 2152; # Spec 2152
GNB_IPV4_ADDRESS_FOR_X2C = "192.168.18.198/24";
GNB_PORT_FOR_X2C = 36422; # Spec 36422
};
}
);
MACRLCs = (
{
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
pusch_TargetSNRx10 = 200;
pucch_TargetSNRx10 = 200;
}
);
prs_config = (
{
NumPRSResources = 8;
PRSResourceSetPeriod = [80, 2];
SymbolStart = [8,8,8,8,8,8,8,8];
NumPRSSymbols = [6,6,6,6,6,6,6,6];
NumRB = 64;
RBOffset = 0;
CombSize = 4;
REOffset = [1,1,1,1,1,1,1,1];
PRSResourceOffset = [0,10,20,30,40,50,60,70];
PRSResourceRepetition = 1;
PRSResourceTimeGap = 1;
NPRS_ID = [10,11,12,13,14,15,16,17];
MutingPattern1 = [];
MutingPattern2 = [];
MutingBitRepetition = 1;
}
);
L1s = (
{
num_cc = 1;
tr_n_preference = "local_mac";
ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0
}
);
RUs = (
{
local_rf = "yes"
nb_tx = 1;
nb_rx = 1;
att_tx = 0;
att_rx = 0;
bands = [7];
sl_ahead = 12;
max_pdschReferenceSignalPower = -27;
max_rxgain = 75;
eNB_instances = [0];
sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2,clock_source=gpsdo,time_source=gpsdo";
if_freq = 50000000L;
}
);
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";
}
);
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";
};
@@ -0,0 +1,334 @@
Active_gNBs = ( "gNB-OAI");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
gNBs =
(
{
////////// Identification parameters:
gNB_CU_ID = 0xe00;
# cell_type = "CELL_MACRO_GNB";
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;
snssaiList = (
{
sst = 1;
sd = 0x010203; // 0 false, else true
},
{
sst = 1;
sd = 0x112233; // 0 false, else true
}
);
});
nr_cellid = 12345678L
# tr_s_preference = "local_mac"
////////// Physical parameters:
#pusch_TargetSNRx10 = 200;
#pucch_TargetSNRx10 = 200;
ul_prbblacklist = "51,52,53,54"
min_rxtxtime = 6;
do_SRS = 0;
pdcch_ConfigSIB1 = (
{
controlResourceSetZero = 11;
searchSpaceZero = 0;
}
);
servingCellConfigCommon = (
{
#spCellConfigCommon
physCellId = 0;
# downlinkConfigCommon
#frequencyInfoDL
# this is 3301.68 MHz + 22*12*30e-3 MHz = 3309.6
#absoluteFrequencySSB = 620640;
# this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68
absoluteFrequencySSB = 621312;
# this is 3503.28 MHz + 22*12*30e-3 MHz = 3511.2
#absoluteFrequencySSB = 634080;
# this is 3600.48 MHz
#absoluteFrequencySSB = 640032;
#dl_frequencyBand = 78;
# this is 3301.68 MHz
#dl_absoluteFrequencyPointA = 620112;
# this is 3300.60 MHz
dl_absoluteFrequencyPointA = 620040;
# this is 3502.56 MHz
#dl_absoluteFrequencyPointA = 633552;
# this is 3600.48 MHz
#dl_absoluteFrequencyPointA = 640032;
#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;
#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 = 3;
#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,
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 = 2;
# 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";
ipv6 = "192:168:30::17";
active = "yes";
preference = "ipv4";
}
);
NETWORK_INTERFACES :
{
GNB_INTERFACE_NAME_FOR_NG_AMF = "em1";
GNB_IPV4_ADDRESS_FOR_NG_AMF = "CI_GNB_IP_ADDR";
GNB_INTERFACE_NAME_FOR_NGU = "em1";
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;
ulsch_max_frame_inactivity = 1;
}
);
prs_config = (
{
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;
}
);
L1s = (
{
num_cc = 1;
tr_n_preference = "local_mac";
prach_dtx_threshold = 120;
#pucch0_dtx_threshold = 150;
}
);
RUs = (
{
local_rf = "yes"
nb_tx = 1
nb_rx = 1
att_tx = 0
att_rx = 0;
bands = [78];
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];
sf_extension = 0
sdr_addrs = "mgmt_addr=172.21.19.14,addr=192.168.10.2,second_addr=192.168.20.2,clock_source=internal,time_source=internal"
}
);
THREAD_STRUCT = (
{
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
parallel_config = "PARALLEL_SINGLE_THREAD";
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
worker_config = "WORKER_ENABLE";
}
);
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;
}
);
}
);
@@ -0,0 +1,47 @@
PRSs =
(
{
Active_gNBs = 1;
prs_config0 = (
{
gNB_id = 0;
NumPRSResources = 8;
PRSResourceSetPeriod = [80, 2];
SymbolStart = [8,8,8,8,8,8,8,8];
NumPRSSymbols = [6,6,6,6,6,6,6,6];
NumRB = 64;
RBOffset = 0;
CombSize = 4;
REOffset = [0,0,0,0,0,0,0,0];
PRSResourceOffset = [0,10,20,30,40,50,60,70];
PRSResourceRepetition = 1;
PRSResourceTimeGap = 1;
NPRS_ID = [0,1,2,3,4,5,6,7];
MutingPattern1 = [];
MutingPattern2 = [];
MutingBitRepetition = 1;
}
);
prs_config1 = (
{
gNB_id = 1;
NumPRSResources = 8;
PRSResourceSetPeriod = [80, 2];
SymbolStart = [8,8,8,8,8,8,8,8];
NumPRSSymbols = [6,6,6,6,6,6,6,6];
NumRB = 64;
RBOffset = 0;
CombSize = 4;
REOffset = [1,1,1,1,1,1,1,1];
PRSResourceOffset = [0,10,20,30,40,50,60,70];
PRSResourceRepetition = 1;
PRSResourceTimeGap = 1;
NPRS_ID = [10,11,12,13,14,15,16,17];
MutingPattern1 = [];
MutingPattern2 = [];
MutingBitRepetition = 1;
}
);
}
);