mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-14 05:00:31 +00:00
Compare commits
341 Commits
nvidia-tes
...
sl-eurecom
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
439bcdf9f8 | ||
|
|
4d21f2fd3e | ||
|
|
bcac6783da | ||
|
|
f35a75baa2 | ||
|
|
ef201f1419 | ||
|
|
eb38ab0a56 | ||
|
|
26700cbb18 | ||
|
|
bbaf90c64d | ||
|
|
5c0497c92a | ||
|
|
13c035ef77 | ||
|
|
9c9e50391e | ||
|
|
801886c8d9 | ||
|
|
a957cc7b59 | ||
|
|
6eba4d2abe | ||
|
|
82af5bb27b | ||
|
|
7d0119efa6 | ||
|
|
c67c11b380 | ||
|
|
92c5b04cdb | ||
|
|
ad6e003ad3 | ||
|
|
0a1d4ba709 | ||
|
|
9ae927b862 | ||
|
|
fd54152a53 | ||
|
|
d01693b901 | ||
|
|
cf65d02fd4 | ||
|
|
3cc086821f | ||
|
|
a8b4080383 | ||
|
|
a32aba4ec5 | ||
|
|
41552c0ea8 | ||
|
|
762e68c327 | ||
|
|
737155131b | ||
|
|
75cf67dcf2 | ||
|
|
ad2c7372e0 | ||
|
|
65f3dd803f | ||
|
|
f1ee81c22e | ||
|
|
56898c81d3 | ||
|
|
9b37a05a71 | ||
|
|
b960ede044 | ||
|
|
a60aa4250a | ||
|
|
6bdcac9e0b | ||
|
|
50892fa07f | ||
|
|
6cb94c69bd | ||
|
|
f44aa9b86e | ||
|
|
336db01213 | ||
|
|
a6a6fe043e | ||
|
|
41fc98eda5 | ||
|
|
230ebaea70 | ||
|
|
87348885b4 | ||
|
|
9b60e7f4ec | ||
|
|
ea14ae4a15 | ||
|
|
8c8408ba8f | ||
|
|
c8ec792c3e | ||
|
|
c9486cb4f8 | ||
|
|
30cb74b96c | ||
|
|
c608abe8a1 | ||
|
|
5831ceada3 | ||
|
|
174e39b417 | ||
|
|
6ee1ed99a0 | ||
|
|
e766185363 | ||
|
|
7dbe690dcf | ||
|
|
b7e443a2ed | ||
|
|
95c143657f | ||
|
|
98ea7cf8a8 | ||
|
|
817aeb6e1b | ||
|
|
aaccfe4beb | ||
|
|
3cdd8e2221 | ||
|
|
2b6e7e105e | ||
|
|
39fb255189 | ||
|
|
e9dd1d9bf0 | ||
|
|
3bf811e903 | ||
|
|
3782926ae5 | ||
|
|
6ced256931 | ||
|
|
e5f6ec76ec | ||
|
|
c3b314ab67 | ||
|
|
16bd6d4421 | ||
|
|
6e00505f98 | ||
|
|
bb792807ab | ||
|
|
852d0dc2b9 | ||
|
|
1f47719f95 | ||
|
|
383a573665 | ||
|
|
a376968ba4 | ||
|
|
7f7c343856 | ||
|
|
98ae1a296a | ||
|
|
9bab4005fe | ||
|
|
e2746c9e62 | ||
|
|
20ae13fa41 | ||
|
|
3b520e933b | ||
|
|
e214756682 | ||
|
|
fb5e590d44 | ||
|
|
bde50f2e63 | ||
|
|
55042e7b9f | ||
|
|
2fd7150702 | ||
|
|
74adc9eeb5 | ||
|
|
419eb6c81f | ||
|
|
6873c38471 | ||
|
|
70d1e6e52c | ||
|
|
8216cbf79a | ||
|
|
bd210f9961 | ||
|
|
c23170f895 | ||
|
|
ecc78c1bea | ||
|
|
aa57104123 | ||
|
|
d09522d616 | ||
|
|
a522b2dcb5 | ||
|
|
c53d66f140 | ||
|
|
c8b84b8e50 | ||
|
|
47a94020cd | ||
|
|
95b9990ef5 | ||
|
|
16f75be9fd | ||
|
|
aed1eb1841 | ||
|
|
f5511fec98 | ||
|
|
5db24ade57 | ||
|
|
171ba6f765 | ||
|
|
d6dc49bc4a | ||
|
|
302b64cc07 | ||
|
|
19d1eb25ba | ||
|
|
0bcbc7401c | ||
|
|
d56d68332e | ||
|
|
4600b1bba6 | ||
|
|
c282e8700a | ||
|
|
5314c750e8 | ||
|
|
6e708111d9 | ||
|
|
fd2ac5a881 | ||
|
|
8fdc275c98 | ||
|
|
ae692d25ac | ||
|
|
1d3b40a602 | ||
|
|
e4508b1d01 | ||
|
|
a2184d2430 | ||
|
|
3645c75ba8 | ||
|
|
88032eaa6f | ||
|
|
eb7214ed1e | ||
|
|
9ebfc7df80 | ||
|
|
c5dd477299 | ||
|
|
de8bde2eb1 | ||
|
|
041a74ad55 | ||
|
|
dd4c1851f3 | ||
|
|
665143e3f6 | ||
|
|
1a904623e1 | ||
|
|
c9e48b8ce9 | ||
|
|
2abf30ad6e | ||
|
|
d37bf06d39 | ||
|
|
eca4d6a572 | ||
|
|
b4b73f2dea | ||
|
|
bc316b1cec | ||
|
|
0ff70cc496 | ||
|
|
816bfec661 | ||
|
|
e8afaa8cca | ||
|
|
f94fe2ac80 | ||
|
|
b1d76e157c | ||
|
|
eea92750b0 | ||
|
|
3743e20f87 | ||
|
|
497858ef37 | ||
|
|
c56f246dd1 | ||
|
|
0fae27e94c | ||
|
|
e12bf1500d | ||
|
|
ba90296301 | ||
|
|
9530eefa24 | ||
|
|
ea4ed2abd8 | ||
|
|
aab3fd92f2 | ||
|
|
31985289a2 | ||
|
|
2c686dd805 | ||
|
|
368a599dc7 | ||
|
|
8ab77553ad | ||
|
|
0788a62aaf | ||
|
|
865df9eea6 | ||
|
|
4aa058efd8 | ||
|
|
0aa31e7af2 | ||
|
|
4c065efd22 | ||
|
|
2e5c6f7d8d | ||
|
|
bb3fb6cbd0 | ||
|
|
b6f04e3ccf | ||
|
|
92340ebd77 | ||
|
|
8c9588739f | ||
|
|
42112e849d | ||
|
|
c40d0d1cb1 | ||
|
|
a1ec6c9ba2 | ||
|
|
bcc632dbdd | ||
|
|
a7f3cd98ec | ||
|
|
16f63c749d | ||
|
|
7e8d791010 | ||
|
|
7ed097874a | ||
|
|
06bccb4087 | ||
|
|
f41b149a58 | ||
|
|
5f829ddb35 | ||
|
|
59a69b5020 | ||
|
|
0845154ef8 | ||
|
|
34d2c4d917 | ||
|
|
9c6c8366af | ||
|
|
d9ede841a1 | ||
|
|
47dc503ca6 | ||
|
|
2516b5b3f1 | ||
|
|
e6e925f9ab | ||
|
|
105f2b57ef | ||
|
|
848e380cd0 | ||
|
|
1cacd66352 | ||
|
|
286ef21839 | ||
|
|
e88f0f5539 | ||
|
|
b1d830adc2 | ||
|
|
36a29714ff | ||
|
|
9fd148dedd | ||
|
|
378e6f5643 | ||
|
|
15f8f5aeea | ||
|
|
f776b88d7f | ||
|
|
ea9289b2de | ||
|
|
30ce40cf03 | ||
|
|
23300df806 | ||
|
|
d9acb85bfa | ||
|
|
ec7b44e6dd | ||
|
|
076c83b6f2 | ||
|
|
616f759661 | ||
|
|
61e62abb7f | ||
|
|
281dc32c26 | ||
|
|
bb35caebed | ||
|
|
1ff86924ff | ||
|
|
e13e26759e | ||
|
|
9588e10de0 | ||
|
|
885d5cd426 | ||
|
|
6536425c4b | ||
|
|
c7e08dffbe | ||
|
|
d2475e0dd6 | ||
|
|
c584baf9e1 | ||
|
|
6fcda3dcc0 | ||
|
|
3e81184deb | ||
|
|
4e2b8ddb92 | ||
|
|
e8ca12049a | ||
|
|
e9ff59611d | ||
|
|
fb6baf3f76 | ||
|
|
18e9694f31 | ||
|
|
183e029c8c | ||
|
|
da97a8f016 | ||
|
|
1a470d5af6 | ||
|
|
c4250dcd2b | ||
|
|
4c4a667fd6 | ||
|
|
da6f3251f3 | ||
|
|
c534570eec | ||
|
|
9642a70e6d | ||
|
|
1c84699e00 | ||
|
|
9d8db83ebd | ||
|
|
9ceb3ddf93 | ||
|
|
289991b0fe | ||
|
|
38a43f3be6 | ||
|
|
6fc72eae0f | ||
|
|
14420f24cb | ||
|
|
53aa746075 | ||
|
|
4e10e4fa2c | ||
|
|
9879c13cd4 | ||
|
|
63454cebf8 | ||
|
|
813b600305 | ||
|
|
9f9dadf621 | ||
|
|
bb13bfa195 | ||
|
|
ee7244ca05 | ||
|
|
05604174e0 | ||
|
|
cbcd09cbca | ||
|
|
4af8be50bd | ||
|
|
ef9f804da7 | ||
|
|
a465e39bb9 | ||
|
|
3370570ecd | ||
|
|
29b74e7410 | ||
|
|
3fa03965a1 | ||
|
|
d7b1a78e71 | ||
|
|
a2e75e10d3 | ||
|
|
714629c26f | ||
|
|
9e686e448d | ||
|
|
5a88bb670a | ||
|
|
b4a314b64e | ||
|
|
6be609a59f | ||
|
|
69c357655e | ||
|
|
45dd2a7fb0 | ||
|
|
b5dd8de98f | ||
|
|
a42a4d1a06 | ||
|
|
3c485239ba | ||
|
|
14b972e878 | ||
|
|
aff9391806 | ||
|
|
c734cfab93 | ||
|
|
3dd8395c8f | ||
|
|
99a750d672 | ||
|
|
82dfb5c4ec | ||
|
|
7fd180f30b | ||
|
|
f52f258eec | ||
|
|
fdad2f7d17 | ||
|
|
1245c05385 | ||
|
|
e534761719 | ||
|
|
2976628409 | ||
|
|
34aede6ee5 | ||
|
|
d2bbbb16ad | ||
|
|
7e83f75d21 | ||
|
|
c4706eda69 | ||
|
|
28f2129d3e | ||
|
|
238a7837cf | ||
|
|
e474090459 | ||
|
|
6f5205ec1c | ||
|
|
f5250c1ec4 | ||
|
|
156b806abb | ||
|
|
d4e030cc3b | ||
|
|
cb17a2530c | ||
|
|
907130d999 | ||
|
|
d201d89c94 | ||
|
|
5cc6d9e5c3 | ||
|
|
1a815f7e15 | ||
|
|
05cb48d29c | ||
|
|
911bd2be5d | ||
|
|
5ea68eb132 | ||
|
|
94188666ce | ||
|
|
a6d86ea8c9 | ||
|
|
d3702751ec | ||
|
|
63b3d8a92f | ||
|
|
597c897977 | ||
|
|
d1bbbb5dd3 | ||
|
|
18853ab6cc | ||
|
|
9cc948635c | ||
|
|
93d4a07932 | ||
|
|
6bfe76b086 | ||
|
|
e568b2c85a | ||
|
|
435b636d89 | ||
|
|
84504a38a0 | ||
|
|
4bd3007565 | ||
|
|
dad4240016 | ||
|
|
2cda03b016 | ||
|
|
198c319788 | ||
|
|
18d720f377 | ||
|
|
ba6a8554a3 | ||
|
|
ffda9c758a | ||
|
|
60a7eb326c | ||
|
|
6a5a9f18bf | ||
|
|
4bf5166aed | ||
|
|
d4e30b972b | ||
|
|
858a13119b | ||
|
|
5b16b58496 | ||
|
|
0588003034 | ||
|
|
b8d9da2e81 | ||
|
|
8199a1e093 | ||
|
|
7efe5880a1 | ||
|
|
b9caf3ecc4 | ||
|
|
4ca508228f | ||
|
|
9ecd473a41 | ||
|
|
f32c759ecf | ||
|
|
88b6cdd209 | ||
|
|
8bb2f3991b | ||
|
|
4d369a6993 | ||
|
|
70f586cb3c | ||
|
|
745cc733ea | ||
|
|
ee7aacf2ca | ||
|
|
fef6303cc9 |
@@ -163,8 +163,8 @@ set(CMAKE_CXX_FLAGS
|
||||
|
||||
add_boolean_option(SANITIZE_ADDRESS False "enable the address sanitizer (ASan)" ON)
|
||||
if (SANITIZE_ADDRESS)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer -fno-common")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer -fno-common")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fstack-check -fno-omit-frame-pointer -fno-common")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fstack-check -fno-omit-frame-pointer -fno-common")
|
||||
# There seems to be some incompatibility with pthread_create and the RT scheduler, which
|
||||
# results in pthread_create hanging.
|
||||
#
|
||||
@@ -689,6 +689,7 @@ target_link_libraries(SCHED_UE_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
|
||||
|
||||
set(SCHED_SRC_NR_UE
|
||||
${OPENAIR1_DIR}/SCHED_NR_UE/phy_procedures_nr_ue.c
|
||||
${OPENAIR1_DIR}/SCHED_NR_UE/phy_procedures_nr_ue_sl.c
|
||||
${OPENAIR1_DIR}/SCHED_NR_UE/fapi_nr_ue_l1.c
|
||||
${OPENAIR1_DIR}/SCHED_NR_UE/phy_frame_config_nr_ue.c
|
||||
${OPENAIR1_DIR}/SCHED_NR_UE/harq_nr.c
|
||||
@@ -1060,8 +1061,20 @@ set(PHY_SRC_UE
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/sss_nr.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/cic_filter_nr.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_pbch.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_psbch_rx.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_psbch_tx.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_psfch_tx.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_pscch_tx.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ue_pucch_rx.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dci.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dci_tools.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
|
||||
@@ -1081,11 +1094,14 @@ set(PHY_SRC_UE
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/dmrs_nr.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/ptrs_nr.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold_ue.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gen_mod_table.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/nr_adjust_gain.c
|
||||
${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
|
||||
${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_measurements_gNB.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/file_output.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c
|
||||
# ${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c
|
||||
@@ -1120,8 +1136,8 @@ target_link_libraries(PHY_COMMON PRIVATE asn1_lte_rrc_hdrs)
|
||||
add_library(PHY ${PHY_SRC})
|
||||
target_link_libraries(PHY PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
|
||||
|
||||
pkg_check_modules(blas REQUIRED blas)
|
||||
pkg_check_modules(lapacke REQUIRED lapacke)
|
||||
#pkg_check_modules(blas REQUIRED blas)
|
||||
#pkg_check_modules(lapacke REQUIRED lapacke)
|
||||
|
||||
add_library(PHY_UE ${PHY_SRC_UE})
|
||||
target_link_libraries(PHY_UE PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
|
||||
@@ -1352,7 +1368,7 @@ set (MAC_NR_SRC
|
||||
|
||||
|
||||
set (MAC_SRC_UE
|
||||
${PHY_INTERFACE_DIR}/phy_stub_UE.c
|
||||
# ${PHY_INTERFACE_DIR}/phy_stub_UE.c
|
||||
${PHY_INTERFACE_DIR}/queue_t.c
|
||||
${MAC_DIR}/main_ue.c
|
||||
${MAC_DIR}/ue_procedures.c
|
||||
@@ -1366,13 +1382,17 @@ set (MAC_NR_SRC_UE
|
||||
${NR_UE_PHY_INTERFACE_DIR}/NR_IF_Module.c
|
||||
${NR_UE_PHY_INTERFACE_DIR}/NR_Packet_Drop.c
|
||||
${NR_UE_MAC_DIR}/config_ue.c
|
||||
${NR_UE_MAC_DIR}/config_ue_sl.c
|
||||
${NR_UE_MAC_DIR}/mac_vars.c
|
||||
${NR_UE_MAC_DIR}/main_ue_nr.c
|
||||
${NR_UE_MAC_DIR}/nr_ue_procedures.c
|
||||
${NR_UE_MAC_DIR}/nr_ue_procedures_sl.c
|
||||
${NR_UE_MAC_DIR}/nr_ue_scheduler.c
|
||||
${NR_UE_MAC_DIR}/nr_ue_dci_configuration.c
|
||||
${NR_UE_MAC_DIR}/nr_ra_procedures.c
|
||||
${NR_UE_MAC_DIR}/nr_ue_power_procedures.c
|
||||
${NR_UE_MAC_DIR}/nr_ue_sci_slsch.c
|
||||
${NR_UE_MAC_DIR}/nr_slsch_scheduler.c
|
||||
)
|
||||
|
||||
set (ENB_APP_SRC
|
||||
@@ -1876,8 +1896,6 @@ set (SIMUSRC
|
||||
)
|
||||
add_library(SIMU STATIC ${SIMUSRC} )
|
||||
target_include_directories(SIMU PUBLIC ${OPENAIR1_DIR}/SIMULATION/TOOLS ${OPENAIR1_DIR}/SIMULATION/RF)
|
||||
target_link_libraries(SIMU PRIVATE ${blas_LIBRARIES} ${cblas_LIBRARIES} ${lapacke_LIBRARIES})
|
||||
target_include_directories(SIMU PRIVATE ${blas_INCLUDE_DIRS} ${lapacke_INCLUDE_DIRS})
|
||||
|
||||
# Qt-based scope
|
||||
add_boolean_option(ENABLE_NRQTSCOPE OFF "Build the Qt-Scope" OFF)
|
||||
@@ -2225,6 +2243,24 @@ target_link_libraries(nr_pbchsim PRIVATE
|
||||
)
|
||||
target_link_libraries(nr_pbchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
|
||||
|
||||
add_executable(nr_psbchsim
|
||||
${OPENAIR1_DIR}/SIMULATION/NR_PHY/psbchsim.c
|
||||
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
|
||||
${OPENAIR_DIR}/common/utils/nr/nr_common.c
|
||||
${OPENAIR_DIR}/executables/softmodem-common.c
|
||||
${OPENAIR2_DIR}/RRC/NAS/nas_config.c
|
||||
${NR_UE_RRC_DIR}/rrc_nsa.c
|
||||
${NFAPI_USER_DIR}/nfapi.c
|
||||
${NFAPI_USER_DIR}/gnb_ind_vars.c
|
||||
${PHY_INTERFACE_DIR}/queue_t.c
|
||||
${T_SOURCE}
|
||||
${SHLIB_LOADER_SOURCES}
|
||||
)
|
||||
target_link_libraries(nr_psbchsim PRIVATE
|
||||
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group
|
||||
m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl shlib_loader
|
||||
)
|
||||
target_link_libraries(nr_psbchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
|
||||
|
||||
#PUCCH ---> Prashanth
|
||||
add_executable(nr_pucchsim
|
||||
|
||||
376
README.md
376
README.md
@@ -1,74 +1,330 @@
|
||||
<h1 align="center">
|
||||
<a href="https://openairinterface.org/"><img src="https://openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png" alt="OAI" width="550"></a>
|
||||
</h1>
|
||||
# OAI-SL-MultiUE-Broker
|
||||
|
||||
<p align="center">
|
||||
<a href="https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-OAI--Public--V1.1-blue" alt="License"></a>
|
||||
<a href="https://releases.ubuntu.com/18.04/"><img src="https://img.shields.io/badge/OS-Ubuntu18-Green" alt="Supported OS Ubuntu 18"></a>
|
||||
<a href="https://releases.ubuntu.com/20.04/"><img src="https://img.shields.io/badge/OS-Ubuntu20-Green" alt="Supported OS Ubuntu 20"></a>
|
||||
<a href="https://releases.ubuntu.com/22.04/"><img src="https://img.shields.io/badge/OS-Ubuntu22-Green" alt="Supported OS Ubuntu 22"></a>
|
||||
<a href="https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux"><img src="https://img.shields.io/badge/OS-RHEL8-Green" alt="Supported OS RHEL8"></a>
|
||||
<a href="https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux"><img src="https://img.shields.io/badge/OS-RHEL9-Green" alt="Supported OS RELH9"></a>
|
||||
<a href="https://getfedora.org/en/workstation/"><img src="https://img.shields.io/badge/OS-Fedore37-Green" alt="Supported OS Fedora 37"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://jenkins-oai.eurecom.fr/job/RAN-Container-Parent/"><img src="https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fjenkins-oai.eurecom.fr%2Fjob%2FRAN-Container-Parent%2F&label=build%20Images"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://hub.docker.com/r/oaisoftwarealliance/oai-gnb"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/oaisoftwarealliance/oai-gnb?label=gNB%20docker%20pulls"></a>
|
||||
<a href="https://hub.docker.com/r/oaisoftwarealliance/oai-nr-ue"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/oaisoftwarealliance/oai-nr-ue?label=NR-UE%20docker%20pulls"></a>
|
||||
<a href="https://hub.docker.com/r/oaisoftwarealliance/oai-enb"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/oaisoftwarealliance/oai-enb?label=eNB%20docker%20pulls"></a>
|
||||
<a href="https://hub.docker.com/r/oaisoftwarealliance/oai-lte-ue"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/oaisoftwarealliance/oai-lte-ue?label=LTE-UE%20docker%20pulls"></a>
|
||||
</p>
|
||||
## RFSim Broker based Multiple UEs Test
|
||||
|
||||
# OpenAirInterface License #
|
||||
This part test is based on ‘sl-eurecom4’ branch on openairinterface5g.
|
||||
(https://gitlab.eurecom.fr/oai/openairinterface5g.git)
|
||||
|
||||
* [OAI License Model](http://www.openairinterface.org/?page_id=101)
|
||||
* [OAI License v1.1 on our website](http://www.openairinterface.org/?page_id=698)
|
||||
|
||||
It is distributed under **OAI Public License V1.1**.
|
||||
|
||||
The license information is distributed under [LICENSE](LICENSE) file in the same directory.
|
||||
|
||||
Please see [NOTICE](NOTICE.md) file for third party software that is included in the sources.
|
||||
|
||||
# Where to Start #
|
||||
|
||||
* [General overview of documentation](./doc/README.md)
|
||||
* [The implemented features](./doc/FEATURE_SET.md)
|
||||
* [How to build](./doc/BUILD.md)
|
||||
* [How to run the modems](./doc/RUNMODEM.md)
|
||||
|
||||
Not all information is available in a central place, and information for
|
||||
specific sub-systems might be available in the corresponding sub-directories.
|
||||
To find all READMEs, this command might be handy:
|
||||
## To start
|
||||
|
||||
First go to the correct repository :
|
||||
```
|
||||
find . -iname "readme*"
|
||||
cd openairinterface5g/cmake_targets
|
||||
```
|
||||
To install zeroMQ :
|
||||
```
|
||||
apt-get install libzmq3-dev
|
||||
```
|
||||
Then start compilation :
|
||||
```
|
||||
sudo ./build_oai --nrUE -w SIMU --cmake-opt -DENABLE_T_TRACER=OFF
|
||||
```
|
||||
Or, to start a clean start compilation, do the clean up first then compile :
|
||||
```
|
||||
sudo ./build_oai -c -C
|
||||
|
||||
sudo ./build_oai -I --cmake-opt -DENABLE_T_TRACER=OFF
|
||||
```
|
||||
Now we need to create three UEs through namespaces:
|
||||
```
|
||||
cd openairinterface5g/cmake_targets
|
||||
sudo ./multi-ue.sh -c1 -c2 -c3
|
||||
```
|
||||
* It is likely the new system would face the ASN.1 error, which is due to the wrong version of ASN.1. To fix it, please do the following:
|
||||
|
||||
* Remove the current wrong version :
|
||||
```
|
||||
sudo rm -rf /opt/asn1c
|
||||
sudo rm -rf /tmp/asn1c
|
||||
```
|
||||
* Clone and checkout the exact same commit:
|
||||
```
|
||||
cd /tmp
|
||||
git clone https://github.com/mouse07410/asn1c.git
|
||||
cd asn1c
|
||||
git checkout 657f5790
|
||||
```
|
||||
* Build and install the correct version :
|
||||
```
|
||||
git submodule update --init --recursive
|
||||
autoreconf -iv
|
||||
./configure --prefix=/opt/asn1c
|
||||
make -j$(nproc)
|
||||
sudo make install
|
||||
```
|
||||
* Then recompile. Do remember to delete the wrong /ran_build files :
|
||||
```
|
||||
cd ~/OAI-SL-Broker/openairinterface5g/cmake_targets
|
||||
rm -rf ran_build
|
||||
sudo ./build_oai --nrUE -w SIMU --cmake-opt -DENABLE_T_TRACER=OFF
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
## Start RFSim for Multiple UEs through Broker
|
||||
|
||||
|
||||
### Launch Broker (outside namespace):
|
||||
```
|
||||
cd ran_build/build/
|
||||
./broker
|
||||
```
|
||||
|
||||
# RAN repository structure #
|
||||
### Launch SYNC-REF (namespace 1):
|
||||
```
|
||||
sudo ./multi-ue.sh -o1
|
||||
cd ran_build/build/
|
||||
sudo RFSIMULATOR=server ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf --sl-mode 2 --sa --sync-ref --brokerip 10.201.1.100
|
||||
```
|
||||
|
||||
The OpenAirInterface (OAI) software is composed of the following parts:
|
||||
### Launch UE2 (namespace 2):
|
||||
```
|
||||
sudo ./multi-ue.sh -o2
|
||||
cd ran_build/build/
|
||||
sudo ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue1.conf --sl-mode 2 --sa --brokerip 10.202.1.100 --device_id 1 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
|
||||
```
|
||||
|
||||
### Launch UE3 (namespace 3):
|
||||
```
|
||||
sudo ./multi-ue.sh -o3
|
||||
cd ran_build/build/
|
||||
sudo ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue2.conf --sl-mode 2 --sa --brokerip 10.203.1.100 --device_id 2 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
|
||||
```
|
||||
|
||||
Optional : You can now quickly check the connection to sync-ref from two UEs :
|
||||
```
|
||||
ping -I oaitun_ue2 10.0.0.1
|
||||
ping -I oaitun_ue3 10.0.0.1
|
||||
```
|
||||
|
||||
Note: when restart the simulation, you might need to kill everything first by the following command :
|
||||
```
|
||||
sudo pkill -f nr-uesoftmodem
|
||||
sudo pkill -f broker
|
||||
sudo pkill -f rfsimulator
|
||||
```
|
||||
|
||||
## Monitor route with Babel and Wireshark
|
||||
You might need to first install Babel onto the local machine
|
||||
|
||||
```
|
||||
openairinterface5g
|
||||
├── charts
|
||||
├── ci-scripts : Meta-scripts used by the OSA CI process. Contains also configuration files used day-to-day by CI.
|
||||
├── CMakeLists.txt : Top-level CMakeLists.txt for building
|
||||
├── cmake_targets : Build utilities to compile (simulation, emulation and real-time platforms), and generated build files.
|
||||
├── common : Some common OAI utilities, some other tools can be found at openair2/UTILS.
|
||||
├── doc : Documentation
|
||||
├── docker : Dockerfiles to build for Ubuntu and RHEL
|
||||
├── executables : Top-level executable source files (gNB, eNB, ...)
|
||||
├── maketags : Script to generate emacs tags.
|
||||
├── nfapi : (n)FAPI code for MAC-PHY interface
|
||||
├── openair1 : 3GPP LTE Rel-10/12 PHY layer / 3GPP NR Rel-15 layer. A local Readme file provides more details.
|
||||
├── openair2 : 3GPP LTE Rel-10 RLC/MAC/PDCP/RRC/X2AP + LTE Rel-14 M2AP implementation. Also 3GPP NR Rel-15 RLC/MAC/PDCP/RRC/X2AP.
|
||||
├── openair3 : 3GPP LTE Rel10 for S1AP, NAS GTPV1-U for both ENB and UE.
|
||||
├── openshift : OpenShift helm charts for some deployment options of OAI
|
||||
├── radio : Drivers for various radios such as USRP, AW2S, RFsim, ...
|
||||
└── targets : Some configuration files; only historical relevance, and might be deleted in the future
|
||||
sudo apt update
|
||||
sudo apt install babeld
|
||||
```
|
||||
|
||||
### Launch SYNC-REF (namespace 1):
|
||||
First go into the correct namespace :
|
||||
```
|
||||
sudo ./multi-ue.sh -o1
|
||||
```
|
||||
|
||||
In order to have a readable address at the logside, we'll hardcode the IP address through following command, so sync-ref will be translate as 'fe80::1/64'
|
||||
```
|
||||
sudo ip netns exec ue1 ip -6 addr add fe80::1/64 dev oaitun_ue1 nodad
|
||||
```
|
||||
Then launch Babel on sync-ref :
|
||||
```
|
||||
ip netns exec ue1 bash -lc '
|
||||
set -e
|
||||
cat > /tmp/babeld-ue1.conf <<EOF
|
||||
interface oaitun_ue1
|
||||
redistribute local deny
|
||||
pid-file /tmp/babeld-ue1.pid
|
||||
EOF
|
||||
babeld -d 1 -c /tmp/babeld-ue1.conf
|
||||
'
|
||||
```
|
||||
For now, as no other UE is connected, sync-ref will simply print its local id.
|
||||
|
||||
### Launch UE2 (namespace 2):
|
||||
First go into the correct namespace :
|
||||
```
|
||||
sudo ./multi-ue.sh -o2
|
||||
```
|
||||
|
||||
To make it easier to observe, UE2 will be allocated address as 'fe80::2/64' by following command :
|
||||
```
|
||||
sudo ip netns exec ue2 ip -6 addr add fe80::2/64 dev oaitun_ue2 nodad
|
||||
```
|
||||
Then launch Babel on UE2 :
|
||||
```
|
||||
ip netns exec ue2 bash -lc '
|
||||
set -e
|
||||
cat > /tmp/babeld-ue2.conf <<EOF
|
||||
interface oaitun_ue2
|
||||
redistribute local deny
|
||||
pid-file /tmp/babeld-ue2.pid
|
||||
EOF
|
||||
babeld -d 1 -c /tmp/babeld-ue2.conf
|
||||
'
|
||||
```
|
||||
|
||||
### Launch UE3 (namespace 3):
|
||||
First go into the correct namespace :
|
||||
```
|
||||
sudo ./multi-ue.sh -o3
|
||||
```
|
||||
|
||||
UE3 will be allocated address as 'fe80::3/64'
|
||||
```
|
||||
sudo ip netns exec ue3 ip -6 addr add fe80::3/64 dev oaitun_ue3 nodad
|
||||
|
||||
```
|
||||
Then launch Babel on UE3 :
|
||||
```
|
||||
ip netns exec ue3 bash -lc '
|
||||
set -e
|
||||
cat > /tmp/babeld-ue3.conf <<EOF
|
||||
interface oaitun_ue3
|
||||
redistribute local deny
|
||||
pid-file /tmp/babeld-ue3.pid
|
||||
EOF
|
||||
babeld -d 1 -c /tmp/babeld-ue3.conf
|
||||
'
|
||||
|
||||
```
|
||||
|
||||
Note : On babel, it will show neighbour connection with 'Neighbour ... rxcost 96 txcost 65535...', when it's 96, it means perfect connection, 65535 means a bad connection, if the connection is bad when generating the UE3, try to kill and restart again.
|
||||
|
||||
### Wireshark monitor
|
||||
Within the each namespace, you can start wireshark with filter on each node to check the Babel messages (example as for sync-ref, please update the oaitun_ueX name for each UE):
|
||||
```
|
||||
sudo wireshark -i oaitun_ue1 -k &
|
||||
```
|
||||
You should be able to see 'Babel Hello' message, and 'Babel Hello ihu'. ihu representing 'I hear you'.
|
||||
When there are two UEs connecting to sync-ref at the same time, you should be able to see 'Babel Hello ihu ihu'
|
||||
|
||||
|
||||
## Enable TAP in RFSim for Multiple UEs
|
||||
This part is to switch from default TUN to TAP.
|
||||
The baseline is, by default, system is running through TUN. In order to enable TAP, when you run each node simply add a flag at the begining: " OAI_TUNTAP_MODE=tap".
|
||||
|
||||
Optional : To disable the TAP (in case of an uncleaned restart...), do the following :
|
||||
```
|
||||
unset OAI_TUNTAP_MODE
|
||||
```
|
||||
### Launch Broker (outside namespace):
|
||||
```
|
||||
cd ran_build/build/
|
||||
./broker
|
||||
```
|
||||
### Launch SYNC-REF (namespace 1):
|
||||
```
|
||||
sudo ./multi-ue.sh -o1
|
||||
cd ran_build/build/
|
||||
sudo OAI_TUNTAP_MODE=tap RFSIMULATOR=server ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf --sl-mode 2 --sa --sync-ref --brokerip 10.201.1.100
|
||||
```
|
||||
|
||||
### Launch UE2 (namespace 2):
|
||||
```
|
||||
sudo ./multi-ue.sh -o2
|
||||
cd ran_build/build/
|
||||
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue1.conf --sl-mode 2 --sa --brokerip 10.202.1.100 --device_id 1 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
|
||||
```
|
||||
|
||||
### Launch UE3 (namespace 3):
|
||||
```
|
||||
sudo ./multi-ue.sh -o3
|
||||
cd ran_build/build/
|
||||
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue2.conf --sl-mode 2 --sa --brokerip 10.203.1.100 --device_id 2 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
|
||||
```
|
||||
|
||||
## Check connection with Batman
|
||||
|
||||
### Start Batman on sync-ref (namespace 1):
|
||||
```
|
||||
sudo ./multi-ue.sh -o1
|
||||
ip link set oaitun_ue1 address 02:00:00:00:00:01
|
||||
sudo batctl if add oaitun_ue1
|
||||
```
|
||||
|
||||
### Start Batman on UE2 (namespace 2):
|
||||
```
|
||||
sudo ./multi-ue.sh -o2
|
||||
ip link set oaitun_ue2 address 02:00:00:00:00:02
|
||||
sudo batctl if add oaitun_ue2
|
||||
```
|
||||
|
||||
|
||||
### Start Batman on UE3 (namespace 3):
|
||||
```
|
||||
sudo ./multi-ue.sh -o3
|
||||
ip link set oaitun_ue3 address 02:00:00:00:00:03
|
||||
sudo batctl if add oaitun_ue3
|
||||
```
|
||||
### Batman command
|
||||
To check the neighbour :
|
||||
```
|
||||
batctl n
|
||||
```
|
||||
To check the routing table :
|
||||
```
|
||||
batctl o
|
||||
```
|
||||
|
||||
### Start wireshark with filter
|
||||
You can check the current packets exchange with wireshark, please update the name 'oaitun_ueX' accordingly.
|
||||
```
|
||||
wireshark -k -i oaitun_ueX -Y "eth.type == 0x4305"
|
||||
```
|
||||
|
||||
## HW with TAP
|
||||
Similarly, we can start the HW with TAP with the following command
|
||||
|
||||
### Launch SYNC-REF (machine 1):
|
||||
```
|
||||
cd ran_build/build/
|
||||
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf --sa -E --sl-mode 2 --sync-ref --usrp-args "type=b200,master_clock_rate=46.08e6,enable_gps=true" --ue-txgain 10 --ue-rxgain 100 --thread-pool -1,-1,-1,-1 --clock-source 2 --time-source 2
|
||||
```
|
||||
|
||||
### Launch UE2 (machine 2):
|
||||
```
|
||||
cd ran_build/build/
|
||||
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue1.conf --sa -E --sl-mode 2 --usrp-args "type=b200,master_clock_rate=46.08e6,enable_gps=true" --ue-txgain 10 --ue-rxgain 100 --thread-pool -1,-1,-1,-1 --clock-source 2 --time-source 2
|
||||
```
|
||||
|
||||
### Launch UE3 (machine 3):
|
||||
```
|
||||
cd ran_build/build/
|
||||
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue2.conf --sa -E --sl-mode 2 --usrp-args "type=b200,master_clock_rate=46.08e6,enable_gps=true" --ue-txgain 10 --ue-rxgain 100 --thread-pool -1,-1,-1,-1 --clock-source 2 --time-source 2
|
||||
```
|
||||
|
||||
## More UEs generated with TAP
|
||||
The newest update enables to generate more than 2 UEs along with one sync-ref. The following is an example of 3 UEs.
|
||||
One would, first, need to create a new .conf file in openairinterface5g/targets/PROJECTS/NR-SIDELINK/, second, in file /openairinterface5g/openair2/LAYER2/NR_MAC_UE/mac_defs.h, the parameter of "#define CUR_SL_UE_CONNECTIONS" need to be updated to match the max number of UEs(Exclusive of sync-ref, this value is limited to 6 though)
|
||||
### Launch Broker (outside namespace):
|
||||
```
|
||||
cd ran_build/build/
|
||||
./broker
|
||||
```
|
||||
### Launch SYNC-REF (namespace 1):
|
||||
```
|
||||
sudo ./multi-ue.sh -o1
|
||||
cd ran_build/build/
|
||||
sudo OAI_TUNTAP_MODE=tap RFSIMULATOR=server ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf --sl-mode 2 --sa --sync-ref --brokerip 10.201.1.100 --thread-pool -1,-1
|
||||
```
|
||||
|
||||
### Launch UE2 (namespace 2):
|
||||
```
|
||||
sudo ./multi-ue.sh -o2
|
||||
cd ran_build/build/
|
||||
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue1.conf --sl-mode 2 --sa --brokerip 10.202.1.100 --device_id 1 --thread-pool -1,-1 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
|
||||
```
|
||||
|
||||
### Launch UE3 (namespace 3):
|
||||
```
|
||||
sudo ./multi-ue.sh -o3
|
||||
cd ran_build/build/
|
||||
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue2.conf --sl-mode 2 --sa --brokerip 10.203.1.100 --device_id 2 --thread-pool -1,-1 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
|
||||
```
|
||||
|
||||
### Launch UE4 (namespace 4):
|
||||
```
|
||||
sudo ./multi-ue.sh -o4
|
||||
cd ran_build/build/
|
||||
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue3.conf --sl-mode 2 --sa --brokerip 10.204.1.100 --device_id 3 --thread-pool -1,-1 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
|
||||
```
|
||||
|
||||
1
cmake_targets/babeld
Submodule
1
cmake_targets/babeld
Submodule
Submodule cmake_targets/babeld added at 950992f282
@@ -280,7 +280,7 @@ function main() {
|
||||
;;
|
||||
"SIMU")
|
||||
HW="OAI_"$2
|
||||
TARGET_LIST="$TARGET_LIST rfsimulator"
|
||||
TARGET_LIST="$TARGET_LIST rfsimulator broker"
|
||||
CMAKE_CMD="$CMAKE_CMD -DOAI_$2=ON"
|
||||
;;
|
||||
"AW2SORI")
|
||||
@@ -315,7 +315,7 @@ function main() {
|
||||
-P | --phy_simulators)
|
||||
SIMUS_PHY=1
|
||||
# TODO: fix: dlsim_tm4 pucchsim prachsim pdcchsim pbchsim mbmssim
|
||||
TARGET_LIST="$TARGET_LIST dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim"
|
||||
TARGET_LIST="$TARGET_LIST dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim nr_psbchsim"
|
||||
echo_info "Will compile dlsim, ulsim, ..."
|
||||
shift;;
|
||||
-s | --check)
|
||||
@@ -479,7 +479,7 @@ function main() {
|
||||
# add some default libraries that should always be built
|
||||
# for eNB, gNB, UEs, simulators
|
||||
if [[ $gNB == 1 || $eNB == 1 || $UE == 1 || $nrUE == 1 || $SIMUS_PHY == 1 || $RU == 1 ]]; then
|
||||
TARGET_LIST="$TARGET_LIST params_libconfig coding rfsimulator dfts"
|
||||
TARGET_LIST="$TARGET_LIST params_libconfig coding rfsimulator dfts broker"
|
||||
fi
|
||||
|
||||
mkdir -p $DIR/$BUILD_DIR/build
|
||||
@@ -523,7 +523,7 @@ function main() {
|
||||
echo_info "Doxygen generation log is located here: $doxygen_log"
|
||||
echo_info "Generating Doxygen files....please wait"
|
||||
(
|
||||
cmake --build . --target doc
|
||||
cmake3 --build . --target doc
|
||||
) >& $doxygen_log
|
||||
fi
|
||||
|
||||
|
||||
67
cmake_targets/multi-ue.sh
Executable file
67
cmake_targets/multi-ue.sh
Executable file
@@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
|
||||
ue_id=-1
|
||||
|
||||
create_namespace() {
|
||||
ue_id=$1
|
||||
local name="ue$ue_id"
|
||||
echo "creating namespace for UE ID ${ue_id} name ${name}"
|
||||
ip netns add $name
|
||||
ip link add v-eth$ue_id type veth peer name v-ue$ue_id
|
||||
ip link set v-ue$ue_id netns $name
|
||||
BASE_IP=$((200+ue_id))
|
||||
ip addr add 10.$BASE_IP.1.100/24 dev v-eth$ue_id
|
||||
ip link set v-eth$ue_id up
|
||||
iptables -t nat -A POSTROUTING -s 10.$BASE_IP.1.0/255.255.255.0 -o lo -j MASQUERADE
|
||||
iptables -A FORWARD -i lo -o v-eth$ue_id -j ACCEPT
|
||||
iptables -A FORWARD -o lo -i v-eth$ue_id -j ACCEPT
|
||||
ip netns exec $name ip link set dev lo up
|
||||
ip netns exec $name ip addr add 10.$BASE_IP.1.$ue_id/24 dev v-ue$ue_id
|
||||
ip netns exec $name ip link set v-ue$ue_id up
|
||||
}
|
||||
|
||||
delete_namespace() {
|
||||
local ue_id=$1
|
||||
local name="ue$ue_id"
|
||||
echo "deleting namespace for UE ID ${ue_id} name ${name}"
|
||||
ip link delete v-eth$ue_id
|
||||
ip netns delete $name
|
||||
}
|
||||
|
||||
list_namespaces() {
|
||||
ip netns list
|
||||
}
|
||||
|
||||
open_namespace() {
|
||||
if [[ $ue_id -lt 1 ]]; then echo "error: no last UE processed"; exit 1; fi
|
||||
local name="ue$ue_id"
|
||||
echo "opening shell in namespace ${name}"
|
||||
echo "type 'ip netns exec $name bash' in additional terminals"
|
||||
ip netns exec $name bash
|
||||
}
|
||||
|
||||
usage () {
|
||||
echo "$1 -c <num>: create namespace \"ue<num>\""
|
||||
echo "$1 -d <num>: delete namespace \"ue<num>\""
|
||||
echo "$1 -e : execute shell in last processed namespace"
|
||||
echo "$1 -l : list namespaces"
|
||||
echo "$1 -o <num>: open shell in namespace \"ue<num>\""
|
||||
}
|
||||
|
||||
prog_name=$(basename $0)
|
||||
|
||||
if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root"; exit 1; fi
|
||||
if [[ $# -eq 0 ]]; then echo "error: no parameters given"; usage $prog_name; exit 1; fi
|
||||
|
||||
while getopts c:d:ehlo: cmd
|
||||
do
|
||||
case "${cmd}" in
|
||||
c) create_namespace ${OPTARG};;
|
||||
d) delete_namespace ${OPTARG};;
|
||||
e) open_namespace; exit;;
|
||||
h) usage ${prog_name}; exit;;
|
||||
l) list_namespaces;;
|
||||
o) ue_id=${OPTARG}; open_namespace;;
|
||||
/?) echo "Invalid option"; usage ${prog_name}; exit;;
|
||||
esac
|
||||
done
|
||||
8
common/utils/colors.h
Normal file
8
common/utils/colors.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#define KNRM "\x1B[0m"
|
||||
#define KRED "\x1B[31m"
|
||||
#define KGRN "\x1B[32m"
|
||||
#define KYEL "\x1B[33m"
|
||||
#define KBLU "\x1B[34m"
|
||||
#define KMAG "\x1B[35m"
|
||||
#define KCYN "\x1B[36m"
|
||||
#define KWHT "\x1B[37m"
|
||||
@@ -33,6 +33,8 @@
|
||||
#include <stdint.h>
|
||||
#include "assertions.h"
|
||||
#include "nr_common.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h"
|
||||
|
||||
const char *duplex_mode[]={"FDD","TDD"};
|
||||
|
||||
@@ -232,6 +234,45 @@ int NRRIV2BW(int locationAndBandwidth,int N_RB) {
|
||||
|
||||
}
|
||||
|
||||
/* This function converts the FRIV to a start sub-channel and length in subchannels */
|
||||
/* for sl_MaxNumPerReserve = 2, the sequence from 38.214 for Lsc = 1,2,3, ...
|
||||
* goes like startsc + (0,N_subch,N_subch +(N_subch-1), N_subch + (N_subch-1) + (N_subch-2), ...)
|
||||
*
|
||||
* This is only done for sl_MaxNumPerReserve = 2
|
||||
* */
|
||||
void convNRFRIV(int FRIV,
|
||||
int N_subch,
|
||||
long sl_MaxNumPerReserve,
|
||||
uint16_t *Lsc,
|
||||
uint16_t *startsc,
|
||||
uint16_t *startsc2) {
|
||||
if (sl_MaxNumPerReserve == NR_SL_UE_SelectedConfigRP_r16__sl_MaxNumPerReserve_r16_n2) {
|
||||
*Lsc=1;
|
||||
int prevN=0;
|
||||
int N=N_subch;
|
||||
while (FRIV>N) {
|
||||
*Lsc = *Lsc+1;
|
||||
prevN = N;
|
||||
N += (N_subch - *Lsc + 1);
|
||||
}
|
||||
if (startsc) *startsc = FRIV-prevN;
|
||||
} else if (sl_MaxNumPerReserve == NR_SL_UE_SelectedConfigRP_r16__sl_MaxNumPerReserve_r16_n3) {
|
||||
*Lsc=1;
|
||||
int prevN=0;
|
||||
int N=N_subch;
|
||||
while (FRIV>N) {
|
||||
*Lsc = *Lsc + 1;
|
||||
prevN = N;
|
||||
N += ((N_subch - *Lsc + 1)*(N_subch - *Lsc + 1));
|
||||
}
|
||||
int tmp1 = FRIV - prevN; // This holds startsc1 + startsc2*(N_subch - *Lsc + 1)
|
||||
if (startsc2) *startsc2 = tmp1 / (N_subch - *Lsc + 1);
|
||||
if (startsc) *startsc = tmp1 % (N_subch - *Lsc + 1);
|
||||
} else {
|
||||
AssertFatal(1 == 0, "sl_MaxNumPerReserve is configured with incorrect value");
|
||||
}
|
||||
}
|
||||
|
||||
int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB) {
|
||||
int tmp = locationAndBandwidth/N_RB;
|
||||
int tmp2 = locationAndBandwidth%N_RB;
|
||||
@@ -351,7 +392,7 @@ int get_dmrs_port(int nl, uint16_t dmrs_ports)
|
||||
}
|
||||
}
|
||||
}
|
||||
AssertFatal(p>-1,"No dmrs port corresponding to layer %d found\n",nl);
|
||||
if (p==-1) LOG_E(NR_PHY,"No dmrs port corresponding to layer %d found\n",nl);
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -733,3 +774,61 @@ uint32_t get_ssb_offset_to_pointA(uint32_t absoluteFrequencySSB,
|
||||
AssertFatal(sco % scs_scaling == 0, "ssb offset %d can create frequency offset\n", sco);
|
||||
return ssb_offset_point_a;
|
||||
}
|
||||
|
||||
#define MAX_EL_213_9_3_2 19
|
||||
const float tab38_213_9_3_2[MAX_EL_213_9_3_2] = {1.125,1.250,1.375,1.625,1.750,2.000,2.250,2.500,2.875,3.125,3.500,4.000,5.000,6.250,8.000,10.000,12.625,15.875,20.000};
|
||||
|
||||
int get_NREsci2(const int sci2_alpha,
|
||||
const int sci2_payload_len,
|
||||
const int sci2_beta_offset,
|
||||
const int pssch_numsym,
|
||||
const int pscch_numsym,
|
||||
const int pscch_numrbs,
|
||||
const int l_subch,
|
||||
const int subchannel_size,
|
||||
const int mcs,
|
||||
const int mcs_tb_ind) {
|
||||
|
||||
float Osci2 = (float)sci2_payload_len;
|
||||
AssertFatal(sci2_beta_offset < MAX_EL_213_9_3_2, "illegal sci2_beta_offset %d\n",sci2_beta_offset);
|
||||
float beta_offset_sci2 = tab38_213_9_3_2[sci2_beta_offset];
|
||||
|
||||
|
||||
uint32_t R10240 = nr_get_code_rate_ul(mcs,mcs_tb_ind);
|
||||
uint32_t tmp = (uint32_t)ceil((Osci2 + 24)*beta_offset_sci2/((float)R10240/5120));
|
||||
float tmp2 = 12.0*pssch_numsym;
|
||||
int N_REsci1 = 12*pscch_numrbs*pscch_numsym;
|
||||
tmp2 *= l_subch*subchannel_size;
|
||||
tmp2 -= N_REsci1;
|
||||
tmp2 *= ((float)sci2_alpha/100.0);
|
||||
int min_val = min(tmp,(int)ceil(tmp2));
|
||||
uint8_t gamma = 12 - (min_val % 12);
|
||||
return min_val + (gamma % 12);
|
||||
|
||||
}
|
||||
int get_NREsci2_2(const int sci2_alpha,
|
||||
const int sci2_payload_len,
|
||||
const int sci2_beta_offset,
|
||||
const int pssch_numsym,
|
||||
const int pscch_numsym,
|
||||
const int pscch_numrbs,
|
||||
const int l_subch,
|
||||
const int subchannel_size,
|
||||
const int target_coderate,
|
||||
const int mcs_table_index) {
|
||||
|
||||
float Osci2 = (float)sci2_payload_len;
|
||||
AssertFatal(sci2_beta_offset < MAX_EL_213_9_3_2, "illegal sci2_beta_offset %d\n",sci2_beta_offset);
|
||||
float beta_offset_sci2 = tab38_213_9_3_2[sci2_beta_offset];
|
||||
|
||||
uint32_t R10240 = get_softmodem_params()->sl_mode ? nr_get_code_rate_ul(1, mcs_table_index) : target_coderate;
|
||||
uint32_t tmp = (uint32_t)ceil((Osci2 + 24)*beta_offset_sci2/((float)R10240/5120));
|
||||
float tmp2 = 12.0*pssch_numsym;
|
||||
int N_REsci1 = 12*pscch_numrbs*pscch_numsym;
|
||||
tmp2 *= l_subch*subchannel_size;
|
||||
tmp2 -= N_REsci1;
|
||||
tmp2 *= ((float)sci2_alpha/100.0);
|
||||
int min_val = min(tmp,(int)ceil(tmp2));
|
||||
uint8_t gamma = 12 - (min_val % 12);
|
||||
return min_val + (gamma % 12);
|
||||
}
|
||||
|
||||
@@ -90,6 +90,7 @@ frame_type_t get_frame_type(uint16_t nr_bandP, uint8_t scs_index);
|
||||
uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex);
|
||||
int NRRIV2BW(int locationAndBandwidth,int N_RB);
|
||||
int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB);
|
||||
void convNRFRIV(int FRIV, int N_subch, long sl_MaxNumPerReserve, uint16_t *Lsc, uint16_t *startsc, uint16_t *startsc2);
|
||||
int PRBalloc_to_locationandbandwidth0(int NPRB,int RBstart,int BWPsize);
|
||||
int PRBalloc_to_locationandbandwidth(int NPRB,int RBstart);
|
||||
int get_subband_size(int NPRB,int size);
|
||||
@@ -113,7 +114,21 @@ uint32_t get_ssb_offset_to_pointA(uint32_t absoluteFrequencySSB,
|
||||
uint32_t absoluteFrequencyPointA,
|
||||
int ssbSubcarrierSpacing,
|
||||
int frequency_range);
|
||||
|
||||
int get_NREsci2(const int sci2_alpha,
|
||||
const int sci2_payload_len,
|
||||
const int sci2_beta_offset,
|
||||
const int pssch_numsym,
|
||||
const int pscch_numsym,
|
||||
const int pscch_numrbs,
|
||||
const int l_subch,
|
||||
const int subchannel_size,
|
||||
const int mcs,
|
||||
const int mcs_tb_ind);
|
||||
|
||||
int get_ssb_subcarrier_offset(uint32_t absoluteFrequencySSB, uint32_t absoluteFrequencyPointA);
|
||||
|
||||
|
||||
#define CEILIDIV(a,b) ((a+b-1)/b)
|
||||
#define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1))
|
||||
|
||||
|
||||
@@ -231,8 +231,9 @@ void threadCreate(pthread_t* t, void * (*func)(void*), void * param, char* name,
|
||||
int settingPriority = 1;
|
||||
ret=pthread_attr_init(&attr);
|
||||
AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno);
|
||||
|
||||
LOG_I(UTIL,"Creating thread %s with affinity %d and priority %d\n",name,affinity,priority);
|
||||
size_t stacksize;
|
||||
pthread_attr_getstacksize(&attr,&stacksize);
|
||||
LOG_I(UTIL,"Creating thread %s with affinity %d and priority %d, stacksize %d\n",name,affinity,priority,(int) stacksize);
|
||||
|
||||
if (checkIfFedoraDistribution())
|
||||
if (checkIfGenericKernelOnFedora())
|
||||
|
||||
49
doc/JSUC.md
Normal file
49
doc/JSUC.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Joint sidelink and Uu communication (JSUC)
|
||||
This tutorial will discuss the setup for a hybrid communication mode using sidelink and Uu.
|
||||
|
||||
## Setup
|
||||
The idea is to have 4 UEs, two running sidelink and two running normal mode. A logical UE (UE A and UE B) supporting hybrid communication mode is represented by 2 UEs, one running sidelink and the other running normal mode.
|
||||
|
||||

|
||||
|
||||
The following repos will be used for each technology:
|
||||
- Uu: `mkdir normal-mode`, `cd normal-mode` then clone `https://github.com/beraoudabdelkhalek/rfsim-Uu-metrics`
|
||||
- Sidelink: `mkdir sidelink`, `cd sidelink` then clone `https://gitlab.eurecom.fr/oai/openairinterface5g` and `git checkout sl-eurecom4`
|
||||
|
||||
- Build both projects, and build the telnet server for each project `./build_oai --build-lib telnetsrv`
|
||||
- Run the OAI core network.
|
||||
- Create 4 namespaces: `sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -c x` where x is from 1-4
|
||||
- Run the gNB executable on the host using the project inside the `normal-mode` directory:
|
||||
```sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --rfsim --rfsimulator.options chanmod --telnetsrv```
|
||||
- Run the broker on the host using the project inside `sidelink` directory.
|
||||
- Run UE 1 in NS 1 (normal mode) using `normal-mode` directory:
|
||||
`sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -o 1`
|
||||
|
||||
```sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --rfsimulator.serveraddr 10.201.1.100 --uicc0.imsi 001010000000001 -O ../../../ci-scripts/conf_files/nrue.uicc.conf --rfsimulator.options chanmod --telnetsrv --telnetsrv.listenport 9091```
|
||||
|
||||
- Run UE 2 in NS 2 (sidelink mode) using `sidelink` directory:
|
||||
`sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -o 2`
|
||||
|
||||
```sudo RFSIMULATOR=server ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf --sl-mode 2 --sa --sync-ref --brokerip 10.202.1.100```
|
||||
|
||||
- Run UE 3 in NS 3 (sidelink mode) using `sidelink` directory:
|
||||
`sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -o 3`
|
||||
|
||||
```sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_ue1.conf --sl-mode 2 --sa --brokerip 10.203.1.100 --device_id 1```
|
||||
|
||||
- Run UE 4 in NS 4 (normal mode) using `normal-mode` directory:
|
||||
`sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -o 4`
|
||||
|
||||
```sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --rfsimulator.serveraddr 10.204.1.100 --uicc0.imsi 001010000000002 -O ../../../ci-scripts/conf_files/nrue.uicc.conf --rfsimulator.options chanmod --telnetsrv --telnetsrv.listenport 9091```
|
||||
|
||||
## Connectivity test
|
||||
|
||||
### Uu Connectivity:
|
||||
From UE 1 ping UE 4:
|
||||
- `sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -o 1`
|
||||
- `ping 10.0.0.3`
|
||||
|
||||
### Sidelink Connectivity:
|
||||
From UE 2 ping UE 3:
|
||||
- `sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -o 2`
|
||||
- `ping 10.0.0.2`
|
||||
BIN
doc/images/hybrid_communication_setup.png
Executable file
BIN
doc/images/hybrid_communication_setup.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
@@ -169,7 +169,7 @@ extern void *udp_eNB_task(void *args_p);
|
||||
|
||||
int transmission_mode=1;
|
||||
int emulate_rf = 0;
|
||||
int numerology = 0;
|
||||
int numerology = 1; //Jin change to 1
|
||||
|
||||
|
||||
static char *parallel_config = NULL;
|
||||
|
||||
@@ -99,7 +99,8 @@
|
||||
typedef enum {
|
||||
pss = 0,
|
||||
pbch = 1,
|
||||
si = 2
|
||||
si = 2,
|
||||
psbch = 3
|
||||
} sync_mode_t;
|
||||
|
||||
static void *NRUE_phy_stub_standalone_pnf_task(void *arg);
|
||||
@@ -161,6 +162,9 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue,
|
||||
// initialize all signal buffers
|
||||
init_nr_ue_signal(ue, nb_connected_gNB);
|
||||
|
||||
if (ue->sl_mode)
|
||||
sl_ue_phy_init(ue);
|
||||
|
||||
// intialize transport
|
||||
init_nr_ue_transport(ue);
|
||||
|
||||
@@ -314,7 +318,7 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg)
|
||||
uint8_t gNB_id = 0;
|
||||
nr_uplink_indication_t ul_info;
|
||||
int slots_per_frame = 20; //30 kHZ subcarrier spacing
|
||||
int slot_ahead = 2; // TODO: Make this dynamic
|
||||
int slot_ahead = 3; // TODO: Make this dynamic
|
||||
ul_info.cc_id = CC_id;
|
||||
ul_info.gNB_index = gNB_id;
|
||||
ul_info.module_id = mod_id;
|
||||
@@ -376,11 +380,12 @@ static void UE_synch(void *arg) {
|
||||
int i, hw_slot_offset;
|
||||
PHY_VARS_NR_UE *UE = syncD->UE;
|
||||
sync_mode_t sync_mode = pbch;
|
||||
if (UE->sl_mode == 2 && !get_nrUE_params()->sync_ref) sync_mode = psbch;
|
||||
//int CC_id = UE->CC_id;
|
||||
static int freq_offset=0;
|
||||
UE->is_synchronized = 0;
|
||||
|
||||
if (UE->UE_scan == 0) {
|
||||
if (UE->UE_scan == 0 && !UE->sl_mode) {
|
||||
|
||||
for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
|
||||
|
||||
@@ -493,6 +498,52 @@ static void UE_synch(void *arg) {
|
||||
}
|
||||
break;
|
||||
|
||||
case psbch:
|
||||
LOG_I(PHY, "[UE thread Synch] Running Sidelink Initial Synch \n");
|
||||
NR_DL_FRAME_PARMS *fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
dl_carrier = fp->sl_CarrierFreq;
|
||||
ul_carrier = fp->sl_CarrierFreq;
|
||||
|
||||
if (sl_nr_slss_search(UE, &syncD->proc, 16) == 0) {
|
||||
freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync
|
||||
hw_slot_offset = ((UE->rx_offset<<1) / fp->samples_per_subframe * fp->slots_per_subframe) +
|
||||
round((float)((UE->rx_offset<<1) % fp->samples_per_subframe)/fp->samples_per_slot0);
|
||||
|
||||
// rerun with new cell parameters and frequency-offset
|
||||
// todo: the freq_offset computed on DL shall be scaled before being applied to UL
|
||||
nr_rf_card_config_freq(&openair0_cfg[UE->rf_map.card], ul_carrier, dl_carrier, freq_offset);
|
||||
|
||||
LOG_I(PHY,"Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %f (DL %f Hz, UL %f Hz)\n",
|
||||
hw_slot_offset,
|
||||
freq_offset,
|
||||
openair0_cfg[UE->rf_map.card].rx_gain[0],
|
||||
openair0_cfg[UE->rf_map.card].rx_freq[0],
|
||||
openair0_cfg[UE->rf_map.card].tx_freq[0]);
|
||||
|
||||
UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0]);
|
||||
if (UE->UE_scan_carrier == 1) {
|
||||
UE->UE_scan_carrier = 0;
|
||||
} else {
|
||||
UE->is_synchronized = 1;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (UE->UE_scan_carrier == 1) {
|
||||
|
||||
if (freq_offset >= 0)
|
||||
freq_offset += 100;
|
||||
|
||||
freq_offset *= -1;
|
||||
|
||||
nr_rf_card_config_freq(&openair0_cfg[UE->rf_map.card], ul_carrier, dl_carrier, freq_offset);
|
||||
|
||||
LOG_I(PHY, "Sidelink Initial sync failed: trying carrier off %d Hz\n", freq_offset);
|
||||
|
||||
UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case si:
|
||||
default:
|
||||
break;
|
||||
@@ -500,14 +551,18 @@ static void UE_synch(void *arg) {
|
||||
}
|
||||
}
|
||||
|
||||
static void RU_write(nr_rxtx_thread_data_t *rxtxD) {
|
||||
static void RU_write(nr_rxtx_thread_data_t *rxtxD, int sl_tx_action) {
|
||||
|
||||
PHY_VARS_NR_UE *UE = rxtxD->UE;
|
||||
UE_nr_rxtx_proc_t *proc = &rxtxD->proc;
|
||||
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
if (UE->sl_mode == 2)
|
||||
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
void *txp[NB_ANTENNAS_TX];
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
|
||||
txp[i] = (void *)&UE->common_vars.txData[i][UE->frame_parms.get_samples_slot_timestamp(proc->nr_slot_tx, &UE->frame_parms, 0)];
|
||||
for (int i=0; i<fp->nb_antennas_tx; i++)
|
||||
txp[i] = (void *)&UE->common_vars.txData[i][fp->get_samples_slot_timestamp(proc->nr_slot_tx, fp, 0)];
|
||||
|
||||
radio_tx_burst_flag_t flags = TX_BURST_INVALID;
|
||||
|
||||
@@ -516,27 +571,34 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD) {
|
||||
openair0_cfg[0].duplex_mode == duplex_mode_TDD &&
|
||||
!get_softmodem_params()->continuous_tx) {
|
||||
|
||||
uint8_t tdd_period = mac->phy_config.config_req.tdd_table.tdd_period_in_slots;
|
||||
int nrofUplinkSlots, nrofUplinkSymbols;
|
||||
if (mac->scc) {
|
||||
nrofUplinkSlots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
|
||||
nrofUplinkSymbols = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols;
|
||||
}
|
||||
else {
|
||||
nrofUplinkSlots = mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
|
||||
nrofUplinkSymbols = mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols;
|
||||
}
|
||||
//Perform USRP write only in case SL Txn needs to be done.
|
||||
if (UE->sl_mode == 2) {
|
||||
flags = sl_tx_action ? TX_BURST_START_AND_END
|
||||
: TX_BURST_INVALID;
|
||||
} else {
|
||||
|
||||
int slot_tx_usrp = proc->nr_slot_tx;
|
||||
uint8_t num_UL_slots = nrofUplinkSlots + (nrofUplinkSymbols != 0);
|
||||
uint8_t first_tx_slot = tdd_period - num_UL_slots;
|
||||
uint8_t tdd_period = mac->phy_config.config_req.tdd_table.tdd_period_in_slots;
|
||||
int nrofUplinkSlots, nrofUplinkSymbols;
|
||||
if (mac->scc) {
|
||||
nrofUplinkSlots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
|
||||
nrofUplinkSymbols = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols;
|
||||
}
|
||||
else {
|
||||
nrofUplinkSlots = mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
|
||||
nrofUplinkSymbols = mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols;
|
||||
}
|
||||
|
||||
if (slot_tx_usrp % tdd_period == first_tx_slot)
|
||||
flags = TX_BURST_START;
|
||||
else if (slot_tx_usrp % tdd_period == first_tx_slot + num_UL_slots - 1)
|
||||
flags = TX_BURST_END;
|
||||
else if (slot_tx_usrp % tdd_period > first_tx_slot)
|
||||
flags = TX_BURST_MIDDLE;
|
||||
int slot_tx_usrp = proc->nr_slot_tx;
|
||||
uint8_t num_UL_slots = nrofUplinkSlots + (nrofUplinkSymbols != 0);
|
||||
uint8_t first_tx_slot = tdd_period - num_UL_slots;
|
||||
|
||||
if (slot_tx_usrp % tdd_period == first_tx_slot)
|
||||
flags = TX_BURST_START;
|
||||
else if (slot_tx_usrp % tdd_period == first_tx_slot + num_UL_slots - 1)
|
||||
flags = TX_BURST_END;
|
||||
else if (slot_tx_usrp % tdd_period > first_tx_slot)
|
||||
flags = TX_BURST_MIDDLE;
|
||||
}
|
||||
} else {
|
||||
flags = TX_BURST_MIDDLE;
|
||||
}
|
||||
@@ -547,10 +609,10 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD) {
|
||||
proc->timestamp_tx,
|
||||
txp,
|
||||
rxtxD->writeBlockSize,
|
||||
UE->frame_parms.nb_antennas_tx,
|
||||
fp->nb_antennas_tx,
|
||||
flags),"");
|
||||
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
|
||||
for (int i=0; i<fp->nb_antennas_tx; i++)
|
||||
memset(txp[i], 0, rxtxD->writeBlockSize);
|
||||
|
||||
}
|
||||
@@ -561,45 +623,77 @@ void processSlotTX(void *arg) {
|
||||
UE_nr_rxtx_proc_t *proc = &rxtxD->proc;
|
||||
PHY_VARS_NR_UE *UE = rxtxD->UE;
|
||||
nr_phy_data_tx_t phy_data = {0};
|
||||
int sl_tx_action = 0;
|
||||
|
||||
LOG_D(PHY,"%d.%d => slot type %d\n", proc->frame_tx, proc->nr_slot_tx, proc->tx_slot_type);
|
||||
if (proc->tx_slot_type == NR_UPLINK_SLOT || proc->tx_slot_type == NR_MIXED_SLOT){
|
||||
|
||||
// wait for rx slots to send indication (if any) that DLSCH decoding is finished
|
||||
for(int i=0; i < rxtxD->tx_wait_for_dlsch; i++) {
|
||||
notifiedFIFO_elt_t *res = pullNotifiedFIFO(UE->tx_resume_ind_fifo[proc->nr_slot_tx]);
|
||||
delNotifiedFIFO_elt(res);
|
||||
}
|
||||
if (proc->tx_slot_type == NR_SIDELINK_SLOT && UE->sl_mode == 2) {
|
||||
|
||||
// trigger L2 to run ue_scheduler thru IF module
|
||||
// [TODO] mapping right after NR initial sync
|
||||
if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) {
|
||||
// trigger L2 to run ue_scheduler thru IF module
|
||||
if(UE->if_inst != NULL && UE->if_inst->sl_indication != NULL) {
|
||||
start_meas(&UE->ue_ul_indication_stats);
|
||||
nr_uplink_indication_t ul_indication;
|
||||
memset((void*)&ul_indication, 0, sizeof(ul_indication));
|
||||
nr_sidelink_indication_t sl_indication;
|
||||
memset((void*)&sl_indication, 0, sizeof(sl_indication));
|
||||
|
||||
ul_indication.module_id = UE->Mod_id;
|
||||
ul_indication.gNB_index = proc->gNB_id;
|
||||
ul_indication.cc_id = UE->CC_id;
|
||||
ul_indication.frame_rx = proc->frame_rx;
|
||||
ul_indication.slot_rx = proc->nr_slot_rx;
|
||||
ul_indication.frame_tx = proc->frame_tx;
|
||||
ul_indication.slot_tx = proc->nr_slot_tx;
|
||||
ul_indication.phy_data = &phy_data;
|
||||
sl_indication.module_id = UE->Mod_id;
|
||||
sl_indication.gNB_index = proc->gNB_id;
|
||||
sl_indication.cc_id = UE->CC_id;
|
||||
sl_indication.frame_rx = proc->frame_rx;
|
||||
sl_indication.slot_rx = proc->nr_slot_rx;
|
||||
sl_indication.frame_tx = proc->frame_tx;
|
||||
sl_indication.slot_tx = proc->nr_slot_tx;
|
||||
sl_indication.phy_data = &phy_data;
|
||||
sl_indication.slot_type = SIDELINK_SLOT_TYPE_TX;
|
||||
|
||||
LOG_D(NR_PHY,"Sending SL indication RX %d.%d TX %d.%d\n",proc->frame_rx,proc->nr_slot_rx,proc->frame_tx,proc->nr_slot_tx);
|
||||
UE->if_inst->sl_indication(&sl_indication);
|
||||
|
||||
UE->if_inst->ul_indication(&ul_indication);
|
||||
stop_meas(&UE->ue_ul_indication_stats);
|
||||
}
|
||||
|
||||
phy_procedures_nrUE_TX(UE, proc, &phy_data);
|
||||
sl_tx_action = phy_procedures_nrUE_SL_TX(UE, proc, &phy_data);
|
||||
|
||||
} else {
|
||||
if (proc->tx_slot_type == NR_UPLINK_SLOT || proc->tx_slot_type == NR_MIXED_SLOT){
|
||||
|
||||
// wait for rx slots to send indication (if any) that DLSCH decoding is finished
|
||||
for(int i=0; i < rxtxD->tx_wait_for_dlsch; i++) {
|
||||
notifiedFIFO_elt_t *res = pullNotifiedFIFO(UE->tx_resume_ind_fifo[proc->nr_slot_tx]);
|
||||
delNotifiedFIFO_elt(res);
|
||||
}
|
||||
|
||||
// trigger L2 to run ue_scheduler thru IF module
|
||||
// [TODO] mapping right after NR initial sync
|
||||
if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) {
|
||||
start_meas(&UE->ue_ul_indication_stats);
|
||||
nr_uplink_indication_t ul_indication;
|
||||
memset((void*)&ul_indication, 0, sizeof(ul_indication));
|
||||
|
||||
ul_indication.module_id = UE->Mod_id;
|
||||
ul_indication.gNB_index = proc->gNB_id;
|
||||
ul_indication.cc_id = UE->CC_id;
|
||||
ul_indication.frame_rx = proc->frame_rx;
|
||||
ul_indication.slot_rx = proc->nr_slot_rx;
|
||||
ul_indication.frame_tx = proc->frame_tx;
|
||||
ul_indication.slot_tx = proc->nr_slot_tx;
|
||||
ul_indication.phy_data = &phy_data;
|
||||
|
||||
UE->if_inst->ul_indication(&ul_indication);
|
||||
stop_meas(&UE->ue_ul_indication_stats);
|
||||
}
|
||||
|
||||
phy_procedures_nrUE_TX(UE, proc, &phy_data);
|
||||
}
|
||||
}
|
||||
|
||||
RU_write(rxtxD);
|
||||
RU_write(rxtxD, sl_tx_action);
|
||||
}
|
||||
|
||||
nr_phy_data_t UE_dl_preprocessing(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc)
|
||||
{
|
||||
nr_phy_data_t phy_data = {0};
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
if (UE->sl_mode == 2)
|
||||
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
if (IS_SOFTMODEM_NOS1 || get_softmodem_params()->sa) {
|
||||
|
||||
@@ -614,34 +708,48 @@ nr_phy_data_t UE_dl_preprocessing(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc)
|
||||
}
|
||||
|
||||
/* send tick to RLC and PDCP every ms */
|
||||
if (proc->nr_slot_rx % UE->frame_parms.slots_per_subframe == 0) {
|
||||
if (proc->nr_slot_rx % fp->slots_per_subframe == 0) {
|
||||
void nr_rlc_tick(int frame, int subframe);
|
||||
void nr_pdcp_tick(int frame, int subframe);
|
||||
nr_rlc_tick(proc->frame_rx, proc->nr_slot_rx / UE->frame_parms.slots_per_subframe);
|
||||
nr_pdcp_tick(proc->frame_rx, proc->nr_slot_rx / UE->frame_parms.slots_per_subframe);
|
||||
nr_rlc_tick(proc->frame_rx, proc->nr_slot_rx / fp->slots_per_subframe);
|
||||
nr_pdcp_tick(proc->frame_rx, proc->nr_slot_rx / fp->slots_per_subframe);
|
||||
}
|
||||
}
|
||||
|
||||
if (proc->rx_slot_type == NR_DOWNLINK_SLOT || proc->rx_slot_type == NR_MIXED_SLOT) {
|
||||
if (UE->sl_mode == 2) {
|
||||
if (proc->rx_slot_type == NR_SIDELINK_SLOT) {
|
||||
|
||||
if(UE->if_inst != NULL && UE->if_inst->dl_indication != NULL) {
|
||||
nr_downlink_indication_t dl_indication;
|
||||
nr_fill_dl_indication(&dl_indication, NULL, NULL, proc, UE, &phy_data);
|
||||
UE->if_inst->dl_indication(&dl_indication);
|
||||
if(UE->if_inst != NULL && UE->if_inst->sl_indication != NULL) {
|
||||
nr_sidelink_indication_t sl_indication;
|
||||
nr_fill_sl_indication(&sl_indication, NULL, NULL, proc, UE, &phy_data);
|
||||
UE->if_inst->sl_indication(&sl_indication);
|
||||
}
|
||||
uint64_t a=rdtsc_oai();
|
||||
psbch_pscch_pssch_processing(UE, proc, &phy_data);
|
||||
LOG_D(PHY, "In %s: slot %d:%d, time %llu\n", __FUNCTION__, proc->frame_rx, proc->nr_slot_rx, (rdtsc_oai()-a)/3500);
|
||||
}
|
||||
} else {
|
||||
if (proc->rx_slot_type == NR_DOWNLINK_SLOT || proc->rx_slot_type == NR_MIXED_SLOT){
|
||||
|
||||
if(UE->if_inst != NULL && UE->if_inst->dl_indication != NULL) {
|
||||
nr_downlink_indication_t dl_indication;
|
||||
nr_fill_dl_indication(&dl_indication, NULL, NULL, proc, UE, &phy_data);
|
||||
UE->if_inst->dl_indication(&dl_indication);
|
||||
}
|
||||
|
||||
uint64_t a=rdtsc_oai();
|
||||
pbch_pdcch_processing(UE, proc, &phy_data);
|
||||
if (phy_data.dlsch[0].active) {
|
||||
// indicate to tx thread to wait for DLSCH decoding
|
||||
const int ack_nack_slot = (proc->nr_slot_rx + phy_data.dlsch[0].dlsch_config.k1_feedback) % UE->frame_parms.slots_per_frame;
|
||||
UE->tx_wait_for_dlsch[ack_nack_slot]++;
|
||||
}
|
||||
|
||||
LOG_D(PHY, "In %s: slot %d, time %llu\n", __FUNCTION__, proc->nr_slot_rx, (rdtsc_oai()-a)/3500);
|
||||
}
|
||||
|
||||
uint64_t a=rdtsc_oai();
|
||||
pbch_pdcch_processing(UE, proc, &phy_data);
|
||||
if (phy_data.dlsch[0].active) {
|
||||
// indicate to tx thread to wait for DLSCH decoding
|
||||
const int ack_nack_slot = (proc->nr_slot_rx + phy_data.dlsch[0].dlsch_config.k1_feedback) % UE->frame_parms.slots_per_frame;
|
||||
UE->tx_wait_for_dlsch[ack_nack_slot]++;
|
||||
}
|
||||
|
||||
LOG_D(PHY, "In %s: slot %d, time %llu\n", __FUNCTION__, proc->nr_slot_rx, (rdtsc_oai()-a)/3500);
|
||||
ue_ta_procedures(UE, proc->nr_slot_tx, proc->frame_tx);
|
||||
}
|
||||
|
||||
ue_ta_procedures(UE, proc->nr_slot_tx, proc->frame_tx);
|
||||
return phy_data;
|
||||
}
|
||||
|
||||
@@ -651,14 +759,20 @@ void UE_dl_processing(void *arg) {
|
||||
PHY_VARS_NR_UE *UE = rxtxD->UE;
|
||||
nr_phy_data_t *phy_data = &rxtxD->phy_data;
|
||||
|
||||
pdsch_processing(UE, proc, phy_data);
|
||||
if (UE->sl_mode == 0)
|
||||
pdsch_processing(UE, proc, phy_data);
|
||||
}
|
||||
|
||||
void dummyWrite(PHY_VARS_NR_UE *UE,openair0_timestamp timestamp, int writeBlockSize) {
|
||||
void *dummy_tx[UE->frame_parms.nb_antennas_tx];
|
||||
int16_t dummy_tx_data[UE->frame_parms.nb_antennas_tx][2*writeBlockSize]; // 2 because the function we call use pairs of int16_t implicitly as complex numbers
|
||||
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
if (UE->sl_mode == 2)
|
||||
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
void *dummy_tx[fp->nb_antennas_tx];
|
||||
int16_t dummy_tx_data[fp->nb_antennas_tx][2*writeBlockSize]; // 2 because the function we call use pairs of int16_t implicitly as complex numbers
|
||||
memset(dummy_tx_data, 0, sizeof(dummy_tx_data));
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
|
||||
for (int i=0; i<fp->nb_antennas_tx; i++)
|
||||
dummy_tx[i]=dummy_tx_data[i];
|
||||
|
||||
AssertFatal( writeBlockSize ==
|
||||
@@ -666,37 +780,45 @@ void dummyWrite(PHY_VARS_NR_UE *UE,openair0_timestamp timestamp, int writeBlockS
|
||||
timestamp,
|
||||
dummy_tx,
|
||||
writeBlockSize,
|
||||
UE->frame_parms.nb_antennas_tx,
|
||||
fp->nb_antennas_tx,
|
||||
4),"");
|
||||
|
||||
}
|
||||
|
||||
void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash) {
|
||||
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
int num_frames = 2;
|
||||
//In Sidelink worst case SL-SSB can be sent once in 16 frames
|
||||
if (UE->sl_mode == 2) {
|
||||
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
num_frames = SL_NR_PSBCH_REPETITION_IN_FRAMES;
|
||||
}
|
||||
|
||||
void *rxp[NB_ANTENNAS_RX];
|
||||
|
||||
for(int x=0; x<20; x++) { // two frames for initial sync
|
||||
for (int slot=0; slot<UE->frame_parms.slots_per_subframe; slot ++ ) {
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++) {
|
||||
for(int x=0; x< num_frames*NR_NUMBER_OF_SUBFRAMES_PER_FRAME; x++) { // two frames for initial sync
|
||||
for (int slot=0; slot<fp->slots_per_subframe; slot ++ ) {
|
||||
for (int i=0; i<fp->nb_antennas_rx; i++) {
|
||||
if (toTrash)
|
||||
rxp[i]=malloc16(UE->frame_parms.get_samples_per_slot(slot,&UE->frame_parms)*4);
|
||||
rxp[i]=malloc16(fp->get_samples_per_slot(slot,fp)*4);
|
||||
else
|
||||
rxp[i] = ((void *)&UE->common_vars.rxdata[i][0]) +
|
||||
4*((x*UE->frame_parms.samples_per_subframe)+
|
||||
UE->frame_parms.get_samples_slot_timestamp(slot,&UE->frame_parms,0));
|
||||
4*((x*fp->samples_per_subframe)+
|
||||
fp->get_samples_slot_timestamp(slot,fp,0));
|
||||
}
|
||||
|
||||
AssertFatal( UE->frame_parms.get_samples_per_slot(slot,&UE->frame_parms) ==
|
||||
|
||||
AssertFatal( fp->get_samples_per_slot(slot,fp) ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
timestamp,
|
||||
rxp,
|
||||
UE->frame_parms.get_samples_per_slot(slot,&UE->frame_parms),
|
||||
UE->frame_parms.nb_antennas_rx), "");
|
||||
fp->get_samples_per_slot(slot,fp),
|
||||
fp->nb_antennas_rx), "");
|
||||
|
||||
if (IS_SOFTMODEM_RFSIM)
|
||||
dummyWrite(UE,*timestamp, UE->frame_parms.get_samples_per_slot(slot,&UE->frame_parms));
|
||||
dummyWrite(UE,*timestamp, fp->get_samples_per_slot(slot,fp));
|
||||
if (toTrash)
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
|
||||
for (int i=0; i<fp->nb_antennas_rx; i++)
|
||||
free(rxp[i]);
|
||||
}
|
||||
}
|
||||
@@ -707,21 +829,25 @@ void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) {
|
||||
|
||||
LOG_I(PHY,"Resynchronizing RX by %d samples\n",UE->rx_offset);
|
||||
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
if (UE->sl_mode == 2)
|
||||
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) {
|
||||
// Resynchonize by slot (will work with numerology 1 only)
|
||||
for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe/2 ) {
|
||||
int unitTransfer=size>UE->frame_parms.samples_per_subframe/2 ? UE->frame_parms.samples_per_subframe/2 : size ;
|
||||
for ( int size=UE->rx_offset ; size > 0 ; size -= fp->samples_per_subframe/2 ) {
|
||||
int unitTransfer=size>fp->samples_per_subframe/2 ? fp->samples_per_subframe/2 : size ;
|
||||
AssertFatal(unitTransfer ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
timestamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
unitTransfer,
|
||||
UE->frame_parms.nb_antennas_rx),"");
|
||||
fp->nb_antennas_rx),"");
|
||||
}
|
||||
} else {
|
||||
*timestamp += UE->frame_parms.get_samples_per_slot(1,&UE->frame_parms);
|
||||
for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe ) {
|
||||
int unitTransfer=size>UE->frame_parms.samples_per_subframe ? UE->frame_parms.samples_per_subframe : size ;
|
||||
*timestamp += fp->get_samples_per_slot(1,fp);
|
||||
for ( int size=UE->rx_offset ; size > 0 ; size -= fp->samples_per_subframe ) {
|
||||
int unitTransfer=size>fp->samples_per_subframe ? fp->samples_per_subframe : size ;
|
||||
// we write before read because gNB waits for UE to write and both executions halt
|
||||
// this happens here as the read size is samples_per_subframe which is very much larger than samp_per_slot
|
||||
if (IS_SOFTMODEM_RFSIM) dummyWrite(UE,*timestamp, unitTransfer);
|
||||
@@ -730,7 +856,7 @@ void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) {
|
||||
timestamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
unitTransfer,
|
||||
UE->frame_parms.nb_antennas_rx),"");
|
||||
fp->nb_antennas_rx),"");
|
||||
*timestamp += unitTransfer; // this does not affect the read but needed for RFSIM write
|
||||
}
|
||||
}
|
||||
@@ -761,6 +887,12 @@ void *UE_thread(void *arg)
|
||||
void *rxp[NB_ANTENNAS_RX];
|
||||
int start_rx_stream = 0;
|
||||
fapi_nr_config_request_t *cfg = &UE->nrUE_config;
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
int is_sidelink = (UE->sl_mode == 2) ? 1 : 0;
|
||||
if (is_sidelink) {
|
||||
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
openair0_cfg[0].gpio_controller = RU_GPIO_CONTROL_GENERIC;
|
||||
}
|
||||
AssertFatal(0== openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]), "");
|
||||
UE->rfdevice.host_type = RAU_HOST;
|
||||
UE->is_synchronized = 0;
|
||||
@@ -779,7 +911,7 @@ void *UE_thread(void *arg)
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(0);
|
||||
|
||||
bool syncRunning=false;
|
||||
const int nb_slot_frame = UE->frame_parms.slots_per_frame;
|
||||
const int nb_slot_frame = fp->slots_per_frame;
|
||||
int absolute_slot=0, decoded_frame_rx=INT_MAX, trashed_frames=0;
|
||||
initNotifiedFIFO(&UE->phy_config_ind);
|
||||
|
||||
@@ -790,6 +922,12 @@ void *UE_thread(void *arg)
|
||||
initNotifiedFIFO(UE->tx_resume_ind_fifo[i]);
|
||||
}
|
||||
|
||||
if (get_nrUE_params()->sync_ref &&
|
||||
UE->sl_mode == 2) {
|
||||
UE->is_synchronized = 1;
|
||||
start_rx_stream = -1;
|
||||
}
|
||||
|
||||
while (!oai_exit) {
|
||||
|
||||
if (syncRunning) {
|
||||
@@ -798,7 +936,8 @@ void *UE_thread(void *arg)
|
||||
if (res) {
|
||||
syncRunning=false;
|
||||
if (UE->is_synchronized) {
|
||||
decoded_frame_rx = mac->mib_frame;
|
||||
if (UE->sl_mode == 2) decoded_frame_rx = UE->SL_UE_PHY_PARAMS.sync_params.DFN;
|
||||
else decoded_frame_rx = mac->mib_frame;
|
||||
LOG_I(PHY,"UE synchronized decoded_frame_rx=%d UE->init_sync_frame=%d trashed_frames=%d\n",
|
||||
decoded_frame_rx,
|
||||
UE->init_sync_frame,
|
||||
@@ -817,7 +956,7 @@ void *UE_thread(void *arg)
|
||||
}
|
||||
} else {
|
||||
readFrame(UE, ×tamp, true);
|
||||
trashed_frames+=2;
|
||||
trashed_frames+=((UE->sl_mode)?SL_NR_PSBCH_REPETITION_IN_FRAMES:2);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -843,21 +982,25 @@ void *UE_thread(void *arg)
|
||||
UE->rx_offset=0;
|
||||
UE->time_sync_cell=0;
|
||||
// read in first symbol
|
||||
AssertFatal (UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 ==
|
||||
AssertFatal (fp->ofdm_symbol_size+fp->nb_prefix_samples0 ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
×tamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0,
|
||||
UE->frame_parms.nb_antennas_rx),"");
|
||||
fp->ofdm_symbol_size+fp->nb_prefix_samples0,
|
||||
fp->nb_antennas_rx),"");
|
||||
|
||||
// we have the decoded frame index in the return of the synch process
|
||||
// and we shifted above to the first slot of next frame
|
||||
decoded_frame_rx++;
|
||||
// we do ++ first in the regular processing, so it will be begin of frame;
|
||||
absolute_slot = decoded_frame_rx * nb_slot_frame - 1;
|
||||
if (UE->sl_mode == 2) {
|
||||
//Set to the slot where the SL-SSB was decoded
|
||||
absolute_slot += UE->SL_UE_PHY_PARAMS.sync_params.slot_offset;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
absolute_slot++;
|
||||
|
||||
int slot_nr = absolute_slot % nb_slot_frame;
|
||||
@@ -868,24 +1011,58 @@ void *UE_thread(void *arg)
|
||||
curMsg.proc.nr_slot_tx = (absolute_slot + DURATION_RX_TO_TX) % nb_slot_frame;
|
||||
curMsg.proc.frame_rx = (absolute_slot / nb_slot_frame) % MAX_FRAME_NUMBER;
|
||||
curMsg.proc.frame_tx = ((absolute_slot + DURATION_RX_TO_TX) / nb_slot_frame) % MAX_FRAME_NUMBER;
|
||||
if (mac->phy_config_request_sent) {
|
||||
curMsg.proc.rx_slot_type = nr_ue_slot_select(cfg, curMsg.proc.frame_rx, curMsg.proc.nr_slot_rx);
|
||||
curMsg.proc.tx_slot_type = nr_ue_slot_select(cfg, curMsg.proc.frame_tx, curMsg.proc.nr_slot_tx);
|
||||
if (UE->phy_config_request_sent) {
|
||||
if (is_sidelink) {
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(UE->Mod_id);
|
||||
uint8_t pool_id = 0;
|
||||
// Temporarily setting this to this initial NON_NR_SIDELINK_SLOT slot type.
|
||||
// Later we should properly determine if the current slot is an NR_DOWNLINK_SLOT, NR_UPLINK_SLOT, or NR_MIXED_SLOT
|
||||
curMsg.proc.tx_slot_type = NON_NR_SIDELINK_SLOT;
|
||||
curMsg.proc.rx_slot_type = NON_NR_SIDELINK_SLOT;
|
||||
|
||||
SL_ResourcePool_params_t *sl_tx_rsrc_pool = mac->SL_MAC_PARAMS->sl_TxPool[pool_id];
|
||||
uint16_t phy_map_sz_tx = ((sl_tx_rsrc_pool->phy_sl_bitmap.size << 3) - sl_tx_rsrc_pool->phy_sl_bitmap.bits_unused);
|
||||
bool sl_tx_slot = is_sl_slot(mac, &sl_tx_rsrc_pool->phy_sl_bitmap, phy_map_sz_tx, absolute_slot + DURATION_RX_TO_TX);
|
||||
if (sl_tx_slot) {
|
||||
frameslot_t frame_slot_tx;
|
||||
frame_slot_tx.frame = curMsg.proc.frame_tx;
|
||||
frame_slot_tx.slot = curMsg.proc.nr_slot_tx;
|
||||
validate_selected_sl_slot(true , false, mac->SL_MAC_PARAMS->sl_TDD_config, frame_slot_tx);
|
||||
curMsg.proc.tx_slot_type = NR_SIDELINK_SLOT;
|
||||
}
|
||||
|
||||
SL_ResourcePool_params_t *sl_rx_rsrc_pool = mac->SL_MAC_PARAMS->sl_RxPool[pool_id];
|
||||
uint16_t phy_map_sz_rx = ((sl_rx_rsrc_pool->phy_sl_bitmap.size << 3) - sl_rx_rsrc_pool->phy_sl_bitmap.bits_unused);
|
||||
bool sl_rx_slot = is_sl_slot(mac, &sl_rx_rsrc_pool->phy_sl_bitmap, phy_map_sz_rx, absolute_slot);
|
||||
if (sl_rx_slot) {
|
||||
frameslot_t frame_slot_rx;
|
||||
frame_slot_rx.frame = curMsg.proc.frame_rx;
|
||||
frame_slot_rx.slot = curMsg.proc.nr_slot_rx;
|
||||
validate_selected_sl_slot(false , true, mac->SL_MAC_PARAMS->sl_TDD_config, frame_slot_rx);
|
||||
curMsg.proc.rx_slot_type = NR_SIDELINK_SLOT;
|
||||
}
|
||||
|
||||
LOG_D(NR_PHY,"Setting SL slot type to TX %d.%d %d, RX %d.%d %d\n",
|
||||
curMsg.proc.frame_tx, curMsg.proc.nr_slot_tx, curMsg.proc.tx_slot_type, curMsg.proc.frame_rx, curMsg.proc.nr_slot_rx, curMsg.proc.rx_slot_type);
|
||||
} else {
|
||||
curMsg.proc.rx_slot_type = nr_ue_slot_select(cfg, curMsg.proc.frame_rx, curMsg.proc.nr_slot_rx);
|
||||
curMsg.proc.tx_slot_type = nr_ue_slot_select(cfg, curMsg.proc.frame_tx, curMsg.proc.nr_slot_tx);
|
||||
}
|
||||
}
|
||||
else {
|
||||
curMsg.proc.rx_slot_type = NR_DOWNLINK_SLOT;
|
||||
curMsg.proc.tx_slot_type = NR_DOWNLINK_SLOT;
|
||||
}
|
||||
|
||||
int firstSymSamp = get_firstSymSamp(slot_nr, &UE->frame_parms);
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
|
||||
int firstSymSamp = get_firstSymSamp(slot_nr, fp);
|
||||
for (int i=0; i<fp->nb_antennas_rx; i++)
|
||||
rxp[i] = (void *)&UE->common_vars.rxdata[i][firstSymSamp+
|
||||
UE->frame_parms.get_samples_slot_timestamp(slot_nr,&UE->frame_parms,0)];
|
||||
fp->get_samples_slot_timestamp(slot_nr,fp,0)];
|
||||
|
||||
int readBlockSize, writeBlockSize;
|
||||
|
||||
readBlockSize = get_readBlockSize(slot_nr, &UE->frame_parms);
|
||||
writeBlockSize = UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX) % nb_slot_frame, &UE->frame_parms);
|
||||
readBlockSize = get_readBlockSize(slot_nr, fp);
|
||||
writeBlockSize = fp->get_samples_per_slot((slot_nr + DURATION_RX_TO_TX) % nb_slot_frame, fp);
|
||||
if (UE->apply_timing_offset && (slot_nr == nb_slot_frame - 1)) {
|
||||
const int sampShift = -(UE->rx_offset>>1);
|
||||
readBlockSize -= sampShift;
|
||||
@@ -898,11 +1075,11 @@ void *UE_thread(void *arg)
|
||||
×tamp,
|
||||
rxp,
|
||||
readBlockSize,
|
||||
UE->frame_parms.nb_antennas_rx),"");
|
||||
fp->nb_antennas_rx),"");
|
||||
|
||||
if(slot_nr == (nb_slot_frame - 1)) {
|
||||
// read in first symbol of next frame and adjust for timing drift
|
||||
int first_symbols = UE->frame_parms.ofdm_symbol_size + UE->frame_parms.nb_prefix_samples0; // first symbol of every frames
|
||||
int first_symbols = fp->ofdm_symbol_size + fp->nb_prefix_samples0; // first symbol of every frames
|
||||
|
||||
if (first_symbols > 0) {
|
||||
openair0_timestamp ignore_timestamp;
|
||||
@@ -911,14 +1088,14 @@ void *UE_thread(void *arg)
|
||||
&ignore_timestamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
first_symbols,
|
||||
UE->frame_parms.nb_antennas_rx),"");
|
||||
fp->nb_antennas_rx),"");
|
||||
} else
|
||||
LOG_E(PHY,"can't compensate: diff =%d\n", first_symbols);
|
||||
}
|
||||
|
||||
// use previous timing_advance value to compute writeTimestamp
|
||||
writeTimestamp = timestamp +
|
||||
UE->frame_parms.get_samples_slot_timestamp(slot_nr,&UE->frame_parms,DURATION_RX_TO_TX)
|
||||
fp->get_samples_slot_timestamp(slot_nr,fp,DURATION_RX_TO_TX)
|
||||
- firstSymSamp - openair0_cfg[0].tx_sample_advance -
|
||||
UE->N_TA_offset - timing_advance;
|
||||
|
||||
@@ -963,16 +1140,20 @@ void *UE_thread(void *arg)
|
||||
|
||||
void init_NR_UE(int nb_inst,
|
||||
char* uecap_file,
|
||||
char* rrc_config_path) {
|
||||
char* rrc_config_path,
|
||||
ueinfo_t* ueinfo) {
|
||||
int inst;
|
||||
NR_UE_MAC_INST_t *mac_inst;
|
||||
NR_UE_RRC_INST_t* rrc_inst;
|
||||
|
||||
|
||||
for (inst=0; inst < nb_inst; inst++) {
|
||||
AssertFatal((rrc_inst = nr_l3_init_ue(uecap_file,rrc_config_path)) != NULL, "can not initialize RRC module\n");
|
||||
AssertFatal((mac_inst = nr_l2_init_ue(rrc_inst)) != NULL, "can not initialize L2 module\n");
|
||||
AssertFatal((mac_inst = nr_l2_init_ue(rrc_inst, ueinfo)) != NULL, "can not initialize L2 module\n");
|
||||
AssertFatal((mac_inst->if_module = nr_ue_if_module_init(inst)) != NULL, "can not initialize IF module\n");
|
||||
}
|
||||
if (get_softmodem_params()->sl_mode) {
|
||||
configure_NR_SL_Preconfig(0, get_nrUE_params()->sync_ref);
|
||||
}
|
||||
}
|
||||
|
||||
void init_NR_UE_threads(int nb_inst) {
|
||||
|
||||
@@ -86,6 +86,7 @@ unsigned short config_frames[4] = {2,9,11,13};
|
||||
#include "nr_nas_msg_sim.h"
|
||||
#include <openair1/PHY/MODULATION/nr_modulation.h>
|
||||
#include "openair2/GNB_APP/gnb_paramdef.h"
|
||||
#include "openair2/RRC/NR_UE/sl_preconfig_paramvalues.h"
|
||||
|
||||
extern const char *duplex_mode[];
|
||||
THREAD_STRUCT thread_struct;
|
||||
@@ -117,6 +118,8 @@ static int tx_max_power[MAX_NUM_CCs] = {0};
|
||||
int single_thread_flag = 1;
|
||||
int tddflag = 0;
|
||||
int vcdflag = 0;
|
||||
int sl_nas_enabled = 0; //SLC Flag
|
||||
|
||||
|
||||
double rx_gain_off = 0.0;
|
||||
char *usrp_args = NULL;
|
||||
@@ -312,16 +315,18 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){
|
||||
|
||||
}
|
||||
|
||||
void init_openair0(void) {
|
||||
void init_openair0(bool is_sidelink) {
|
||||
int card;
|
||||
int freq_off = 0;
|
||||
NR_DL_FRAME_PARMS *frame_parms = &PHY_vars_UE_g[0][0]->frame_parms;
|
||||
if (is_sidelink)
|
||||
frame_parms = &PHY_vars_UE_g[0][0]->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
for (card=0; card<MAX_CARDS; card++) {
|
||||
uint64_t dl_carrier, ul_carrier, sl_carrier;
|
||||
uint64_t dl_carrier, ul_carrier;
|
||||
openair0_cfg[card].configFilename = NULL;
|
||||
openair0_cfg[card].threequarter_fs = frame_parms->threequarter_fs;
|
||||
openair0_cfg[card].sample_rate = frame_parms->samples_per_subframe * 1e3;
|
||||
openair0_cfg[card].sample_rate = IS_SOFTMODEM_RFSIM ? frame_parms->samples_per_subframe * 1e3 : 46080000;
|
||||
openair0_cfg[card].samples_per_frame = frame_parms->samples_per_frame;
|
||||
|
||||
if (frame_parms->frame_type==TDD)
|
||||
@@ -344,15 +349,14 @@ void init_openair0(void) {
|
||||
openair0_cfg[card].rx_num_channels,
|
||||
duplex_mode[openair0_cfg[card].duplex_mode]);
|
||||
|
||||
nr_get_carrier_frequencies(PHY_vars_UE_g[0][0], &dl_carrier, &ul_carrier);
|
||||
if (is_sidelink) {
|
||||
dl_carrier = frame_parms->dl_CarrierFreq;
|
||||
ul_carrier = frame_parms->ul_CarrierFreq;
|
||||
} else
|
||||
nr_get_carrier_frequencies(PHY_vars_UE_g[0][0], &dl_carrier, &ul_carrier);
|
||||
|
||||
nr_rf_card_config_freq(&openair0_cfg[card], ul_carrier, dl_carrier, freq_off);
|
||||
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
nr_get_carrier_frequencies_sl(PHY_vars_UE_g[0][0], &sl_carrier);
|
||||
nr_rf_card_config_freq(&openair0_cfg[card], sl_carrier, sl_carrier, freq_off);
|
||||
}
|
||||
|
||||
nr_rf_card_config_gain(&openair0_cfg[card], rx_gain_off);
|
||||
|
||||
openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file;
|
||||
@@ -447,7 +451,6 @@ int main( int argc, char **argv ) {
|
||||
// get options and fill parameters from configuration file
|
||||
|
||||
get_options (); //Command-line options specific for NRUE
|
||||
|
||||
get_common_options(SOFTMODEM_5GUE_BIT);
|
||||
CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
|
||||
#if T_TRACER
|
||||
@@ -472,17 +475,28 @@ int main( int argc, char **argv ) {
|
||||
#endif
|
||||
LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
|
||||
|
||||
init_NR_UE(1,uecap_file,rrc_config_path);
|
||||
ueinfo_t ueinfo;
|
||||
char aprefix[MAX_OPTNAME_SIZE*2 + 8];
|
||||
paramdef_t SL_UEINFO[] = SL_UEINFO_DESC(ueinfo);
|
||||
paramlist_def_t SL_UEINFOList = {SL_CONFIG_STRING_UEINFO, NULL, 0};
|
||||
sprintf(aprefix, "%s.[%d]", SL_CONFIG_STRING_SL_PRECONFIGURATION, 0);
|
||||
config_getlist(&SL_UEINFOList, NULL, 0, aprefix);
|
||||
sprintf(aprefix, "%s.[%i].%s.[%i]", SL_CONFIG_STRING_SL_PRECONFIGURATION, 0, SL_CONFIG_STRING_UEINFO, 0);
|
||||
config_get(SL_UEINFO, sizeof(SL_UEINFO)/sizeof(paramdef_t), aprefix);
|
||||
|
||||
init_NR_UE(1, uecap_file, rrc_config_path, &ueinfo);
|
||||
|
||||
int mode_offset = get_softmodem_params()->nsa ? NUMBER_OF_UE_MAX : 1;
|
||||
uint16_t node_number = get_softmodem_params()->node_number;
|
||||
ue_id_g = (node_number == 0) ? 0 : node_number - 2;
|
||||
AssertFatal(ue_id_g >= 0, "UE id is expected to be nonnegative.\n");
|
||||
|
||||
if(IS_SOFTMODEM_NOS1 || get_softmodem_params()->sa || get_softmodem_params()->nsa) {
|
||||
if(node_number == 0) {
|
||||
if(node_number == 0 && get_softmodem_params()->sl_mode == 0) {
|
||||
init_pdcp(0);
|
||||
}
|
||||
else {
|
||||
} else if (get_softmodem_params()->sl_mode == 2) {
|
||||
init_pdcp(1+ueinfo.srcid);
|
||||
} else {
|
||||
init_pdcp(mode_offset + ue_id_g);
|
||||
}
|
||||
}
|
||||
@@ -522,7 +536,7 @@ int main( int argc, char **argv ) {
|
||||
get_softmodem_params()->numerology,
|
||||
nr_band);
|
||||
}
|
||||
else{
|
||||
else if (get_softmodem_params()->sl_mode != 2){
|
||||
DevAssert(mac->if_module != NULL && mac->if_module->phy_config_request != NULL);
|
||||
mac->if_module->phy_config_request(&mac->phy_config);
|
||||
mac->phy_config_request_sent = true;
|
||||
@@ -532,10 +546,34 @@ int main( int argc, char **argv ) {
|
||||
*mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]);
|
||||
}
|
||||
|
||||
UE[CC_id]->sl_mode = get_softmodem_params()->sl_mode;
|
||||
|
||||
if (UE[CC_id]->sl_mode) {
|
||||
AssertFatal(UE[CC_id]->sl_mode == 2, "Only Sidelink mode 2 supported. Mode 1 not yet supported\n");
|
||||
// starting the sockets between the PC5 Controller and the RRC and the PDCP
|
||||
//nr_rrc_pc5_control_socket_init();
|
||||
if (sl_nas_enabled) {
|
||||
nr_rrc_pc5_control_socket_init();
|
||||
LOG_I(RRC, "[SL-NAS] PC5 controller socket started\n");
|
||||
} else {
|
||||
LOG_I(RRC, "[SL-NAS] PC5 controller socket not started\n");
|
||||
}
|
||||
nr_pdcp_pc5_signaling_socket_init();
|
||||
//
|
||||
nr_UE_configure_Sidelink(0, get_nrUE_params()->sync_ref, &ueinfo);
|
||||
DevAssert(mac->if_module != NULL && mac->if_module->sl_phy_config_request != NULL);
|
||||
sl_nr_ue_phy_params_t *sl_phy = &UE[CC_id]->SL_UE_PHY_PARAMS;
|
||||
mac->if_module->sl_phy_config_request(&mac->SL_MAC_PARAMS->sl_phy_config);
|
||||
nr_init_frame_parms_ue_sl(&sl_phy->sl_frame_params,&sl_phy->sl_config,
|
||||
get_nrUE_params()->threequarter_fs,
|
||||
get_nrUE_params()->ofdm_offset_divisor);
|
||||
}
|
||||
init_nr_ue_vars(UE[CC_id], 0, abstraction_flag);
|
||||
}
|
||||
|
||||
init_openair0();
|
||||
bool is_sl = (get_softmodem_params()->sl_mode) ? 1 : 0;
|
||||
|
||||
init_openair0(is_sl);
|
||||
// init UE_PF_PO and mutex lock
|
||||
pthread_mutex_init(&ue_pf_po_mutex, NULL);
|
||||
memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*NUMBER_OF_UE_MAX*MAX_NUM_CCs);
|
||||
|
||||
@@ -5,13 +5,20 @@
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "SIMULATION/ETH_TRANSPORT/proto.h"
|
||||
|
||||
|
||||
typedef struct ueinfo {
|
||||
int srcid;
|
||||
int thirdOctet;
|
||||
int fourthOctet;
|
||||
} ueinfo_t;
|
||||
|
||||
#define CONFIG_HLP_IF_FREQ "IF frequency for RF, if needed\n"
|
||||
#define CONFIG_HLP_IF_FREQ_OFF "UL IF frequency offset for RF, if needed\n"
|
||||
#define CONFIG_HLP_DLSCH_PARA "number of threads for dlsch processing 0 for no parallelization\n"
|
||||
#define CONFIG_HLP_OFFSET_DIV "Divisor for computing OFDM symbol offset in Rx chain (num samples in CP/<the value>). Default value is 8. To set the sample offset to 0, set this value ~ 10e6\n"
|
||||
#define CONFIG_HLP_MAX_LDPC_ITERATIONS "Maximum LDPC decoder iterations\n"
|
||||
#define CONFIG_HLP_SL_SYNCSOURCEUE "Sidelink UE acts as SYNC REF UE"
|
||||
#define CONFIG_HLP_SL_MAX_MCS "Sidelink initial max mcs value"
|
||||
#define CONFIG_HLP_SL_SNR "Sets sidelink SNR value"
|
||||
/***************************************************************************************************************************************/
|
||||
/* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument
|
||||
when calling config_get or config_getlist functions */
|
||||
@@ -24,6 +31,7 @@
|
||||
#define CALIBPRACH_OPT "calib-prach-tx"
|
||||
#define DUMPFRAME_OPT "ue-dump-frame"
|
||||
|
||||
#define SL_UE_iterator(BaSe, VaR) NR_SL_UE_info_t ** VaR##pptr=BaSe, *VaR; while ((VaR=*(VaR##pptr++)))
|
||||
/*------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* command line parameters defining UE running mode */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
@@ -61,6 +69,10 @@
|
||||
{"chest-time", CONFIG_HLP_CHESTTIME, 0, .iptr=&(nrUE_params.chest_time), .defintval=0, TYPE_INT, 0}, \
|
||||
{"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, .iptr=&(nrUE_params.no_timing_correction), .defintval=0, TYPE_INT, 0}, \
|
||||
{"SLC", CONFIG_HLP_SLF, 0, .u64ptr=&(sidelink_frequency[0][0]), .defuintval=2600000000,TYPE_UINT64,0}, \
|
||||
{"sync-ref", CONFIG_HLP_SL_SYNCSOURCEUE, PARAMFLAG_BOOL, .uptr=&(nrUE_params.sync_ref), .defuintval=0, TYPE_UINT32, 0}, \
|
||||
{"sl-nas", "Enable SL-NAS PC5 controller socket\n", PARAMFLAG_BOOL, .iptr=&sl_nas_enabled, .defintval=0, TYPE_INT, 0}, \
|
||||
{"mcs", CONFIG_HLP_SL_MAX_MCS, 0, .u8ptr=&(nrUE_params.mcs), .defintval=9, TYPE_UINT8, 0}, \
|
||||
{"snr", CONFIG_HLP_SL_SNR, 0, .dblptr=&(nrUE_params.snr), .defdblval=0.0, TYPE_DOUBLE, 0}, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
@@ -82,6 +94,9 @@ typedef struct {
|
||||
int threequarter_fs;
|
||||
int N_RB_DL;
|
||||
int ssb_start_subcarrier;
|
||||
uint32_t sync_ref;
|
||||
uint8_t mcs;
|
||||
double snr;
|
||||
} nrUE_params_t;
|
||||
extern uint64_t get_nrUE_optmask(void);
|
||||
extern uint64_t set_nrUE_optmask(uint64_t bitmask);
|
||||
@@ -91,7 +106,7 @@ extern nrUE_params_t *get_nrUE_params(void);
|
||||
// In nr-ue.c
|
||||
extern int setup_nr_ue_buffers(PHY_VARS_NR_UE **phy_vars_ue, openair0_config_t *openair0_cfg);
|
||||
extern void fill_ue_band_info(void);
|
||||
extern void init_NR_UE(int, char*, char*);
|
||||
extern void init_NR_UE(int, char*, char*, ueinfo_t*);
|
||||
extern void init_NR_UE_threads(int);
|
||||
extern void reset_opp_meas(void);
|
||||
extern void print_opp_meas(void);
|
||||
@@ -99,4 +114,6 @@ 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);
|
||||
|
||||
extern int sl_nas_enabled; //SLC Flag
|
||||
#endif
|
||||
|
||||
@@ -119,6 +119,8 @@ typedef struct {
|
||||
typedef struct {
|
||||
uint8_t harq_pid;
|
||||
uint8_t ack_nack;
|
||||
uint8_t *ack_nack_rcvd;
|
||||
uint8_t num_acks_rcvd;
|
||||
uint32_t pdu_length;
|
||||
uint8_t* pdu;
|
||||
} fapi_nr_pdsch_pdu_t;
|
||||
|
||||
@@ -942,6 +942,7 @@ typedef struct
|
||||
uint16_t scramb_id; // ScramblingID of the CSI-RS [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->1023
|
||||
uint8_t power_control_offset; // Ratio of PDSCH EPRE to NZP CSI-RSEPRE [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->23 representing -8 to 15 dB in 1dB steps; 255: L1 is configured with ProfileSSS
|
||||
uint8_t power_control_offset_ss; // Ratio of NZP CSI-RS EPRE to SSB/PBCH block EPRE [3GPP TS 38.214, sec 5.2.2.3.1], Values: 0: -3dB; 1: 0dB; 2: 3dB; 3: 6dB; 255: L1 is configured with ProfileSSS
|
||||
uint8_t measurement_bitmap;
|
||||
} nfapi_nr_dl_tti_csi_rs_pdu_rel15_t;
|
||||
|
||||
|
||||
|
||||
@@ -4,12 +4,31 @@
|
||||
#include "fapi_nr_ue_interface.h"
|
||||
|
||||
#define SL_NR_RX_CONFIG_LIST_NUM 1
|
||||
#define SL_NR_TX_CONFIG_LIST_NUM 1
|
||||
#define SL_NR_RX_IND_MAX_PDU 1
|
||||
#define SL_NR_TX_CONFIG_LIST_NUM 1 //Jin original 1, change to 2
|
||||
#define SL_NR_RX_IND_MAX_PDU 2
|
||||
#define SL_NR_SCI_IND_MAX_PDU 2
|
||||
#define SL_NR_MAX_PSCCH_SCI_LENGTH_IN_BYTES 8
|
||||
#define SL_NR_MAX_PSSCH_SCI_LENGTH_IN_BYTES 8
|
||||
#define SL_NR_MAX_SCI_LENGTH_IN_BYTES 8
|
||||
|
||||
typedef struct sl_nr_tti_csi_rs_pdu {
|
||||
uint8_t subcarrier_spacing; // subcarrierSpacing [3GPP TS 38.211, sec 4.2], Value:0->4
|
||||
uint8_t cyclic_prefix; // Cyclic prefix type [3GPP TS 38.211, sec 4.2], 0: Normal; 1: Extended
|
||||
uint16_t start_rb; // PRB where this CSI resource starts related to common resource block #0 (CRB#0). Only multiples of 4 are allowed. [3GPP TS 38.331, sec 6.3.2 parameter CSIFrequencyOccupation], Value: 0 ->274
|
||||
uint16_t nr_of_rbs; // Number of PRBs across which this CSI resource spans. Only multiples of 4 are allowed. [3GPP TS 38.331, sec 6.3.2 parameter CSI-FrequencyOccupation], Value: 24 -> 276
|
||||
uint8_t csi_type; // CSI Type [3GPP TS 38.211, sec 7.4.1.5], Value: 0:TRS; 1:CSI-RS NZP; 2:CSI-RS ZP
|
||||
uint8_t row; // Row entry into the CSI Resource location table. [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 1-18
|
||||
uint16_t freq_domain; // Bitmap defining the frequencyDomainAllocation [3GPP TS 38.211, sec 7.4.1.5.3] [3GPP TS 38.331 CSIResourceMapping], Value: Up to the 12 LSBs, actual size is determined by the Row parameter
|
||||
uint8_t symb_l0; // The time domain location l0 and firstOFDMSymbolInTimeDomain [3GPP TS 38.211, sec 7.4.1.5.3], Value: 0->13
|
||||
uint8_t symb_l1; // The time domain location l1 and firstOFDMSymbolInTimeDomain2 [3GPP TS 38.211, sec 7.4.1.5.3], Value: 2->12
|
||||
uint8_t cdm_type; // The cdm-Type field [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 0: noCDM; 1: fd-CDM2; 2: cdm4-FD2-TD2; 3: cdm8-FD2-TD4
|
||||
uint8_t freq_density; // The density field, p and comb offset (for dot5). [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 0: dot5 (even RB); 1: dot5 (odd RB); 2: one; 3: three
|
||||
uint16_t scramb_id; // ScramblingID of the CSI-RS [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->1023
|
||||
uint8_t power_control_offset; // Ratio of PDSCH EPRE to NZP CSI-RSEPRE [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->23 representing -8 to 15 dB in 1dB steps; 255: L1 is configured with ProfileSSS
|
||||
uint8_t power_control_offset_ss; // Ratio of NZP CSI-RS EPRE to SSB/PBCH block EPRE [3GPP TS 38.214, sec 5.2.2.3.1], Values: 0: -3dB; 1: 0dB; 2: 3dB; 3: 6dB; 255: L1 is configured with ProfileSSS
|
||||
uint8_t measurement_bitmap; // bit 0 RSRP, bit 1 RI, bit 2 LI, bit 3 PMI, bit 4 CQI, bit 5 i1
|
||||
} sl_nr_tti_csi_rs_pdu_t;
|
||||
|
||||
typedef enum sl_sci_format_type_enum {
|
||||
SL_SCI_INVALID_FORMAT,
|
||||
SL_SCI_FORMAT_1A_ON_PSCCH,
|
||||
@@ -20,7 +39,8 @@ typedef enum sl_sci_format_type_enum {
|
||||
typedef enum sl_rx_pdu_type_enum {
|
||||
SL_NR_RX_PDU_TYPE_NONE,
|
||||
SL_NR_RX_PDU_TYPE_SSB,
|
||||
SL_NR_RX_PDU_TYPE_SLSCH
|
||||
SL_NR_RX_PDU_TYPE_SLSCH,
|
||||
SL_NR_RX_PDU_TYPE_SLSCH_PSFCH,
|
||||
} sl_rx_pdu_type_enum_t;
|
||||
|
||||
//Type of SL-RX CONFIG requests from MAC to PHY
|
||||
@@ -29,6 +49,8 @@ typedef enum sl_nr_rx_config_type_enum {
|
||||
SL_NR_CONFIG_TYPE_RX_PSCCH,
|
||||
SL_NR_CONFIG_TYPE_RX_PSSCH_SCI,
|
||||
SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH,
|
||||
SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_PSFCH,
|
||||
SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_CSI_RS,
|
||||
SL_NR_CONFIG_TYPE_RX_MAXIMUM
|
||||
} sl_nr_rx_config_type_enum_t;
|
||||
|
||||
@@ -36,7 +58,8 @@ typedef enum sl_nr_rx_config_type_enum {
|
||||
typedef enum sl_nr_tx_config_type_enum {
|
||||
SL_NR_CONFIG_TYPE_TX_PSBCH = SL_NR_CONFIG_TYPE_RX_MAXIMUM + 1,
|
||||
SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH,
|
||||
SL_NR_CONFIG_TYPE_TX_PSFCH,
|
||||
SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH,
|
||||
SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS,
|
||||
SL_NR_CONFIG_TYPE_TX_MAXIMUM
|
||||
} sl_nr_tx_config_type_enum_t;
|
||||
|
||||
@@ -68,7 +91,7 @@ typedef struct {
|
||||
uint8_t sensing_result;
|
||||
//in case pssch sensing is requested.
|
||||
int16_t pssch_rsrp;
|
||||
sl_nr_sci_indication_pdu_t sci_pdu;
|
||||
sl_nr_sci_indication_pdu_t sci_pdu[SL_NR_SCI_IND_MAX_PDU];
|
||||
} sl_nr_sci_indication_t;
|
||||
|
||||
// IF UE Rx PSBCH, PHY indicates MAC with received MIB and PSBCH RSRP
|
||||
@@ -190,6 +213,22 @@ typedef struct sl_nr_rx_config_pssch_pdu {
|
||||
uint8_t ndi;
|
||||
} sl_nr_rx_config_pssch_pdu_t;
|
||||
|
||||
typedef struct sl_nr_tx_rx_config_psfch_pdu {
|
||||
// These fields can be mapped directly to the same fields in nfapi_nr_ul_config_pucch_pdu
|
||||
uint8_t freq_hop_flag;
|
||||
uint8_t group_hop_flag;
|
||||
uint8_t sequence_hop_flag;
|
||||
uint16_t second_hop_prb;
|
||||
uint8_t nr_of_symbols;
|
||||
uint8_t start_symbol_index;
|
||||
uint8_t hopping_id;
|
||||
uint16_t prb;
|
||||
uint16_t sl_bwp_start;
|
||||
uint16_t initial_cyclic_shift;
|
||||
uint8_t mcs;
|
||||
uint8_t bit_len_harq;
|
||||
} sl_nr_tx_rx_config_psfch_pdu_t;
|
||||
|
||||
typedef struct {
|
||||
sl_nr_rx_config_type_enum_t pdu_type; // indicates the type of RX config request
|
||||
union {
|
||||
@@ -197,6 +236,9 @@ typedef struct {
|
||||
sl_nr_rx_config_pssch_sci_pdu_t rx_sci2_config_pdu;
|
||||
sl_nr_rx_config_pssch_pdu_t rx_pssch_config_pdu;
|
||||
};
|
||||
sl_nr_tti_csi_rs_pdu_t rx_csi_rs_config_pdu;
|
||||
sl_nr_tx_rx_config_psfch_pdu_t *rx_psfch_pdu_list;
|
||||
uint16_t num_psfch_pdus;
|
||||
} sl_nr_rx_config_request_pdu_t;
|
||||
|
||||
// MAC commands PHY to perform an action on RX RESOURCE POOL or RX PSBCH using this RX CONFIG
|
||||
@@ -243,6 +285,9 @@ typedef struct sl_nr_tx_config_pscch_pssch_pdu {
|
||||
//Indicates the number of symbols for PSCCH+PSSCH txn
|
||||
uint8_t pssch_numsym;
|
||||
|
||||
// start symbol of PSCCH/PSSCH (excluding AGC)
|
||||
uint8_t pssch_startsym;
|
||||
|
||||
//.... Other Parameters for SCI-2 and PSSCH
|
||||
|
||||
// Used to determine number of SCI2 modulated symbols
|
||||
@@ -265,14 +310,21 @@ typedef struct sl_nr_tx_config_pscch_pssch_pdu {
|
||||
// Table from SPEC 38.211, Table 8.4.1.1.2-1
|
||||
uint16_t dmrs_symbol_position;
|
||||
|
||||
|
||||
// PSFCH related parameters
|
||||
sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu_list;
|
||||
uint16_t num_psfch_pdus;
|
||||
//....TBD.. any additional parameters
|
||||
|
||||
// CSI-RS related parameters
|
||||
sl_nr_tti_csi_rs_pdu_t nr_sl_csi_rs_pdu;
|
||||
|
||||
//TX Power for PSSCH in symbol without PSCCH.
|
||||
// Power for PSCCH and power for PSSCH in symbol with PSCCH is calculated
|
||||
// from this value according to 38.213 section 16
|
||||
int16_t pssch_tx_power;
|
||||
|
||||
uint16_t slsch_payload_length;
|
||||
uint8_t *slsch_payload;
|
||||
} sl_nr_tx_config_pscch_pssch_pdu_t;
|
||||
|
||||
// MAC indicates PHY to send PSBCH.
|
||||
@@ -351,7 +403,7 @@ typedef struct
|
||||
uint16_t sl_bandwidth;
|
||||
//Absolute frequency of SL point A in KHz
|
||||
//n38 (2570-2620 Mhz), n47 (5855-5925 Mhz) are defined.
|
||||
uint32_t sl_frequency;
|
||||
uint64_t sl_frequency;
|
||||
|
||||
//Only 1 SCS-SpecificCarrier allowed for NR-SL communication
|
||||
uint16_t sl_grid_size;// bandwidth for each numerology
|
||||
@@ -363,7 +415,7 @@ typedef struct
|
||||
uint8_t sl_frequency_shift_7p5khz;
|
||||
//Indicates presence of +/-5Khz shift wrt FREF for V2X reference frequencies.
|
||||
//Possible values: {-1,0,1}
|
||||
uint8_t sl_value_N;
|
||||
int8_t sl_value_N;
|
||||
|
||||
} sl_nr_carrier_config_t;
|
||||
|
||||
@@ -382,7 +434,26 @@ typedef struct {
|
||||
//only 1 SL-BWP can be configured in REL16, REL17
|
||||
sl_nr_bwp_config_t sl_bwp_config;
|
||||
|
||||
uint32_t sl_DMRS_ScrambleId;
|
||||
|
||||
} sl_nr_phy_config_request_t;
|
||||
|
||||
/* Dependencies */
|
||||
typedef enum NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR {
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_NOTHING, /* No components present */
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots4,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots5,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots8,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots10,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots16,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots20,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots32,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots40,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots64,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots80,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots160,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots320,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots640
|
||||
} NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -339,6 +339,10 @@ int check_crc(uint8_t* decoded_bytes, uint32_t n, uint8_t crc_type)
|
||||
for (int i=0; i<crc_len; i++)
|
||||
oldcrc |= (decoded_bytes[(n>>3)-crc_len+i])<<((crc_len-1-i)<<3);
|
||||
|
||||
if (oldcrc == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (crc_type) {
|
||||
|
||||
case CRC24_A:
|
||||
|
||||
@@ -451,11 +451,15 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
|
||||
// Parity Check not necessary here since it will fail
|
||||
// because first 2 cols/BNs in BG are punctured and cannot be
|
||||
// estimated after only one iteration
|
||||
// Added 2 to numMaxIter to execute ldpc process five times (max. iterations);
|
||||
// it is skipping first two iterations so, previously, it was iterating only three times
|
||||
// In case of check_crc() pass, we subtracted 2 to consider upto 7 iterations (worst case) only; in case of iteration 8,
|
||||
// it will still consider the ldpc decoding as abort
|
||||
|
||||
// First iteration finished
|
||||
uint32_t numIter = 1;
|
||||
int32_t pcRes = 1; // pcRes is 0 if the ldpc decoder is succesful
|
||||
while ((numIter <= numMaxIter) && (pcRes != 0)) {
|
||||
while ((numIter <= numMaxIter + 2) && (pcRes != 0)) {
|
||||
// Increase iteration counter
|
||||
numIter++;
|
||||
if (check_abort(ab)) {
|
||||
@@ -713,6 +717,7 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
|
||||
nrLDPC_llr2bit(p_out, p_llrOut, numLLR);
|
||||
if (check_crc((uint8_t*)p_out, p_decParams->block_length, p_decParams->crc_type)) {
|
||||
LOG_D(PHY, "Segment CRC OK, exiting LDPC decoder\n");
|
||||
numIter -= 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
#define __NR_POLAR_DCI_DEFS__H__
|
||||
|
||||
#define NR_POLAR_DCI_MESSAGE_TYPE 1 //int8_t
|
||||
#define NR_POLAR_SCI_MESSAGE_TYPE (NR_POLAR_PSBCH_MESSAGE_TYPE + 1) //int8_t
|
||||
#define NR_POLAR_SCI2_MESSAGE_TYPE (NR_POLAR_SCI_MESSAGE_TYPE + 1) //int8_t
|
||||
#define NR_POLAR_DCI_CRC_PARITY_BITS 24
|
||||
#define NR_POLAR_DCI_CRC_ERROR_CORRECTION_BITS 3
|
||||
|
||||
|
||||
@@ -607,6 +607,7 @@ void init_polar_deinterleaver_table(t_nrPolar_params *polarParams) {
|
||||
|
||||
uint32_t polar_decoder_int16(int16_t *input,
|
||||
uint64_t *out,
|
||||
uint16_t *nid,
|
||||
uint8_t ones_flag,
|
||||
int8_t messageType,
|
||||
uint16_t messageLength,
|
||||
@@ -615,7 +616,7 @@ uint32_t polar_decoder_int16(int16_t *input,
|
||||
t_nrPolar_params *polarParams=nr_polar_params(messageType, messageLength, aggregation_level, true);
|
||||
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
printf("\nRX\n");
|
||||
printf("\nRX N %d (messageType %d messageLength %d aggregation_level %d)\n",polarParams->N,messageType,messageLength,aggregation_level);
|
||||
printf("rm:");
|
||||
for (int i = 0; i < polarParams->N; i++) {
|
||||
if (i % 4 == 0) {
|
||||
@@ -794,5 +795,6 @@ uint32_t polar_decoder_int16(int16_t *input,
|
||||
#endif
|
||||
out[0]=Ar;
|
||||
|
||||
if (nid) *nid=crc&65535;
|
||||
polarReturn crc^rxcrc;
|
||||
}
|
||||
|
||||
@@ -153,6 +153,7 @@ void polar_encoder_dci(uint32_t *in,
|
||||
|
||||
void polar_encoder_fast(uint64_t *A,
|
||||
void *out,
|
||||
uint32_t *crc,
|
||||
int32_t crcmask,
|
||||
uint8_t ones_flag,
|
||||
int8_t messageType,
|
||||
@@ -168,6 +169,7 @@ int8_t polar_decoder(double *input,
|
||||
|
||||
uint32_t polar_decoder_int16(int16_t *input,
|
||||
uint64_t *out,
|
||||
uint16_t *nid,
|
||||
uint8_t ones_flag,
|
||||
int8_t messageType,
|
||||
uint16_t messageLength,
|
||||
|
||||
@@ -304,6 +304,7 @@ void nr_polar_rm_interleaving_cb(void *in, void *out, uint16_t E)
|
||||
static inline void polar_rate_matching(const t_nrPolar_params *polarParams,void *in,void *out) __attribute__((always_inline));
|
||||
|
||||
static inline void polar_rate_matching(const t_nrPolar_params *polarParams,void *in,void *out) {
|
||||
int i = 0;
|
||||
|
||||
// handle rate matching with a single 128 bit word using bit shuffling
|
||||
// can be done with SIMD intrisics if needed
|
||||
@@ -343,15 +344,20 @@ static inline void polar_rate_matching(const t_nrPolar_params *polarParams,void
|
||||
}
|
||||
// These are based on LUTs for byte and short word groups
|
||||
else if (polarParams->groupsize == 8)
|
||||
for (int i=0; i<polarParams->encoderLength>>3; i++) ((uint8_t *)out)[i] = ((uint8_t *)in)[polarParams->rm_tab[i]];
|
||||
for (i=0; i<polarParams->encoderLength>>3; i++) ((uint8_t *)out)[i] = ((uint8_t *)in)[polarParams->rm_tab[i]];
|
||||
else // groupsize==16
|
||||
for (int i=0; i<polarParams->encoderLength>>4; i++) {
|
||||
for (i=0; i<polarParams->encoderLength>>4; i++) {
|
||||
((uint16_t *)out)[i] = ((uint16_t *)in)[polarParams->rm_tab[i]];
|
||||
}
|
||||
|
||||
if (polarParams->i_bil == 1) {
|
||||
nr_polar_rm_interleaving_cb(out, out, polarParams->encoderLength);
|
||||
}
|
||||
// handle remaining bits which do not fill a full group
|
||||
for(i=i*polarParams->groupsize; i<polarParams->encoderLength; i++) {
|
||||
uint8_t pi = polarParams->rate_matching_pattern[i];
|
||||
((uint8_t *)out)[i>>3] |= ( ((((uint8_t *)in)[pi >> 3] >> (pi & 7)) & 1) << (i&7));
|
||||
}
|
||||
}
|
||||
|
||||
void build_polar_tables(t_nrPolar_params *polarParams) {
|
||||
@@ -448,8 +454,8 @@ void build_polar_tables(t_nrPolar_params *polarParams) {
|
||||
}
|
||||
#ifdef DEBUG_POLAR_ENCODER
|
||||
groupcnt++;
|
||||
#endif
|
||||
if ((ccnt+1)<mingroupsize) mingroupsize=ccnt+1;
|
||||
#endif
|
||||
//if ((ccnt+1)<mingroupsize) mingroupsize=ccnt+1;
|
||||
#ifdef DEBUG_POLAR_ENCODER
|
||||
printf("group %d (size %d): (%d:%d) => (%d:%d)\n",groupcnt,ccnt+1,
|
||||
firstingroup_in,firstingroup_in+ccnt,
|
||||
@@ -477,8 +483,7 @@ void build_polar_tables(t_nrPolar_params *polarParams) {
|
||||
break;
|
||||
}
|
||||
|
||||
polarParams->rm_tab = (int *)malloc(sizeof(int) * (polarParams->encoderLength >> shift));
|
||||
|
||||
polarParams->rm_tab=(int *)malloc(sizeof(int)*((polarParams->encoderLength+mingroupsize-1)/mingroupsize));
|
||||
// rerun again to create groups
|
||||
int tcnt = 0;
|
||||
for (int outpos = 0; outpos < polarParams->encoderLength; outpos += mingroupsize, tcnt++)
|
||||
@@ -487,6 +492,7 @@ void build_polar_tables(t_nrPolar_params *polarParams) {
|
||||
|
||||
void polar_encoder_fast(uint64_t *A,
|
||||
void *out,
|
||||
uint32_t *crc,
|
||||
int32_t crcmask,
|
||||
uint8_t ones_flag,
|
||||
int8_t messageType,
|
||||
@@ -599,7 +605,7 @@ void polar_encoder_fast(uint64_t *A,
|
||||
else if (polarParams->crcParityBits == 11)
|
||||
tcrc = (uint64_t)((crcmask^(crc11(A128_flip,bitlen)>>21)))&0x7ff;
|
||||
}
|
||||
|
||||
if (crc) *crc = (uint32_t)tcrc;
|
||||
// this is number of quadwords in the bit string
|
||||
int quadwlen = (polarParams->K+63)/64;
|
||||
|
||||
@@ -707,11 +713,12 @@ void polar_encoder_fast(uint64_t *A,
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
memset((void*)out,0,polarParams->encoderLength>>3);
|
||||
memset((void*)out,0,(polarParams->encoderLength + 7)>>3);
|
||||
polar_rate_matching(polarParams,(void *)D, out);
|
||||
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
uint64_t *out64 = (uint64_t *)out;
|
||||
printf("N %d, encoderLength %d\n",polarParams->N,polarParams->encoderLength);
|
||||
printf("rm:");
|
||||
for (int n = 0; n < polarParams->encoderLength; n++) {
|
||||
if (n % 4 == 0) {
|
||||
|
||||
57
openair1/PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h
Normal file
57
openair1/PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 /PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h
|
||||
\brief Polar definitions required for Sidelink PSBCH
|
||||
\author
|
||||
\date
|
||||
\version
|
||||
\company: Fraunhofer
|
||||
\email:
|
||||
\note
|
||||
\warning
|
||||
*/
|
||||
|
||||
#ifndef __NR_POLAR_PSBCH_DEFS__H__
|
||||
#define __NR_POLAR_PSBCH_DEFS__H__
|
||||
|
||||
//PSBCH related polar parameters.
|
||||
|
||||
//PSBCH symbols sent in 11RBS, 9 symbols. 11*9*(12-3(for DMRS))*2bits = 1782 bits
|
||||
#define SL_NR_POLAR_PSBCH_E_NORMAL_CP 1782
|
||||
//PSBCH symbols sent in 11RBS, 7 symbols. 11*7*(12-3(for DMRS))*2bits = 1386 bits
|
||||
#define SL_NR_POLAR_PSBCH_E_EXT_CP 1386
|
||||
// SL_NR_POLAR_PSBCH_E_NORMAL_CP/32
|
||||
#define SL_NR_POLAR_PSBCH_E_DWORD 56
|
||||
|
||||
#define SL_NR_POLAR_PSBCH_MESSAGE_TYPE (NR_POLAR_UCI_PUCCH_MESSAGE_TYPE + 1)
|
||||
#define SL_NR_POLAR_PSBCH_PAYLOAD_BITS 32
|
||||
#define SL_NR_POLAR_PSBCH_AGGREGATION_LEVEL 0
|
||||
#define SL_NR_POLAR_PSBCH_N_MAX 9
|
||||
#define SL_NR_POLAR_PSBCH_I_IL 1
|
||||
#define SL_NR_POLAR_PSBCH_I_SEG 0
|
||||
#define SL_NR_POLAR_PSBCH_N_PC 0
|
||||
#define SL_NR_POLAR_PSBCH_N_PC_WM 0
|
||||
#define SL_NR_POLAR_PSBCH_I_BIL 0
|
||||
#define SL_NR_POLAR_PSBCH_CRC_PARITY_BITS 24
|
||||
#define SL_NR_POLAR_PSBCH_CRC_ERROR_CORRECTION_BITS 3
|
||||
|
||||
#endif
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_dci.h"
|
||||
#include "nrPolar_tools/nr_polar_psbch_defs.h"
|
||||
|
||||
#define PolarKey ((messageType<<24)|(messageLength<<8)|aggregation_level)
|
||||
static t_nrPolar_params * PolarList=NULL;
|
||||
@@ -98,7 +99,7 @@ t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, ui
|
||||
//Parse the list. If the node is already created, return without initialization.
|
||||
while (currentPtr != NULL) {
|
||||
//printf("currentPtr->idx %d, (%d,%d)\n",currentPtr->idx,currentPtr->payloadBits,currentPtr->encoderLength);
|
||||
//LOG_D(PHY,"Looking for index %d\n",(messageType * messageLength * aggregation_prime));
|
||||
LOG_D(NR_PHY,"Looking for index %d\n",(messageType * messageLength * aggregation_level));
|
||||
if (currentPtr->busy == false && currentPtr->idx == PolarKey ) {
|
||||
currentPtr->busy=true;
|
||||
pthread_mutex_unlock(&PolarListMutex);
|
||||
@@ -194,7 +195,39 @@ t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, ui
|
||||
newPolarInitNode->payloadBits = messageLength;
|
||||
newPolarInitNode->crcCorrectionBits = NR_POLAR_PUCCH_CRC_ERROR_CORRECTION_BITS;
|
||||
//LOG_D(PHY,"New polar node, encoderLength %d, aggregation_level %d\n",newPolarInitNode->encoderLength,aggregation_level);
|
||||
} else if (messageType == SL_NR_POLAR_PSBCH_MESSAGE_TYPE) { //PSBCH
|
||||
newPolarInitNode->n_max = SL_NR_POLAR_PSBCH_N_MAX;
|
||||
newPolarInitNode->i_il = SL_NR_POLAR_PSBCH_I_IL;
|
||||
newPolarInitNode->i_seg = SL_NR_POLAR_PSBCH_I_SEG;
|
||||
newPolarInitNode->n_pc = SL_NR_POLAR_PSBCH_N_PC;
|
||||
newPolarInitNode->n_pc_wm = SL_NR_POLAR_PSBCH_N_PC_WM;
|
||||
newPolarInitNode->i_bil = SL_NR_POLAR_PSBCH_I_BIL;
|
||||
newPolarInitNode->crcParityBits = SL_NR_POLAR_PSBCH_CRC_PARITY_BITS;
|
||||
newPolarInitNode->payloadBits = SL_NR_POLAR_PSBCH_PAYLOAD_BITS;
|
||||
newPolarInitNode->encoderLength = SL_NR_POLAR_PSBCH_E_NORMAL_CP;
|
||||
newPolarInitNode->crcCorrectionBits = SL_NR_POLAR_PSBCH_CRC_ERROR_CORRECTION_BITS;
|
||||
newPolarInitNode->crc_generator_matrix = crc24c_generator_matrix(newPolarInitNode->payloadBits);//G_P
|
||||
LOG_D(PHY,"SIDELINK: Initializing polar parameters for PSBCH (K %d, E %d)\n",newPolarInitNode->payloadBits,newPolarInitNode->encoderLength);
|
||||
} else if (messageType == NR_POLAR_DCI_MESSAGE_TYPE || messageType == NR_POLAR_SCI_MESSAGE_TYPE || messageType == NR_POLAR_SCI2_MESSAGE_TYPE) {
|
||||
newPolarInitNode->n_max = NR_POLAR_DCI_N_MAX;
|
||||
newPolarInitNode->i_il = NR_POLAR_DCI_I_IL;
|
||||
newPolarInitNode->i_seg = NR_POLAR_DCI_I_SEG;
|
||||
newPolarInitNode->n_pc = NR_POLAR_DCI_N_PC;
|
||||
newPolarInitNode->n_pc_wm = NR_POLAR_DCI_N_PC_WM;
|
||||
newPolarInitNode->i_bil = NR_POLAR_DCI_I_BIL;
|
||||
newPolarInitNode->crcParityBits = NR_POLAR_DCI_CRC_PARITY_BITS;
|
||||
newPolarInitNode->payloadBits = messageLength;
|
||||
if (messageType == NR_POLAR_DCI_MESSAGE_TYPE)
|
||||
newPolarInitNode->encoderLength = aggregation_level * 108;
|
||||
else if (messageType == NR_POLAR_SCI_MESSAGE_TYPE)
|
||||
newPolarInitNode->encoderLength = aggregation_level * 18; // for SCI1A aggregartion_level helds the number of PRBs, so multiply by 9*2 bits per PRB (9 REs with PSCCH payload)
|
||||
else if (messageType == NR_POLAR_SCI2_MESSAGE_TYPE)
|
||||
newPolarInitNode->encoderLength = aggregation_level * 2; // for SCI2 aggregartion_level helds the number of REs so multiple by 2, QPSK )
|
||||
newPolarInitNode->crcCorrectionBits = NR_POLAR_DCI_CRC_ERROR_CORRECTION_BITS;
|
||||
newPolarInitNode->crc_generator_matrix = crc24c_generator_matrix(newPolarInitNode->payloadBits + newPolarInitNode->crcParityBits); // G_P
|
||||
//printf("Initializing polar parameters for DCI (K %d, E %d, L %d)\n",newPolarInitNode->payloadBits,newPolarInitNode->encoderLength,aggregation_level);
|
||||
|
||||
} else if (messageType == NR_POLAR_UCI_PUCCH_MESSAGE_TYPE) {
|
||||
} else {
|
||||
AssertFatal(1 == 0, "[nr_polar_init] Incorrect Message Type(%d)", messageType);
|
||||
}
|
||||
|
||||
@@ -572,7 +572,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
|
||||
nr_generate_modulation_table();
|
||||
gNB->pdcch_gold_init = cfg->cell_config.phy_cell_id.value;
|
||||
nr_init_pdcch_dmrs(gNB, cfg->cell_config.phy_cell_id.value);
|
||||
nr_init_pdcch_dmrs(&gNB->frame_parms,gNB->nr_gold_pdcch_dmrs, cfg->cell_config.phy_cell_id.value);
|
||||
nr_init_pbch_interleaver(gNB->nr_pbch_interleaver);
|
||||
|
||||
//PDSCH DMRS init
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "PHY/MODULATION/nr_modulation.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
|
||||
#include "PHY/NR_REFSIG/pss_nr.h"
|
||||
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
|
||||
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
|
||||
@@ -35,6 +36,9 @@
|
||||
#include "PHY/MODULATION/nr_modulation.h"
|
||||
#include "openair2/COMMON/prs_nr_paramdef.h"
|
||||
#include "SCHED_NR_UE/harq_nr.h"
|
||||
#include "PHY/NR_REFSIG/nr_mod_table.h"
|
||||
#include <math.h>
|
||||
#include <complex.h>
|
||||
|
||||
void RCconfig_nrUE_prs(void *cfg)
|
||||
{
|
||||
@@ -296,8 +300,12 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
// init RX buffers
|
||||
common_vars->rxdata = malloc16(fp->nb_antennas_rx * sizeof(c16_t *));
|
||||
|
||||
int num_samples = 2 * fp->samples_per_frame + fp->ofdm_symbol_size;
|
||||
if (ue->sl_mode == 2)
|
||||
num_samples = (SL_NR_PSBCH_REPETITION_IN_FRAMES * fp->samples_per_frame) + fp->ofdm_symbol_size;
|
||||
|
||||
for (i=0; i<fp->nb_antennas_rx; i++) {
|
||||
common_vars->rxdata[i] = malloc16_clear((2 * (fp->samples_per_frame) + fp->ofdm_symbol_size) * sizeof(c16_t));
|
||||
common_vars->rxdata[i] = malloc16_clear(num_samples * sizeof(c16_t));
|
||||
}
|
||||
|
||||
// ceil(((NB_RB<<1)*3)/32) // 3 RE *2(QPSK)
|
||||
@@ -384,6 +392,15 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sl_ue_free(PHY_VARS_NR_UE *UE) {
|
||||
|
||||
if (UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation) {
|
||||
free_and_zero(UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation[0]);
|
||||
free_and_zero(UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation[1]);
|
||||
free_and_zero(UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation);
|
||||
}
|
||||
}
|
||||
|
||||
void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
{
|
||||
const NR_DL_FRAME_PARMS* fp = &ue->frame_parms;
|
||||
@@ -489,6 +506,8 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
|
||||
free_and_zero(ue->prs_vars[idx]);
|
||||
}
|
||||
|
||||
sl_ue_free(ue);
|
||||
}
|
||||
|
||||
void free_nr_ue_dl_harq(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PROCESSES], int number_of_processes, int num_rb) {
|
||||
@@ -540,8 +559,10 @@ void term_nr_ue_transport(PHY_VARS_NR_UE *ue)
|
||||
{
|
||||
const int N_RB_DL = ue->frame_parms.N_RB_DL;
|
||||
const int N_RB_UL = ue->frame_parms.N_RB_UL;
|
||||
const int N_RB_SL = ue->SL_UE_PHY_PARAMS.sl_frame_params.N_RB_SL;
|
||||
free_nr_ue_dl_harq(ue->dl_harq_processes, NR_MAX_DLSCH_HARQ_PROCESSES, N_RB_DL);
|
||||
free_nr_ue_ul_harq(ue->ul_harq_processes, NR_MAX_ULSCH_HARQ_PROCESSES, N_RB_UL, ue->frame_parms.nb_antennas_tx);
|
||||
free_nr_ue_ul_harq(ue->sl_harq_processes, NR_MAX_SLSCH_HARQ_PROCESSES, N_RB_SL, ue->SL_UE_PHY_PARAMS.sl_frame_params.nb_antennas_tx);
|
||||
}
|
||||
|
||||
void nr_init_dl_harq_processes(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PROCESSES], int number_of_processes, int num_rb) {
|
||||
@@ -624,6 +645,7 @@ void init_nr_ue_transport(PHY_VARS_NR_UE *ue) {
|
||||
|
||||
nr_init_dl_harq_processes(ue->dl_harq_processes, NR_MAX_DLSCH_HARQ_PROCESSES, ue->frame_parms.N_RB_DL);
|
||||
nr_init_ul_harq_processes(ue->ul_harq_processes, NR_MAX_ULSCH_HARQ_PROCESSES, ue->frame_parms.N_RB_UL, ue->frame_parms.nb_antennas_tx);
|
||||
nr_init_ul_harq_processes(ue->sl_harq_processes, NR_MAX_SLSCH_HARQ_PROCESSES, ue->SL_UE_PHY_PARAMS.sl_frame_params.N_RB_SL, ue->frame_parms.nb_antennas_tx);
|
||||
|
||||
for(int i=0; i<5; i++)
|
||||
ue->dl_stats[i] = 0;
|
||||
@@ -634,7 +656,8 @@ void init_N_TA_offset(PHY_VARS_NR_UE *ue){
|
||||
|
||||
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
|
||||
if (fp->frame_type == FDD) {
|
||||
// No timing offset for Sidelink, refer to 3GPP 38.211 Section 8.5
|
||||
if (fp->frame_type == FDD || ue->sl_mode == 2) {
|
||||
ue->N_TA_offset = 0;
|
||||
} else {
|
||||
int N_TA_offset = fp->ul_CarrierFreq < 6e9 ? 400 : 431; // reference samples for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2
|
||||
@@ -686,3 +709,364 @@ void phy_term_nr_top(void)
|
||||
free_ul_reference_signal_sequences();
|
||||
free_context_synchro_nr();
|
||||
}
|
||||
|
||||
static void sl_init_psbch_dmrs_gold_sequences(PHY_VARS_NR_UE *UE)
|
||||
{
|
||||
unsigned int x1, x2;
|
||||
uint16_t slss_id;
|
||||
uint8_t reset;
|
||||
|
||||
for (slss_id = 0; slss_id < SL_NR_NUM_SLSS_IDs; slss_id++) {
|
||||
|
||||
reset = 1;
|
||||
x2 = slss_id;
|
||||
|
||||
#ifdef SL_DEBUG_INIT
|
||||
printf("\nPSBCH DMRS GOLD SEQ for SLSSID :%d :\n", slss_id);
|
||||
#endif
|
||||
|
||||
for (uint8_t n=0; n<SL_NR_NUM_PSBCH_DMRS_RE_DWORD; n++) {
|
||||
UE->SL_UE_PHY_PARAMS.init_params.psbch_dmrs_gold_sequences[slss_id][n] = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
|
||||
#ifdef SL_DEBUG_INIT_DATA
|
||||
printf("%x\n",SL_UE_INIT_PARAMS.sl_psbch_dmrs_gold_sequences[slss_id][n]);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void sl_generate_psbch_dmrs_qpsk_sequences(PHY_VARS_NR_UE *UE,
|
||||
struct complex16 *modulated_dmrs_sym,
|
||||
uint16_t slss_id) {
|
||||
|
||||
uint8_t idx = 0;
|
||||
uint32_t *sl_dmrs_sequence = UE->SL_UE_PHY_PARAMS.init_params.psbch_dmrs_gold_sequences[slss_id];
|
||||
|
||||
#ifdef SL_DEBUG_INIT
|
||||
printf("SIDELINK INIT: PSBCH DMRS Generation with slss_id:%d\n", slss_id);
|
||||
#endif
|
||||
|
||||
/// QPSK modulation
|
||||
for (int m=0; m<SL_NR_NUM_PSBCH_DMRS_RE; m++) {
|
||||
|
||||
idx = (((sl_dmrs_sequence[(m<<1)>>5])>>((m<<1)&0x1f))&3);
|
||||
modulated_dmrs_sym[m].r = nr_qpsk_mod_table[2*idx];
|
||||
modulated_dmrs_sym[m].i = nr_qpsk_mod_table[(2*idx) + 1];
|
||||
|
||||
#ifdef SL_DEBUG_INIT_DATA
|
||||
printf("m:%d gold seq: %d b0-b1: %d-%d DMRS Symbols: %d %d\n", m, sl_dmrs_sequence[(m<<1)>>5], (((sl_dmrs_sequence[(m<<1)>>5])>>((m<<1)&0x1f))&1),
|
||||
(((sl_dmrs_sequence[((m<<1)+1)>>5])>>(((m<<1)+1)&0x1f))&1), modulated_dmrs_sym[m].r, modulated_dmrs_sym[m].i);
|
||||
printf("idx:%d, qpsk_table.r:%d, qpsk_table.i:%d\n", idx, nr_qpsk_mod_table[2*idx], nr_qpsk_mod_table[(2*idx) + 1]);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SL_DUMP_INIT_SAMPLES
|
||||
char filename[40], varname[25];
|
||||
sprintf(filename,"sl_psbch_dmrs_slssid_%d.m", slss_id);
|
||||
sprintf(varname,"sl_dmrs_id_%d.m", slss_id);
|
||||
LOG_M(filename, varname, (void*)modulated_dmrs_sym, SL_NR_NUM_PSBCH_DMRS_RE, 1, 1);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void sl_generate_pss(SL_NR_UE_INIT_PARAMS_t *sl_init_params, uint8_t n_sl_id2, uint16_t scaling) {
|
||||
|
||||
int i = 0, m = 0;
|
||||
int16_t x[SL_NR_PSS_SEQUENCE_LENGTH];
|
||||
const int x_initial[7] = {0, 1, 1 , 0, 1, 1, 1};
|
||||
int16_t *sl_pss = sl_init_params->sl_pss[n_sl_id2];
|
||||
int16_t *sl_pss_for_sync = sl_init_params->sl_pss_for_sync[n_sl_id2];
|
||||
|
||||
LOG_D(PHY, "SIDELINK PSBCH INIT: PSS Generation with N_SL_id2:%d\n", n_sl_id2);
|
||||
|
||||
#ifdef SL_DEBUG_INIT
|
||||
printf("SIDELINK: PSS Generation with N_SL_id2:%d\n", n_sl_id2);
|
||||
#endif
|
||||
|
||||
/// Sequence generation
|
||||
for (i=0; i < 7; i++)
|
||||
x[i] = x_initial[i];
|
||||
|
||||
for (i=0; i < (SL_NR_PSS_SEQUENCE_LENGTH - 7); i++) {
|
||||
x[i+7] = (x[i + 4] + x[i]) %2;
|
||||
}
|
||||
|
||||
for (i=0; i < SL_NR_PSS_SEQUENCE_LENGTH; i++) {
|
||||
m = (i + 22 + 43*n_sl_id2) % SL_NR_PSS_SEQUENCE_LENGTH;
|
||||
sl_pss_for_sync[i] = (1 - 2*x[m]);
|
||||
sl_pss[i] = sl_pss_for_sync[i] * scaling;
|
||||
|
||||
#ifdef SL_DEBUG_INIT_DATA
|
||||
printf("m:%d, sl_pss[%d]:%d\n", m, i, sl_pss[i]);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef SL_DUMP_INIT_SAMPLES
|
||||
LOG_M("sl_pss_seq.m", "sl_pss", (void*)sl_pss, SL_NR_PSS_SEQUENCE_LENGTH, 1, 0);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void sl_generate_sss(SL_NR_UE_INIT_PARAMS_t *sl_init_params, uint16_t slss_id, uint16_t scaling) {
|
||||
|
||||
int i = 0;
|
||||
int m0, m1;
|
||||
int n_sl_id1, n_sl_id2;
|
||||
int16_t *sl_sss = sl_init_params->sl_sss[slss_id];
|
||||
int16_t *sl_sss_for_sync = sl_init_params->sl_sss_for_sync[slss_id];
|
||||
|
||||
int16_t x0[SL_NR_SSS_SEQUENCE_LENGTH], x1[SL_NR_SSS_SEQUENCE_LENGTH];
|
||||
const int x_initial[7] = { 1, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
n_sl_id1 = slss_id % 336;
|
||||
n_sl_id2 = slss_id / 336;
|
||||
|
||||
LOG_D(PHY, "SIDELINK INIT: SSS Generation with N_SL_id1:%d N_SL_id2:%d\n", n_sl_id1, n_sl_id2);
|
||||
|
||||
#ifdef SL_DEBUG_INIT
|
||||
printf("SIDELINK: SSS Generation with slss_id:%d, N_SL_id1:%d, N_SL_id2:%d\n", slss_id, n_sl_id1, n_sl_id2);
|
||||
#endif
|
||||
|
||||
for ( i=0 ; i < 7 ; i++) {
|
||||
x0[i] = x_initial[i];
|
||||
x1[i] = x_initial[i];
|
||||
}
|
||||
|
||||
for ( i=0 ; i < SL_NR_SSS_SEQUENCE_LENGTH - 7 ; i++) {
|
||||
x0[i+7] = (x0[i + 4] + x0[i]) % 2;
|
||||
x1[i+7] = (x1[i + 1] + x1[i]) % 2;
|
||||
}
|
||||
|
||||
m0 = 15*(n_sl_id1/112) + (5*n_sl_id2);
|
||||
m1 = n_sl_id1 % 112;
|
||||
|
||||
for (i = 0; i < SL_NR_SSS_SEQUENCE_LENGTH ; i++) {
|
||||
sl_sss_for_sync[i] = (1 - 2*x0[(i + m0) % SL_NR_SSS_SEQUENCE_LENGTH] ) * (1 - 2*x1[(i + m1) % SL_NR_SSS_SEQUENCE_LENGTH] );
|
||||
sl_sss[i] = sl_sss_for_sync[i] * scaling;
|
||||
|
||||
#ifdef SL_DEBUG_INIT_DATA
|
||||
printf("m0:%d, m1:%d, sl_sss_for_sync[%d]:%d, sl_sss[%d]:%d\n", m0, m1, i, sl_sss_for_sync[i], i, sl_sss[i]);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef SL_DUMP_PSBCH_TX_SAMPLES
|
||||
LOG_M("sl_sss_seq.m", "sl_sss", (void*)sl_sss, SL_NR_SSS_SEQUENCE_LENGTH, 1, 0);
|
||||
LOG_M("sl_sss_forsync_seq.m", "sl_sss_for_sync", (void*)sl_sss_for_sync, SL_NR_SSS_SEQUENCE_LENGTH, 1, 0);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// This cannot be done at init time as ofdm symbol size, ssb start subcarrier depends on configuration
|
||||
// done at SLSS read time.
|
||||
static void sl_generate_pss_ifft_samples(sl_nr_ue_phy_params_t *sl_ue_params, SL_NR_UE_INIT_PARAMS_t *sl_init_params) {
|
||||
|
||||
uint8_t id2 = 0;
|
||||
int16_t *sl_pss = NULL;
|
||||
NR_DL_FRAME_PARMS *sl_fp = &sl_ue_params->sl_frame_params;
|
||||
int16_t scaling_factor = AMP;
|
||||
|
||||
int16_t *pss_F = NULL; // IQ samples in freq domain
|
||||
int32_t *pss_T = NULL;
|
||||
|
||||
uint16_t k = 0;
|
||||
|
||||
pss_F = malloc16_clear(2*sizeof(int16_t) * sl_fp->ofdm_symbol_size);
|
||||
|
||||
LOG_I(PHY, "SIDELINK INIT: Generation of PSS time domain samples. scaling_factor:%d\n", scaling_factor);
|
||||
|
||||
for (id2 = 0; id2 < SL_NR_NUM_IDs_IN_PSS; id2++) {
|
||||
|
||||
k = sl_fp->first_carrier_offset + sl_fp->ssb_start_subcarrier + 2; // PSS in from REs 2-129
|
||||
if (k >= sl_fp->ofdm_symbol_size) k -= sl_fp->ofdm_symbol_size;
|
||||
|
||||
pss_T = &sl_init_params->sl_pss_for_correlation[id2][0];
|
||||
sl_pss = sl_init_params->sl_pss[id2];
|
||||
|
||||
memset(pss_T, 0, sl_fp->ofdm_symbol_size * sizeof(pss_T[0]));
|
||||
memset(pss_F, 0, sl_fp->ofdm_symbol_size * 2 * sizeof(pss_F[0]));
|
||||
|
||||
for (int i=0; i < SL_NR_PSS_SEQUENCE_LENGTH; i++) {
|
||||
|
||||
pss_F[2*k] = (sl_pss[i] * scaling_factor) >> 15;
|
||||
//pss_F[2*k] = (sl_pss[i]/23170) * 4192;
|
||||
//pss_F[2*k+1] = 0;
|
||||
|
||||
#ifdef SL_DEBUG_INIT_DATA
|
||||
printf("id:%d, k:%d, pss_F[%d]:%d, sl_pss[%d]:%d\n", id2, k, 2*k, pss_F[2*k], i, sl_pss[i]);
|
||||
#endif
|
||||
|
||||
k++;
|
||||
if (k == sl_fp->ofdm_symbol_size) k=0;
|
||||
|
||||
}
|
||||
|
||||
idft((int16_t)get_idft(sl_fp->ofdm_symbol_size),
|
||||
pss_F, /* complex input */
|
||||
(int16_t *)&pss_T[0], /* complex output */
|
||||
1); /* scaling factor */
|
||||
|
||||
}
|
||||
|
||||
#ifdef SL_DUMP_PSBCH_TX_SAMPLES
|
||||
LOG_M("sl_pss_TD_id0.m", "pss_TD_0", (void*)sl_init_params->sl_pss_for_correlation[0], sl_fp->ofdm_symbol_size, 1, 1);
|
||||
LOG_M("sl_pss_TD_id1.m", "pss_TD_1", (void*)sl_init_params->sl_pss_for_correlation[1], sl_fp->ofdm_symbol_size, 1, 1);
|
||||
#endif
|
||||
|
||||
free(pss_F);
|
||||
|
||||
}
|
||||
|
||||
void init_ul_delay_table(NR_DL_FRAME_PARMS *fp)
|
||||
{
|
||||
for (int delay = -MAX_UL_DELAY_COMP; delay <= MAX_UL_DELAY_COMP; delay++) {
|
||||
for (int k = 0; k < fp->ofdm_symbol_size; k++) {
|
||||
double complex delay_cexp = cexp(I * (2.0 * M_PI * k * delay / fp->ofdm_symbol_size));
|
||||
fp->ul_delay_table[MAX_UL_DELAY_COMP + delay][k].r = (int16_t)round(256 * creal(delay_cexp));
|
||||
fp->ul_delay_table[MAX_UL_DELAY_COMP + delay][k].i = (int16_t)round(256 * cimag(delay_cexp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void sl_ue_phy_init(PHY_VARS_NR_UE *UE) {
|
||||
|
||||
uint16_t scaling_value = ONE_OVER_SQRT2_Q15;
|
||||
|
||||
NR_DL_FRAME_PARMS *sl_fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
if (!UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation) {
|
||||
UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation = (int32_t **)malloc16_clear(SL_NR_NUM_IDs_IN_PSS *sizeof(int32_t *) );
|
||||
UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation[0] = (int32_t *)malloc16_clear( sizeof(int32_t)*sl_fp->ofdm_symbol_size);
|
||||
UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation[1] = (int32_t *)malloc16_clear( sizeof(int32_t)*sl_fp->ofdm_symbol_size);
|
||||
}
|
||||
LOG_I(PHY, "SIDELINK INIT: GENERATE PSS, SSS, GOLD SEQUENCES AND PSBCH DMRS SEQUENCES FOR ALL possible SLSS IDs 0- 671\n");
|
||||
|
||||
// Generate PSS sequences for IDs 0,1 used in PSS
|
||||
sl_generate_pss(&UE->SL_UE_PHY_PARAMS.init_params,0, scaling_value);
|
||||
sl_generate_pss(&UE->SL_UE_PHY_PARAMS.init_params,1, scaling_value);
|
||||
|
||||
// Generate psbch dmrs Gold Sequences and modulated dmrs symbols
|
||||
sl_init_psbch_dmrs_gold_sequences(UE);
|
||||
// Generate pscch dmrs Gold Sequences
|
||||
UE->nr_gold_pscch_dmrs = (uint32_t ***)malloc16(sl_fp->slots_per_frame*sizeof(uint32_t **));
|
||||
uint32_t ***pscch_dmrs = UE->nr_gold_pscch_dmrs;
|
||||
AssertFatal(pscch_dmrs!=NULL, "NR init: pscch_dmrs malloc failed\n");
|
||||
int pscch_dmrs_init_length = (((sl_fp->N_RB_UL<<1)*3)>>5)+1;
|
||||
|
||||
for (int slot=0; slot<sl_fp->slots_per_frame; slot++) {
|
||||
pscch_dmrs[slot] = (uint32_t **)malloc16(sl_fp->symbols_per_slot*sizeof(uint32_t *));
|
||||
AssertFatal(pscch_dmrs[slot]!=NULL, "NR SL UE init: pscch_dmrs for slot %d - malloc failed\n", slot);
|
||||
|
||||
for (int symb=0; symb<sl_fp->symbols_per_slot; symb++) {
|
||||
pscch_dmrs[slot][symb] = (uint32_t *)malloc16(pscch_dmrs_init_length*sizeof(uint32_t));
|
||||
LOG_D(PHY,"pscch_dmrs[%d][%d] %p\n",slot,symb,pscch_dmrs[slot][symb]);
|
||||
AssertFatal(pscch_dmrs[slot][symb]!=NULL, "NR SL UE init: pscch_dmrs for slot %d symbol %d - malloc failed\n", slot, symb);
|
||||
}
|
||||
}
|
||||
|
||||
nr_init_pdcch_dmrs(sl_fp,UE->nr_gold_pscch_dmrs, UE->SL_UE_PHY_PARAMS.sl_config.sl_DMRS_ScrambleId);
|
||||
|
||||
// PSCCH DMRS RX
|
||||
UE->nr_gold_pscch = malloc16(sl_fp->slots_per_frame * sizeof(uint32_t **));
|
||||
uint32_t ***pscch_dmrs_rx = UE->nr_gold_pscch;
|
||||
AssertFatal(pscch_dmrs_rx!=NULL, "NR init: pscch_dmrs malloc failed\n");
|
||||
|
||||
for (int slot=0; slot<sl_fp->slots_per_frame; slot++) {
|
||||
pscch_dmrs_rx[slot] = malloc16(sl_fp->symbols_per_slot * sizeof(uint32_t *));
|
||||
AssertFatal(pscch_dmrs_rx[slot]!=NULL, "NR init: pscch_dmrs for slot %d - malloc failed\n", slot);
|
||||
|
||||
for (int symb=0; symb<sl_fp->symbols_per_slot; symb++) {
|
||||
pscch_dmrs_rx[slot][symb] = malloc16(pscch_dmrs_init_length * sizeof(uint32_t));
|
||||
AssertFatal(pscch_dmrs[slot][symb]!=NULL, "NR init: pscch_dmrs for slot %d symbol %d - malloc failed\n", slot, symb);
|
||||
}
|
||||
}
|
||||
|
||||
nr_gold_pdcch(sl_fp, pscch_dmrs_rx,UE->SL_UE_PHY_PARAMS.sl_config.sl_DMRS_ScrambleId);
|
||||
|
||||
// SSS
|
||||
for (int slss_id = 0; slss_id < SL_NR_NUM_SLSS_IDs; slss_id++) {
|
||||
sl_generate_psbch_dmrs_qpsk_sequences(UE, UE->SL_UE_PHY_PARAMS.init_params.psbch_dmrs_modsym[slss_id], slss_id);
|
||||
sl_generate_sss(&UE->SL_UE_PHY_PARAMS.init_params, slss_id, scaling_value);
|
||||
}
|
||||
|
||||
// Generate PSS time domain samples used for correlation during SLSS reception.
|
||||
sl_generate_pss_ifft_samples(&UE->SL_UE_PHY_PARAMS, &UE->SL_UE_PHY_PARAMS.init_params);
|
||||
|
||||
|
||||
UE->max_nb_slsch = NR_SLSCH_RX_MAX;
|
||||
UE->slsch = (NR_gNB_ULSCH_t *)malloc16(UE->max_nb_slsch * sizeof(NR_gNB_ULSCH_t));
|
||||
for (int i = 0; i < UE->max_nb_slsch; i++) {
|
||||
LOG_I(PHY, "Allocating Transport Channel Buffers for SLSCH %d/%d\n", i, UE->max_nb_slsch);
|
||||
UE->slsch[i] = new_gNB_ulsch(UE->max_ldpc_iterations, sl_fp->N_RB_UL);
|
||||
}
|
||||
|
||||
int Prx=sl_fp->nb_antennas_rx;
|
||||
int N_RB_UL = sl_fp->N_RB_UL;
|
||||
int n_buf = 2*Prx;
|
||||
|
||||
int nb_re_pusch = N_RB_UL * NR_NB_SC_PER_RB;
|
||||
int nb_re_pusch2 = nb_re_pusch + (nb_re_pusch&7);
|
||||
UE->pssch_thres = 10;
|
||||
UE->pssch_vars = (NR_gNB_PUSCH *)malloc16_clear(UE->max_nb_slsch * sizeof(NR_gNB_PUSCH));
|
||||
for (int SLSCH_id = 0; SLSCH_id < NR_SLSCH_RX_MAX; SLSCH_id++) {
|
||||
NR_gNB_PUSCH *pssch = &UE->pssch_vars[SLSCH_id];
|
||||
pssch->rxdataF_ext = (int32_t **)malloc16(Prx * sizeof(int32_t *));
|
||||
pssch->ul_ch_estimates = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
|
||||
pssch->ul_ch_estimates_ext = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
|
||||
pssch->ptrs_phase_per_slot = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
|
||||
pssch->ul_ch_estimates_time = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
|
||||
pssch->rxdataF_comp = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
|
||||
pssch->ul_ch_mag0 = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
|
||||
pssch->ul_ch_magb0 = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
|
||||
pssch->ul_ch_magc0 = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
|
||||
pssch->ul_ch_mag = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
|
||||
pssch->ul_ch_magb = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
|
||||
pssch->ul_ch_magc = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
|
||||
pssch->rho = (int32_t ***)malloc16(Prx * sizeof(int32_t **));
|
||||
pssch->llr_layers = (int16_t **)malloc16(2 * sizeof(int32_t *));
|
||||
for (int i = 0; i < Prx; i++) {
|
||||
pssch->rxdataF_ext[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
|
||||
pssch->rho[i] = (int32_t **)malloc16_clear(2 * 2 * sizeof(int32_t *));
|
||||
|
||||
for (int j = 0; j < 2; j++) {
|
||||
for (int k = 0; k < 2; k++) {
|
||||
pssch->rho[i][j * 2 + k] =
|
||||
(int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < n_buf; i++) {
|
||||
pssch->ul_ch_estimates[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * sl_fp->ofdm_symbol_size * sl_fp->symbols_per_slot);
|
||||
pssch->ul_ch_estimates_ext[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
|
||||
pssch->ul_ch_estimates_time[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * sl_fp->ofdm_symbol_size);
|
||||
pssch->ptrs_phase_per_slot[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * sl_fp->symbols_per_slot); // symbols per slot
|
||||
pssch->rxdataF_comp[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
|
||||
pssch->ul_ch_mag0[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
|
||||
pssch->ul_ch_magb0[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
|
||||
pssch->ul_ch_magc0[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
|
||||
pssch->ul_ch_mag[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
|
||||
pssch->ul_ch_magb[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
|
||||
pssch->ul_ch_magc[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
|
||||
}
|
||||
|
||||
for (int i=0; i< 2; i++) {
|
||||
pssch->llr_layers[i] = (int16_t *)malloc16_clear((8 * ((3 * 8 * 6144) + 12))
|
||||
* sizeof(int16_t)); // [hna] 6144 is LTE and (8*((3*8*6144)+12)) is not clear
|
||||
}
|
||||
pssch->llr = (int16_t *)malloc16_clear((8 * ((3 * 8 * 6144) + 12))
|
||||
* sizeof(int16_t)); // [hna] 6144 is LTE and (8*((3*8*6144)+12)) is not clear
|
||||
pssch->ul_valid_re_per_slot = (int16_t *)malloc16_clear(sizeof(int16_t) * sl_fp->symbols_per_slot);
|
||||
} // ulsch_id
|
||||
UE->sl_measurements = calloc(1,sizeof(struct PHY_MEASUREMENTS_gNB_s));
|
||||
|
||||
|
||||
init_ul_delay_table(sl_fp);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "PHY/MODULATION/nr_modulation.h"
|
||||
|
||||
/// Subcarrier spacings in Hz indexed by numerology index
|
||||
static const uint32_t nr_subcarrier_spacing[MAX_NUM_SUBCARRIER_SPACING] = {15e3, 30e3, 60e3, 120e3, 240e3};
|
||||
@@ -42,18 +43,6 @@ static const int nr_ssb_table[48][3] = {
|
||||
{93, 15, nr_ssb_type_A}, {94, 15, nr_ssb_type_A}, {96, 30, nr_ssb_type_C}};
|
||||
|
||||
void set_Lmax(NR_DL_FRAME_PARMS *fp) {
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
int sl_NumSSB_WithinPeriod = 1; //TODO: Needs to be updated from RRC parameters
|
||||
int sl_TimeOffsetSSB = 1; //TODO: Needs to be updated from RRC parameters
|
||||
int sl_TimeInterval = 1; //TODO: Needs to be updated from RRC parameters
|
||||
if ((sl_NumSSB_WithinPeriod == 4) && ((sl_TimeOffsetSSB % fp->slots_per_frame) + 3 * sl_TimeInterval < NR_NUMBER_OF_SUBFRAMES_PER_FRAME * 2))
|
||||
fp->Lmax = 4;
|
||||
else if ((sl_NumSSB_WithinPeriod == 2) && ((sl_TimeOffsetSSB % fp->slots_per_frame) + sl_TimeInterval < NR_NUMBER_OF_SUBFRAMES_PER_FRAME))
|
||||
fp->Lmax = 2;
|
||||
else
|
||||
fp->Lmax = 1;
|
||||
return;
|
||||
}
|
||||
// definition of Lmax according to ts 38.213 section 4.1
|
||||
if (fp->dl_CarrierFreq < 6e9) {
|
||||
if(fp->frame_type && (fp->ssb_type==2))
|
||||
@@ -115,23 +104,27 @@ void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, int N_RB_DL)
|
||||
case NR_MU_0: //15kHz scs
|
||||
fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_0];
|
||||
fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_0];
|
||||
fp->ssb_type = nr_ssb_type_A;
|
||||
while(nr_ssb_table[idx][0]!=fp->nr_band)
|
||||
idx++;
|
||||
AssertFatal(nr_ssb_table[idx][1]==15,"SCS %d not applicable to band %d\n",
|
||||
fp->subcarrier_spacing,fp->nr_band);
|
||||
if (fp->nr_band != 47) {
|
||||
fp->ssb_type = nr_ssb_type_A;
|
||||
while(nr_ssb_table[idx][0]!=fp->nr_band)
|
||||
idx++;
|
||||
AssertFatal(nr_ssb_table[idx][1]==15,"SCS %d not applicable to band %d\n",
|
||||
fp->subcarrier_spacing,fp->nr_band);
|
||||
}
|
||||
break;
|
||||
|
||||
case NR_MU_1: //30kHz scs
|
||||
fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_1];
|
||||
fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_1];
|
||||
while(nr_ssb_table[idx][0]!=fp->nr_band ||
|
||||
nr_ssb_table[idx][1]!=30) {
|
||||
AssertFatal(nr_ssb_table[idx][0]<=fp->nr_band,"SCS %d not applicable to band %d\n",
|
||||
fp->subcarrier_spacing,fp->nr_band);
|
||||
idx++;
|
||||
if (fp->nr_band != 47) {
|
||||
while(nr_ssb_table[idx][0]!=fp->nr_band ||
|
||||
nr_ssb_table[idx][1]!=30) {
|
||||
AssertFatal(nr_ssb_table[idx][0]<=fp->nr_band,"SCS %d not applicable to band %d\n",
|
||||
fp->subcarrier_spacing,fp->nr_band);
|
||||
idx++;
|
||||
}
|
||||
fp->ssb_type = nr_ssb_table[idx][2];
|
||||
}
|
||||
fp->ssb_type = nr_ssb_table[idx][2];
|
||||
break;
|
||||
|
||||
case NR_MU_2: //60kHz scs
|
||||
@@ -164,9 +157,6 @@ void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, int N_RB_DL)
|
||||
fp->ofdm_symbol_size <<= 1;
|
||||
|
||||
fp->first_carrier_offset = fp->ofdm_symbol_size - (N_RB_DL * 12 / 2);
|
||||
// TODO: Temporarily setting fp->first_carrier_offset = 0 for SL until MAC is developed
|
||||
if (get_softmodem_params()->sl_mode == 2)
|
||||
fp->first_carrier_offset = 0;
|
||||
fp->nb_prefix_samples = fp->ofdm_symbol_size / 128 * 9;
|
||||
fp->nb_prefix_samples0 = fp->ofdm_symbol_size / 128 * (9 + (1 << mu));
|
||||
LOG_W(PHY,"Init: N_RB_DL %d, first_carrier_offset %d, nb_prefix_samples %d,nb_prefix_samples0 %d, ofdm_symbol_size %d\n",
|
||||
@@ -299,11 +289,6 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
|
||||
LOG_D(PHY,"dl_bw_kHz %lu\n",dl_bw_khz);
|
||||
LOG_D(PHY,"dl_CarrierFreq %lu\n",fp->dl_CarrierFreq);
|
||||
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
uint64_t sl_bw_khz = (12 * config->carrier_config.sl_grid_size[config->ssb_config.scs_common]) * (15 << config->ssb_config.scs_common);
|
||||
fp->sl_CarrierFreq = ((sl_bw_khz >> 1) + config->carrier_config.sl_frequency) * 1000;
|
||||
}
|
||||
|
||||
uint64_t ul_bw_khz = (12*config->carrier_config.ul_grid_size[config->ssb_config.scs_common])*(15<<config->ssb_config.scs_common);
|
||||
fp->ul_CarrierFreq = ((ul_bw_khz>>1) + config->carrier_config.uplink_frequency)*1000 ;
|
||||
|
||||
@@ -329,7 +314,7 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
|
||||
AssertFatal(fp->numerology_index == NR_MU_2,"Invalid cyclic prefix %d for numerology index %d\n", Ncp, fp->numerology_index);
|
||||
|
||||
fp->Ncp = Ncp;
|
||||
int N_RB = (get_softmodem_params()->sl_mode == 2) ? fp->N_RB_SL : fp->N_RB_DL;
|
||||
int N_RB = fp->N_RB_DL;
|
||||
set_scs_parameters(fp, fp->numerology_index, N_RB);
|
||||
|
||||
fp->slots_per_frame = 10* fp->slots_per_subframe;
|
||||
@@ -354,10 +339,6 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
|
||||
}
|
||||
|
||||
fp->ssb_start_subcarrier = (12 * config->ssb_table.ssb_offset_point_a + sco);
|
||||
// TODO: Temporarily setting fp->ssb_start_subcarrier = 0 for SL until MAC is developed
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
fp->ssb_start_subcarrier = 0;
|
||||
}
|
||||
set_Lmax(fp);
|
||||
|
||||
fp->L_ssb = (((uint64_t) config->ssb_table.ssb_mask_list[0].ssb_mask)<<32) | config->ssb_table.ssb_mask_list[1].ssb_mask;
|
||||
@@ -407,12 +388,6 @@ void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink
|
||||
|
||||
}
|
||||
|
||||
void nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *frame_parms, uint64_t sidelink_frequency, uint16_t nr_band) {
|
||||
LOG_D(NR_PHY, "SL init parameters. SL freq %lu\n", sidelink_frequency);
|
||||
frame_parms->sl_CarrierFreq = sidelink_frequency;
|
||||
frame_parms->nr_band = nr_band;
|
||||
}
|
||||
|
||||
void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp)
|
||||
{
|
||||
LOG_I(PHY,"fp->scs=%d\n",fp->subcarrier_spacing);
|
||||
@@ -426,7 +401,109 @@ void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp)
|
||||
LOG_I(PHY,"fp->samples_per_frame=%d\n",fp->samples_per_frame);
|
||||
LOG_I(PHY,"fp->dl_CarrierFreq=%lu\n",fp->dl_CarrierFreq);
|
||||
LOG_I(PHY,"fp->ul_CarrierFreq=%lu\n",fp->ul_CarrierFreq);
|
||||
LOG_I(PHY,"fp->Nid_cell=%d\n",fp->Nid_cell);
|
||||
LOG_I(PHY,"fp->first_carrier_offset=%d\n",fp->first_carrier_offset);
|
||||
LOG_I(PHY,"fp->ssb_start_subcarrier=%d\n",fp->ssb_start_subcarrier);
|
||||
LOG_I(PHY,"fp->Ncp=%d\n",fp->Ncp);
|
||||
LOG_I(PHY,"fp->N_RB_DL=%d\n",fp->N_RB_DL);
|
||||
LOG_I(PHY,"fp->numerology_index=%d\n",fp->numerology_index);
|
||||
LOG_I(PHY,"fp->nr_band=%d\n",fp->nr_band);
|
||||
LOG_I(PHY,"fp->ofdm_offset_divisor=%d\n",fp->ofdm_offset_divisor);
|
||||
LOG_I(PHY,"fp->threequarter_fs=%d\n",fp->threequarter_fs);
|
||||
LOG_I(PHY,"fp->sl_CarrierFreq=%lu\n",fp->sl_CarrierFreq);
|
||||
LOG_I(PHY,"fp->N_RB_SL=%d\n",fp->N_RB_SL);
|
||||
}
|
||||
|
||||
int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp,
|
||||
sl_nr_phy_config_request_t* config,
|
||||
int threequarter_fs,
|
||||
uint32_t ofdm_offset_divisor)
|
||||
{
|
||||
|
||||
//Set also these parameters here instead of some where else.
|
||||
fp->ofdm_offset_divisor = ofdm_offset_divisor;
|
||||
fp->threequarter_fs = threequarter_fs;
|
||||
|
||||
fp->nr_band = get_band(config->sl_carrier_config.sl_frequency*1000, 0);
|
||||
|
||||
fp->att_rx = config->sl_carrier_config.sl_num_rx_ant;
|
||||
fp->att_tx = config->sl_carrier_config.sl_num_tx_ant;
|
||||
fp->nb_antennas_rx = fp->att_rx;
|
||||
fp->nb_antennas_tx = fp->att_tx;
|
||||
|
||||
fp->numerology_index = config->sl_bwp_config.sl_scs;
|
||||
fp->N_RB_SL = config->sl_carrier_config.sl_grid_size;
|
||||
fp->N_RB_DL = fp->N_RB_SL;
|
||||
fp->N_RB_UL = fp->N_RB_SL;
|
||||
fp->Ncp = config->sl_bwp_config.sl_cyclic_prefix;
|
||||
|
||||
fp->frame_type = get_frame_type(fp->nr_band, fp->numerology_index);
|
||||
int32_t uplink_frequency_offset = get_delta_duplex(fp->nr_band, fp->numerology_index);
|
||||
uplink_frequency_offset *= 1000;
|
||||
|
||||
uint64_t bw_khz = (12*config->sl_carrier_config.sl_grid_size)*(15<<config->sl_bwp_config.sl_scs);
|
||||
//REfer to section 3GPP spec 38.101 5.4E.2.1
|
||||
//FrefV2x = Fref + deltashift + valueN*5Khz
|
||||
uint32_t deltashift = (config->sl_carrier_config.sl_frequency_shift_7p5khz) ? 7500 : 0; //In Hz
|
||||
deltashift += config->sl_carrier_config.sl_value_N * 5000; //In Hz
|
||||
fp->sl_CarrierFreq = ((bw_khz >> 1) + config->sl_carrier_config.sl_frequency)*1000 ;
|
||||
fp->sl_CarrierFreq += (deltashift >> 1);
|
||||
fp->dl_CarrierFreq = fp->sl_CarrierFreq;
|
||||
fp->ul_CarrierFreq = fp->dl_CarrierFreq + uplink_frequency_offset;
|
||||
|
||||
LOG_D(PHY,"bw_kHz %lu, deltashift:%d Hz\n",bw_khz,deltashift);
|
||||
LOG_D(PHY,"CarrierFreq %lu Hz\n",fp->sl_CarrierFreq);
|
||||
|
||||
LOG_I(PHY, "Initializing frame parms: DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %d Hz\n",
|
||||
fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, uplink_frequency_offset);
|
||||
|
||||
AssertFatal(fp->frame_type==TDD, "Sidelink bands only support TDD");
|
||||
|
||||
AssertFatal(fp->ul_CarrierFreq == (fp->dl_CarrierFreq + uplink_frequency_offset),
|
||||
"Disagreement in uplink frequency for band %d: ul_CarrierFreq = %lu Hz vs expected %lu Hz\n",
|
||||
fp->nr_band, fp->ul_CarrierFreq, fp->dl_CarrierFreq + uplink_frequency_offset);
|
||||
|
||||
LOG_I(PHY,"Initializing frame parms for mu %d, N_RB %d, Ncp %d\n",fp->numerology_index, fp->N_RB_DL, fp->Ncp);
|
||||
|
||||
if (fp->Ncp == EXTENDED)
|
||||
AssertFatal(fp->numerology_index == NR_MU_2,"Invalid cyclic prefix %d for numerology index %d\n",
|
||||
fp->Ncp, fp->numerology_index);
|
||||
|
||||
set_scs_parameters(fp, fp->numerology_index, fp->N_RB_SL);
|
||||
|
||||
fp->slots_per_frame = 10* fp->slots_per_subframe;
|
||||
fp->symbols_per_slot = ((fp->Ncp == NORMAL)? 14 : 12); // to redefine for different slot formats
|
||||
fp->samples_per_subframe_wCP = fp->ofdm_symbol_size * fp->symbols_per_slot * fp->slots_per_subframe;
|
||||
fp->samples_per_frame_wCP = 10 * fp->samples_per_subframe_wCP;
|
||||
fp->samples_per_slot_wCP = fp->symbols_per_slot*fp->ofdm_symbol_size;
|
||||
fp->samples_per_slotN0 = (fp->nb_prefix_samples + fp->ofdm_symbol_size) * fp->symbols_per_slot;
|
||||
fp->samples_per_slot0 = fp->nb_prefix_samples0 + ((fp->symbols_per_slot-1)*fp->nb_prefix_samples) + (fp->symbols_per_slot*fp->ofdm_symbol_size);
|
||||
fp->samples_per_subframe = (fp->nb_prefix_samples0 + fp->ofdm_symbol_size) * 2 +
|
||||
(fp->nb_prefix_samples + fp->ofdm_symbol_size) * (fp->symbols_per_slot * fp->slots_per_subframe - 2);
|
||||
fp->get_samples_per_slot = &get_samples_per_slot;
|
||||
fp->get_samples_slot_timestamp = &get_samples_slot_timestamp;
|
||||
fp->samples_per_frame = 10 * fp->samples_per_subframe;
|
||||
fp->freq_range = (fp->dl_CarrierFreq < 6e9)? nr_FR1 : nr_FR2;
|
||||
|
||||
//ssb_offset_pointa points to the first RE where Sidelink-PSBCH starts
|
||||
fp->ssb_start_subcarrier = config->sl_bwp_config.sl_ssb_offset_point_a;
|
||||
|
||||
|
||||
init_symbol_rotation(fp);
|
||||
init_timeshift_rotation(fp);
|
||||
|
||||
//Not used for Sidelink
|
||||
fp->Lmax = 0;
|
||||
fp->L_ssb = 0;
|
||||
fp->N_ssb = 0;
|
||||
fp->half_frame_bit = 0;
|
||||
fp->ssb_index = 0;
|
||||
fp->ssb_type = 0;
|
||||
|
||||
//#ifdef SL_DEBUG
|
||||
LOG_I(PHY, "Dumping Sidelink Frame Parameters\n");
|
||||
nr_dump_frame_parms(fp);
|
||||
//#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,10 @@ int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp,uint8_t i_ssb);
|
||||
int nr_init_frame_parms(nfapi_nr_config_request_scf_t *config, NR_DL_FRAME_PARMS *frame_parms);
|
||||
int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *frame_parms, fapi_nr_config_request_t *config, uint16_t nr_band);
|
||||
void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink_frequency, int32_t uplink_frequency_offset, uint8_t mu, uint16_t nr_band);
|
||||
void nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *frame_parms, uint64_t sidelink_frequency, uint16_t nr_band);
|
||||
int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp,
|
||||
sl_nr_phy_config_request_t* config,
|
||||
int threequarter_fs,
|
||||
uint32_t ofdm_offset_divisor);
|
||||
int init_nr_ue_signal(PHY_VARS_NR_UE *ue,int nb_connected_eNB);
|
||||
void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB);
|
||||
void init_nr_ue_transport(PHY_VARS_NR_UE *ue);
|
||||
@@ -56,5 +59,6 @@ void free_nr_ue_ul_harq(NR_UL_UE_HARQ_t harq_list[NR_MAX_ULSCH_HARQ_PROCESSES],
|
||||
|
||||
void phy_init_nr_top(PHY_VARS_NR_UE *ue);
|
||||
void phy_term_nr_top(void);
|
||||
void sl_ue_phy_init(PHY_VARS_NR_UE *UE);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -49,9 +49,17 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue,
|
||||
int reset_freq_est);
|
||||
|
||||
int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
unsigned char symbol,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
c16_t rxdataF[][frame_parms->samples_per_slot_wCP],
|
||||
uint32_t linktype);
|
||||
int sl_nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
unsigned char symbol,
|
||||
unsigned char Ns,
|
||||
uint32_t sample_offset,
|
||||
c16_t rxdataF[][ue->SL_UE_PHY_PARAMS.sl_frame_params.samples_per_slot_wCP]);
|
||||
|
||||
int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
|
||||
@@ -601,7 +601,7 @@ void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) {
|
||||
uint64_t dl_CarrierFreq = fp->dl_CarrierFreq;
|
||||
uint64_t ul_CarrierFreq = fp->ul_CarrierFreq;
|
||||
uint64_t sl_CarrierFreq = fp->sl_CarrierFreq;
|
||||
double f[2] = {(double)dl_CarrierFreq, (double)ul_CarrierFreq};
|
||||
double f[3] = {(double)dl_CarrierFreq, (double)ul_CarrierFreq, (double)sl_CarrierFreq};
|
||||
|
||||
const int nsymb = fp->symbols_per_slot * fp->slots_per_frame/10;
|
||||
const double Tc=(1/480e3/4096);
|
||||
@@ -609,15 +609,12 @@ void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) {
|
||||
const double Ncp0=16*64 + (144*64*(1/(float)(1<<fp->numerology_index)));
|
||||
const double Ncp1=(144*64*(1/(float)(1<<fp->numerology_index)));
|
||||
|
||||
for (uint8_t ll = 0; ll < 2; ll++){
|
||||
for (uint8_t ll = 0; ll < 3; ll++){
|
||||
|
||||
double f0 = f[ll];
|
||||
LOG_D(PHY, "Doing symbol rotation calculation for gNB TX/RX, f0 %f Hz, Nsymb %d\n", f0, nsymb);
|
||||
if (f0 == 0) continue;
|
||||
LOG_I(NR_PHY, "Doing symbol rotation calculation for gNB TX/RX, f0 %f Hz, Nsymb %d\n", f0, nsymb);
|
||||
c16_t *symbol_rotation = fp->symbol_rotation[ll];
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
f0 = (double)sl_CarrierFreq;
|
||||
symbol_rotation = fp->symbol_rotation[link_type_sl];
|
||||
}
|
||||
|
||||
double tl = 0.0;
|
||||
double poff = 0.0;
|
||||
@@ -634,12 +631,12 @@ void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) {
|
||||
}
|
||||
|
||||
poff = 2 * M_PI * (tl + (Ncp * Tc)) * f0;
|
||||
exp_re = cos(poff);
|
||||
exp_im = sin(-poff);
|
||||
exp_re = 1.0;//cos(poff);
|
||||
exp_im = 0.0;//sin(-poff);
|
||||
symbol_rotation[l].r = (int16_t)floor(exp_re * 32767);
|
||||
symbol_rotation[l].i = (int16_t)floor(exp_im * 32767);
|
||||
|
||||
LOG_D(PHY, "Symbol rotation %d/%d => tl %f (%d,%d) (%f)\n",
|
||||
LOG_I(PHY, "Symbol rotation %d/%d => tl %f (%d,%d) (%f)\n",
|
||||
l,
|
||||
nsymb,
|
||||
tl,
|
||||
|
||||
@@ -45,7 +45,6 @@ void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRA
|
||||
{
|
||||
|
||||
|
||||
|
||||
PHY_ofdm_mod((int *)txdataF, // input
|
||||
(int *)txdata, // output
|
||||
frame_parms->ofdm_symbol_size,
|
||||
@@ -67,6 +66,7 @@ void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRA
|
||||
void nr_normal_prefix_mod(c16_t *txdataF, c16_t *txdata, uint8_t nsymb, const NR_DL_FRAME_PARMS *frame_parms, uint32_t slot)
|
||||
{
|
||||
// This function works only slot wise. For more generic symbol generation refer nr_feptx0()
|
||||
LOG_D(NR_PHY,"normal_prefix_mod: prefix0 %d, prefix %d, nsymb %d\n",frame_parms->nb_prefix_samples0,frame_parms->nb_prefix_samples,nsymb);
|
||||
if (frame_parms->numerology_index != 0) { // case where numerology != 0
|
||||
if (!(slot%(frame_parms->slots_per_subframe/2))) {
|
||||
PHY_ofdm_mod((int *)txdataF,
|
||||
|
||||
@@ -131,7 +131,7 @@ int slot_fep(PHY_VARS_UE *ue,
|
||||
// (frame_parms->ofdm_symbol_size+nb_prefix_samples)*(l-1);
|
||||
#ifdef DEBUG_FEP
|
||||
// if (ue->frame <100)
|
||||
LOG_I(PHY,"slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d, frame_length_samples %d\n",
|
||||
LOG_D(PHY,"slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d, frame_length_samples %d\n",
|
||||
ue->proc.proc_rxtx[(Ns>>1)&1].frame_rx,Ns, symbol,
|
||||
nb_prefix_samples,nb_prefix_samples0,slot_offset,subframe_offset,sample_offset,rx_offset,frame_length_samples);
|
||||
#endif
|
||||
@@ -206,7 +206,7 @@ int slot_fep(PHY_VARS_UE *ue,
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FEP
|
||||
printf("slot_fep: done\n");
|
||||
printf("slot_fep: Ns %d l %d, done\n",Ns,l);
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
@@ -316,7 +316,7 @@ int front_end_fft(PHY_VARS_UE *ue,
|
||||
// (frame_parms->ofdm_symbol_size+nb_prefix_samples)*(l-1);
|
||||
#ifdef DEBUG_FEP
|
||||
// if (ue->frame <100)
|
||||
LOG_I(PHY,
|
||||
LOG_D(PHY,
|
||||
"slot_fep: frame %d: slot %d, threadId %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d, frame_length_samples %d\n",
|
||||
ue->proc.proc_rxtx[threadId].frame_rx,Ns, threadId,symbol,
|
||||
nb_prefix_samples,nb_prefix_samples0,slot_offset,subframe_offset,sample_offset,rx_offset,frame_length_samples);
|
||||
|
||||
@@ -34,12 +34,107 @@
|
||||
#define LOG_I(A,B...) printf(A)
|
||||
#endif*/
|
||||
|
||||
int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
int sl_nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
unsigned char symbol,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
|
||||
unsigned char Ns,
|
||||
uint32_t sample_offset,
|
||||
c16_t rxdataF[][ue->SL_UE_PHY_PARAMS.sl_frame_params.samples_per_slot_wCP])
|
||||
{
|
||||
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
NR_DL_FRAME_PARMS *frame_params = &ue->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
NR_UE_COMMON *common_vars = &ue->common_vars;
|
||||
|
||||
AssertFatal(symbol < frame_params->symbols_per_slot, "slot_fep: symbol must be between 0 and %d\n", frame_params->symbols_per_slot-1);
|
||||
AssertFatal(Ns < frame_params->slots_per_frame, "slot_fep: Ns must be between 0 and %d\n", frame_params->slots_per_frame-1);
|
||||
|
||||
unsigned int nb_prefix_samples = frame_params->nb_prefix_samples;
|
||||
unsigned int nb_prefix_samples0 = frame_params->nb_prefix_samples0;
|
||||
|
||||
|
||||
dft_size_idx_t dftsize = get_dft(frame_params->ofdm_symbol_size);
|
||||
// This is for misalignment issues
|
||||
int32_t tmp_dft_in[8192] __attribute__ ((aligned (32)));
|
||||
|
||||
unsigned int rx_offset = frame_params->get_samples_slot_timestamp(Ns,frame_params,0);
|
||||
unsigned int abs_symbol = Ns * frame_params->symbols_per_slot + symbol;
|
||||
|
||||
rx_offset += sample_offset;
|
||||
rx_offset += ue->rx_offset;
|
||||
|
||||
for (int idx_symb = Ns*frame_params->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++)
|
||||
rx_offset += (idx_symb%(0x7<<frame_params->numerology_index)) ? nb_prefix_samples : nb_prefix_samples0;
|
||||
rx_offset += frame_params->ofdm_symbol_size * symbol;
|
||||
|
||||
// use OFDM symbol from within 1/8th of the CP to avoid ISI
|
||||
rx_offset -= (nb_prefix_samples / frame_params->ofdm_offset_divisor);
|
||||
|
||||
#ifdef SL_DEBUG_SLOT_FEP
|
||||
// if (ue->frame <100)
|
||||
LOG_I(PHY, "slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, rx_offset %u\n",
|
||||
Ns, symbol, nb_prefix_samples, nb_prefix_samples0, rx_offset);
|
||||
#endif
|
||||
|
||||
for (unsigned char aa=0; aa<frame_params->nb_antennas_rx; aa++) {
|
||||
memset(&rxdataF[aa][frame_params->ofdm_symbol_size*symbol],0,frame_params->ofdm_symbol_size*sizeof(int32_t));
|
||||
|
||||
int16_t *rxdata_ptr = (int16_t *)&common_vars->rxdata[aa][rx_offset];
|
||||
|
||||
// if input to dft is not 256-bit aligned
|
||||
if ((rx_offset & 7) != 0) {
|
||||
memcpy((void *)&tmp_dft_in[0],
|
||||
(void *)&common_vars->rxdata[aa][rx_offset],
|
||||
frame_params->ofdm_symbol_size * sizeof(int32_t));
|
||||
|
||||
rxdata_ptr = (int16_t *)tmp_dft_in;
|
||||
}
|
||||
|
||||
dft(dftsize,
|
||||
rxdata_ptr,
|
||||
(int16_t *)&rxdataF[aa][frame_params->ofdm_symbol_size*symbol],
|
||||
1);
|
||||
|
||||
|
||||
int symb_offset = (Ns%frame_params->slots_per_subframe)*frame_params->symbols_per_slot;
|
||||
int32_t rot2 = ((uint32_t*)frame_params->symbol_rotation[1])[symbol+symb_offset];
|
||||
((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1];
|
||||
|
||||
#ifdef SL_DEBUG_SLOT_FEP
|
||||
// if (ue->frame <100)
|
||||
LOG_I(PHY, "slot_fep: slot %d, symbol %d rx_offset %u, rotation symbol %d %d.%d\n", Ns,symbol, rx_offset,
|
||||
symbol+symb_offset,((int16_t*)&rot2)[0],((int16_t*)&rot2)[1]);
|
||||
#endif
|
||||
|
||||
rotate_cpx_vector((c16_t *)&rxdataF[aa][frame_params->ofdm_symbol_size*symbol],
|
||||
(c16_t *)&rot2,
|
||||
(c16_t *)&rxdataF[aa][frame_params->ofdm_symbol_size*symbol],
|
||||
frame_params->ofdm_symbol_size,
|
||||
15);
|
||||
|
||||
int16_t *shift_rot = (int16_t *)frame_params->timeshift_symbol_rotation;
|
||||
|
||||
multadd_cpx_vector((int16_t *)&rxdataF[aa][frame_params->ofdm_symbol_size*symbol],
|
||||
shift_rot,
|
||||
(int16_t *)&rxdataF[aa][frame_params->ofdm_symbol_size*symbol],
|
||||
1,
|
||||
frame_params->ofdm_symbol_size,
|
||||
15);
|
||||
}
|
||||
|
||||
|
||||
|
||||
LOG_D(PHY, "SIDELINK RX: Slot FEP: done for symbol:%d\n", symbol);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
unsigned char symbol,
|
||||
c16_t rxdataF[][frame_parms->samples_per_slot_wCP],
|
||||
uint32_t linktype)
|
||||
{
|
||||
|
||||
NR_UE_COMMON *common_vars = &ue->common_vars;
|
||||
int Ns = proc->nr_slot_rx;
|
||||
|
||||
@@ -67,13 +162,14 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
rx_offset += frame_parms->ofdm_symbol_size * symbol;
|
||||
|
||||
// use OFDM symbol from within 1/8th of the CP to avoid ISI
|
||||
rx_offset -= (nb_prefix_samples / frame_parms->ofdm_offset_divisor);
|
||||
// rx_offset -= (nb_prefix_samples / frame_parms->ofdm_offset_divisor);
|
||||
rx_offset += 1;
|
||||
|
||||
//#ifdef DEBUG_FEP
|
||||
#ifdef DEBUG_FEP
|
||||
// if (ue->frame <100)
|
||||
LOG_D(PHY,"slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, rx_offset %u energy %d\n",
|
||||
LOG_I(PHY,"slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, rx_offset %u energy %d\n",
|
||||
Ns, symbol, nb_prefix_samples, nb_prefix_samples0, rx_offset, dB_fixed(signal_energy((int32_t *)&common_vars->rxdata[0][rx_offset],frame_parms->ofdm_symbol_size)));
|
||||
//#endif
|
||||
#endif
|
||||
|
||||
for (unsigned char aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
||||
int16_t *rxdata_ptr = (int16_t *)&common_vars->rxdata[aa][rx_offset];
|
||||
@@ -96,18 +192,22 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
|
||||
stop_meas(&ue->rx_dft_stats);
|
||||
|
||||
/*
|
||||
LOG_I(NR_PHY,"%d.%d Applying rotation for symbol %d, linktype %d\n",
|
||||
proc->frame_rx,proc->nr_slot_rx,symbol,linktype);
|
||||
apply_nr_rotation_RX(frame_parms,
|
||||
rxdataF[aa],
|
||||
frame_parms->symbol_rotation[0],
|
||||
frame_parms->symbol_rotation[linktype],
|
||||
Ns,
|
||||
frame_parms->N_RB_DL,
|
||||
0,
|
||||
symbol,
|
||||
1);
|
||||
linktype);
|
||||
*/
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FEP
|
||||
printf("slot_fep: done\n");
|
||||
LOG_I(NR_PHY,"slot_fep: done for Ns %d symbol %d\n",Ns,symbol);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
@@ -297,7 +397,6 @@ void apply_nr_rotation_RX(NR_DL_FRAME_PARMS *frame_parms,
|
||||
|
||||
c16_t rot2 = rot[symbol + symb_offset];
|
||||
rot2.i = -rot2.i;
|
||||
LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n", slot, symb_offset, rot2.r, rot2.i);
|
||||
c16_t *shift_rot = frame_parms->timeshift_symbol_rotation;
|
||||
c16_t *this_symbol = &rxdataF[soffset + (frame_parms->ofdm_symbol_size * symbol)];
|
||||
|
||||
|
||||
@@ -220,7 +220,8 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB,int slot, int first_symb,int num_symb
|
||||
//
|
||||
// Todo:
|
||||
// - averaging IIR filter for RX power and noise
|
||||
void nr_gnb_measurements(PHY_VARS_gNB *gNB,
|
||||
void nr_gnb_measurements(PHY_MEASUREMENTS_gNB *meas,
|
||||
NR_DL_FRAME_PARMS *fp,
|
||||
NR_gNB_ULSCH_t *ulsch,
|
||||
NR_gNB_PUSCH *pusch_vars,
|
||||
unsigned char symbol,
|
||||
@@ -232,8 +233,6 @@ void nr_gnb_measurements(PHY_VARS_gNB *gNB,
|
||||
|
||||
double rx_gain = openair0_cfg[0].rx_gain[0];
|
||||
double rx_gain_offset = openair0_cfg[0].rx_gain_offset[0];
|
||||
PHY_MEASUREMENTS_gNB *meas = &gNB->measurements;
|
||||
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
|
||||
int ch_offset = fp->ofdm_symbol_size * symbol;
|
||||
int N_RB_UL = ulsch->harq_process->ulsch_pdu.rb_size;
|
||||
ulsch_measurements_gNB *ulsch_measurements = &ulsch->ulsch_measurements;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "nr_ul_estimation.h"
|
||||
#include "PHY/sse_intrin.h"
|
||||
#include "PHY/NR_REFSIG/nr_refsig.h"
|
||||
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
|
||||
#include "PHY/NR_REFSIG/dmrs_nr.h"
|
||||
#include "PHY/NR_REFSIG/ptrs_nr.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
@@ -117,34 +118,39 @@ int get_delay_idx(int delay) {
|
||||
}
|
||||
|
||||
int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
int rxFSz,
|
||||
c16_t rxdataF[][rxFSz],
|
||||
unsigned char Ns,
|
||||
unsigned short p,
|
||||
unsigned char symbol,
|
||||
int ul_id,
|
||||
unsigned short bwp_start_subcarrier,
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
sl_nr_rx_config_pssch_sci_pdu_t *pssch_pdu,
|
||||
int *max_ch,
|
||||
uint32_t *nvar) {
|
||||
|
||||
c16_t pilot[3280] __attribute__((aligned(32)));
|
||||
const int chest_freq = gNB->chest_freq;
|
||||
const int chest_freq = gNB ? gNB->chest_freq : ue->chest_freq;
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
FILE *debug_ch_est;
|
||||
debug_ch_est = fopen("debug_ch_est.txt","w");
|
||||
#endif
|
||||
//uint16_t Nid_cell = (eNB_offset == 0) ? gNB->frame_parms.Nid_cell : gNB->measurements.adj_cell_id[eNB_offset-1];
|
||||
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ul_id];
|
||||
NR_gNB_PUSCH *pusch_vars = gNB ? &gNB->pusch_vars[ul_id] : &ue->pssch_vars[ul_id];
|
||||
c16_t **ul_ch_estimates = (c16_t **)pusch_vars->ul_ch_estimates;
|
||||
const int symbolSize = gNB->frame_parms.ofdm_symbol_size;
|
||||
const int soffset = (Ns&3)*gNB->frame_parms.symbols_per_slot*symbolSize;
|
||||
const int symbolSize = gNB ? gNB->frame_parms.ofdm_symbol_size : ue->SL_UE_PHY_PARAMS.sl_frame_params.ofdm_symbol_size;
|
||||
const int soffset = 0;//(Ns&3)*(gNB?gNB->frame_parms.symbols_per_slot:(ue->SL_UE_PHY_PARAMS.sl_frame_params.symbols_per_slot)*symbolSize);
|
||||
const int nushift = (p>>1)&1;
|
||||
gNB->frame_parms.nushift = nushift;
|
||||
if (gNB) gNB->frame_parms.nushift = nushift;
|
||||
else ue->SL_UE_PHY_PARAMS.sl_frame_params.nushift = nushift;
|
||||
int ch_offset = symbolSize*symbol;
|
||||
const int symbol_offset = symbolSize*symbol;
|
||||
|
||||
const int k0 = bwp_start_subcarrier;
|
||||
const int nb_rb_pusch = pusch_pdu->rb_size;
|
||||
const int nb_rb_pusch = gNB ? pusch_pdu->rb_size : pssch_pdu->subchannel_size*pssch_pdu->l_subch;
|
||||
|
||||
LOG_D(PHY, "In %s: ch_offset %d, soffset %d, symbol_offset %d, OFDM size %d, Ns = %d, k0 = %d, symbol %d\n",
|
||||
__FUNCTION__,
|
||||
@@ -157,14 +163,23 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
|
||||
//------------------generate DMRS------------------//
|
||||
|
||||
if(pusch_pdu->ul_dmrs_scrambling_id != gNB->pusch_gold_init[pusch_pdu->scid]) {
|
||||
if(gNB && pusch_pdu->ul_dmrs_scrambling_id != gNB->pusch_gold_init[pusch_pdu->scid]) {
|
||||
gNB->pusch_gold_init[pusch_pdu->scid] = pusch_pdu->ul_dmrs_scrambling_id;
|
||||
nr_gold_pusch(gNB, pusch_pdu->scid, pusch_pdu->ul_dmrs_scrambling_id);
|
||||
}
|
||||
|
||||
if (pusch_pdu->transform_precoding == transformPrecoder_disabled) {
|
||||
nr_pusch_dmrs_rx(gNB, Ns, gNB->nr_gold_pusch_dmrs[pusch_pdu->scid][Ns][symbol], (int32_t *)pilot, (1000+p), 0, nb_rb_pusch,
|
||||
(pusch_pdu->bwp_start + pusch_pdu->rb_start)*NR_NB_SC_PER_RB, pusch_pdu->dmrs_config_type);
|
||||
if (ue || pusch_pdu->transform_precoding == transformPrecoder_disabled) {
|
||||
if (gNB) nr_pusch_dmrs_rx(NORMAL, Ns, gNB->nr_gold_pusch_dmrs[pusch_pdu->scid][Ns][symbol], (int32_t *)pilot, (1000+p), 0, nb_rb_pusch,
|
||||
(pusch_pdu->bwp_start + pusch_pdu->rb_start)*NR_NB_SC_PER_RB, pusch_pdu->dmrs_config_type);
|
||||
else {
|
||||
// compute gold sequence based on Nid from SCI1A
|
||||
int nb_re = ue->SL_UE_PHY_PARAMS.sl_frame_params.N_RB_UL*12;
|
||||
uint32_t pssch_dmrs[(nb_re>>5)+1];
|
||||
nr_init_pssch_dmrs_oneshot(&ue->SL_UE_PHY_PARAMS.sl_frame_params,pssch_pdu->Nid,pssch_dmrs,Ns,symbol);
|
||||
// call nr_pusch_dmrs_rx`
|
||||
nr_pusch_dmrs_rx(NORMAL, Ns, pssch_dmrs, (int32_t *)pilot, (1000+p), 0, nb_rb_pusch,
|
||||
(pssch_pdu->startrb)*NR_NB_SC_PER_RB, 0);
|
||||
}
|
||||
} else { // if transform precoding or SC-FDMA is enabled in Uplink
|
||||
// NR_SC_FDMA supports type1 DMRS so only 6 DMRS REs per RB possible
|
||||
const uint16_t index = get_index_for_dmrs_lowpapr_seq(nb_rb_pusch * (NR_NB_SC_PER_RB/2));
|
||||
@@ -176,7 +191,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
AssertFatal(dmrs_seq != NULL, "DMRS low PAPR seq not found, check if DMRS sequences are generated");
|
||||
nr_pusch_lowpaprtype1_dmrs_rx(gNB, Ns, dmrs_seq, (int32_t *)pilot, 1000, 0, nb_rb_pusch, 0, pusch_pdu->dmrs_config_type);
|
||||
#ifdef DEBUG_PUSCH
|
||||
printf ("NR_UL_CHANNEL_EST: index %d, u %d,v %d\n", index, u, v);
|
||||
LOG_I(NR_PHY,"NR_UL_CHANNEL_EST: index %d, u %d,v %d\n", index, u, v);
|
||||
LOG_M("gNb_DMRS_SEQ.m","gNb_DMRS_SEQ", dmrs_seq,6*nb_rb_pusch,1,1);
|
||||
#endif
|
||||
}
|
||||
@@ -194,22 +209,23 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
uint64_t noise_amp2 = 0;
|
||||
c16_t ul_ls_est[symbolSize] __attribute__((aligned(32)));
|
||||
memset(ul_ls_est, 0, sizeof(c16_t) * symbolSize);
|
||||
NR_ULSCH_delay_t *delay = &gNB->ulsch[ul_id].delay;
|
||||
NR_ULSCH_delay_t *delay = gNB ? &gNB->ulsch[ul_id].delay : &ue->slsch[ul_id].delay;
|
||||
memset(delay, 0, sizeof(*delay));
|
||||
|
||||
for (int aarx=0; aarx<gNB->frame_parms.nb_antennas_rx; aarx++) {
|
||||
c16_t *rxdataF = (c16_t *)&gNB->common_vars.rxdataF[aarx][symbol_offset];
|
||||
c16_t *ul_ch = &ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset];
|
||||
NR_DL_FRAME_PARMS *fp = gNB ? &gNB->frame_parms : &ue->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
int nrx = fp->nb_antennas_rx;
|
||||
for (int aarx=0; aarx<nrx; aarx++) {
|
||||
c16_t *rxdataF2 = (c16_t *)&rxdataF[aarx][symbol_offset];
|
||||
c16_t *ul_ch = &ul_ch_estimates[p*nrx+aarx][ch_offset];
|
||||
|
||||
memset(ul_ch,0,sizeof(*ul_ch)*symbolSize);
|
||||
#ifdef DEBUG_PUSCH
|
||||
LOG_I(PHY, "In %s symbol_offset %d, nushift %d\n", __FUNCTION__, symbol_offset, nushift);
|
||||
LOG_I(PHY, "In %s ch est pilot, N_RB_UL %d\n", __FUNCTION__, gNB->frame_parms.N_RB_UL);
|
||||
LOG_I(PHY, "In %s bwp_start_subcarrier %d, k0 %d, first_carrier %d, nb_rb_pusch %d\n", __FUNCTION__, bwp_start_subcarrier, k0, gNB->frame_parms.first_carrier_offset, nb_rb_pusch);
|
||||
LOG_I(PHY, "In %s ch est pilot, N_RB_UL %d\n", __FUNCTION__, fp->N_RB_UL);
|
||||
LOG_I(PHY, "In %s bwp_start_subcarrier %d, k0 %d, first_carrier %d, nb_rb_pusch %d\n", __FUNCTION__, bwp_start_subcarrier, k0, fp->first_carrier_offset, nb_rb_pusch);
|
||||
LOG_I(PHY, "In %s ul_ch addr %p nushift %d\n", __FUNCTION__, ul_ch, nushift);
|
||||
#endif
|
||||
|
||||
if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1 && chest_freq == 0) {
|
||||
if ((ue || pusch_pdu->dmrs_config_type == pusch_dmrs_type1) && chest_freq == 0) {
|
||||
c16_t *pil = pilot;
|
||||
int re_offset = k0;
|
||||
LOG_D(PHY,"PUSCH estimation DMRS type 1, Freq-domain interpolation");
|
||||
@@ -224,7 +240,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
|
||||
for (int k_line = 0; k_line <= 1; k_line++) {
|
||||
re_offset = (k0 + (n << 2) + (k_line << 1) + delta) % symbolSize;
|
||||
ch = c32x16maddShift(*pil, rxdataF[soffset + re_offset], ch, 16);
|
||||
ch = c32x16maddShift(*pil, rxdataF2[soffset + re_offset], ch, 16);
|
||||
pil++;
|
||||
}
|
||||
|
||||
@@ -238,13 +254,13 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
|
||||
freq2time(symbolSize, (int16_t *)ul_ls_est, (int16_t *)pusch_vars->ul_ch_estimates_time[aarx]);
|
||||
|
||||
nr_est_timing_advance_pusch(&gNB->frame_parms, pusch_vars->ul_ch_estimates_time[aarx], delay);
|
||||
nr_est_timing_advance_pusch(fp, pusch_vars->ul_ch_estimates_time[aarx], delay);
|
||||
int pusch_delay = delay->pusch_est_delay;
|
||||
int delay_idx = get_delay_idx(pusch_delay);
|
||||
c16_t *ul_delay_table = gNB->frame_parms.ul_delay_table[delay_idx];
|
||||
c16_t *ul_delay_table = fp->ul_delay_table[delay_idx];
|
||||
|
||||
#ifdef DEBUG_PUSCH
|
||||
printf("Estimated delay = %i\n", pusch_delay >> 1);
|
||||
LOG_I(NR_PHY,"Estimated delay = %i\n", pusch_delay >> 1);
|
||||
#endif
|
||||
|
||||
pilot_cnt = 0;
|
||||
@@ -259,9 +275,9 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
|
||||
#ifdef DEBUG_PUSCH
|
||||
re_offset = (k0 + (n << 2) + (k_line << 1)) % symbolSize;
|
||||
c16_t *rxF = &rxdataF[soffset + re_offset];
|
||||
printf("pilot %4d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d)\n",
|
||||
pilot_cnt, pil->r, pil->i, rxF->r, rxF->i, ch.r, ch.i);
|
||||
c16_t *rxF = &rxdataF2[soffset + re_offset];
|
||||
LOG_I(NR_PHY,"pilot %4d: ul_delay` -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d)\n",
|
||||
pilot_cnt, ul_delay_table[k].r, ul_delay_table[k].i, rxF->r, rxF->i, ch16.r, ch16.i);
|
||||
#endif
|
||||
|
||||
if (pilot_cnt == 0) {
|
||||
@@ -283,9 +299,9 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
|
||||
// Revert delay
|
||||
pilot_cnt = 0;
|
||||
ul_ch = &ul_ch_estimates[p * gNB->frame_parms.nb_antennas_rx + aarx][ch_offset];
|
||||
ul_ch = &ul_ch_estimates[p * nrx + aarx][ch_offset];
|
||||
int inv_delay_idx = get_delay_idx(-pusch_delay);
|
||||
c16_t *ul_inv_delay_table = gNB->frame_parms.ul_delay_table[inv_delay_idx];
|
||||
c16_t *ul_inv_delay_table = fp->ul_delay_table[inv_delay_idx];
|
||||
for (int n = 0; n < 3 * nb_rb_pusch; n++) {
|
||||
for (int k_line = 0; k_line <= 1; k_line++) {
|
||||
int k = pilot_cnt << 1;
|
||||
@@ -296,18 +312,18 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
|
||||
#ifdef DEBUG_PUSCH
|
||||
re_offset = (k0 + (n << 2) + (k_line << 1)) % symbolSize;
|
||||
c16_t *rxF = &rxdataF[soffset + re_offset];
|
||||
printf("ch -> (%4d,%4d), ch_inter -> (%4d,%4d)\n", ul_ls_est[k].r, ul_ls_est[k].i, ul_ch[k].r, ul_ch[k].i);
|
||||
c16_t *rxF = &rxdataF2[soffset + re_offset];
|
||||
LOG_I(NR_PHY,"ch -> (%4d,%4d), ch_inter -> (%4d,%4d)\n", ul_ls_est[k].r, ul_ls_est[k].i, ul_ch[k].r, ul_ch[k].i);
|
||||
#endif
|
||||
pilot_cnt++;
|
||||
nest_count += 2;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type2 && chest_freq == 0) { // pusch_dmrs_type2 |p_r,p_l,d,d,d,d,p_r,p_l,d,d,d,d|
|
||||
} else if (gNB && pusch_pdu->dmrs_config_type == pusch_dmrs_type2 && chest_freq == 0) { // pusch_dmrs_type2 |p_r,p_l,d,d,d,d,p_r,p_l,d,d,d,d|
|
||||
LOG_D(PHY, "PUSCH estimation DMRS type 2, Freq-domain interpolation\n");
|
||||
c16_t *pil = pilot;
|
||||
c16_t *rx = &rxdataF[soffset + nushift];
|
||||
c16_t *rx = &rxdataF2[soffset + nushift];
|
||||
for (int n = 0; n < nb_rb_pusch * NR_NB_SC_PER_RB; n += 6) {
|
||||
c16_t ch0 = c16mulShift(*pil, rx[(k0 + n) % symbolSize], 15);
|
||||
pil++;
|
||||
@@ -334,9 +350,9 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
|
||||
}
|
||||
|
||||
else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1) { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB
|
||||
else if (ue || pusch_pdu->dmrs_config_type == pusch_dmrs_type1) { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB
|
||||
LOG_D(PHY,"PUSCH estimation DMRS type 1, no Freq-domain interpolation\n");
|
||||
c16_t *rxF = &rxdataF[soffset + nushift];
|
||||
c16_t *rxF = &rxdataF2[soffset + nushift];
|
||||
int pil_offset = 0;
|
||||
int re_offset = k0;
|
||||
c16_t ch;
|
||||
@@ -398,23 +414,23 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
c32_t ch0={0};
|
||||
//First PRB
|
||||
ch0=c32x16mulShift(*pil,
|
||||
rxdataF[soffset + nushift + re_offset],
|
||||
rxdataF2[soffset + nushift + re_offset],
|
||||
15);
|
||||
pil++;
|
||||
re_offset = (re_offset+1) % symbolSize;
|
||||
ch0=c32x16maddShift(*pil,
|
||||
rxdataF[nushift+re_offset],
|
||||
rxdataF2[nushift+re_offset],
|
||||
ch0,
|
||||
15);
|
||||
pil++;
|
||||
re_offset = (re_offset+5) % symbolSize;
|
||||
ch0=c32x16maddShift(*pil,
|
||||
rxdataF[nushift+re_offset],
|
||||
rxdataF2[nushift+re_offset],
|
||||
ch0,
|
||||
15);
|
||||
re_offset = (re_offset+1) % symbolSize;
|
||||
ch0=c32x16maddShift(*pil,
|
||||
rxdataF[nushift+re_offset],
|
||||
rxdataF2[nushift+re_offset],
|
||||
ch0,
|
||||
15);
|
||||
pil++;
|
||||
@@ -435,19 +451,19 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
|
||||
for (int pilot_cnt=4; pilot_cnt<4*(nb_rb_pusch-1); pilot_cnt += 4) {
|
||||
c32_t ch0;
|
||||
ch0=c32x16mulShift(*pil, rxdataF[nushift+re_offset], 15);
|
||||
ch0=c32x16mulShift(*pil, rxdataF2[nushift+re_offset], 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+1) % symbolSize;
|
||||
|
||||
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
|
||||
ch0=c32x16maddShift(*pil, rxdataF2[nushift+re_offset], ch0, 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+5) % symbolSize;
|
||||
|
||||
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
|
||||
ch0=c32x16maddShift(*pil, rxdataF2[nushift+re_offset], ch0, 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+1) % symbolSize;
|
||||
|
||||
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
|
||||
ch0=c32x16maddShift(*pil, rxdataF2[nushift+re_offset], ch0, 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+5) % symbolSize;
|
||||
|
||||
@@ -470,19 +486,19 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
}
|
||||
|
||||
// Last PRB
|
||||
ch0=c32x16mulShift(*pil, rxdataF[nushift+re_offset], 15);
|
||||
ch0=c32x16mulShift(*pil, rxdataF2[nushift+re_offset], 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+1) % symbolSize;
|
||||
|
||||
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
|
||||
ch0=c32x16maddShift(*pil, rxdataF2[nushift+re_offset], ch0, 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+5) % symbolSize;
|
||||
|
||||
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
|
||||
ch0=c32x16maddShift(*pil, rxdataF2[nushift+re_offset], ch0, 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+1) % symbolSize;
|
||||
|
||||
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
|
||||
ch0=c32x16maddShift(*pil, rxdataF2[nushift+re_offset], ch0, 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+5) % symbolSize;
|
||||
|
||||
@@ -500,12 +516,12 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PUSCH
|
||||
ul_ch = &ul_ch_estimates[p * gNB->frame_parms.nb_antennas_rx + aarx][ch_offset];
|
||||
ul_ch = &ul_ch_estimates[p * (gNB?gNB->frame_parms.nb_antennas_rx:ue->SL_UE_PHY_PARAMS.sl_frame_params.nb_antennas_rx) + aarx][ch_offset];
|
||||
for (int idxP = 0; idxP < ceil((float)nb_rb_pusch * 12 / 8); idxP++) {
|
||||
for (int idxI = 0; idxI < 8; idxI++) {
|
||||
printf("%d\t%d\t", ul_ch[idxP * 8 + idxI].r, ul_ch[idxP * 8 + idxI].i);
|
||||
LOG_I(NR_PHY,"%d\t%d\t", ul_ch[idxP * 8 + idxI].r, ul_ch[idxP * 8 + idxI].i);
|
||||
}
|
||||
printf("%d\n", idxP);
|
||||
LOG_I(NR_PHY,"%d\n", idxP);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -545,28 +561,33 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
* 3) Compensated DMRS based estimated signal with PTRS estimation for slot
|
||||
*********************************************************************/
|
||||
void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
|
||||
struct PHY_VARS_NR_UE_s *ue,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
nfapi_nr_pusch_pdu_t *rel15_ul,
|
||||
sl_nr_rx_config_pssch_sci_pdu_t *pssch_pdu,
|
||||
uint8_t ulsch_id,
|
||||
uint8_t nr_tti_rx,
|
||||
unsigned char symbol,
|
||||
uint32_t nb_re_pusch)
|
||||
{
|
||||
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id];
|
||||
NR_gNB_PUSCH *pusch_vars = gNB ? &gNB->pusch_vars[ulsch_id] : &ue->pssch_vars[ulsch_id];
|
||||
//#define DEBUG_UL_PTRS 1
|
||||
int32_t *ptrs_re_symbol = NULL;
|
||||
int8_t ret = 0;
|
||||
uint8_t symbInSlot = rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols;
|
||||
uint8_t *startSymbIndex = &rel15_ul->start_symbol_index;
|
||||
uint8_t *nbSymb = &rel15_ul->nr_of_symbols;
|
||||
uint8_t *L_ptrs = &rel15_ul->pusch_ptrs.ptrs_time_density;
|
||||
uint8_t *K_ptrs = &rel15_ul->pusch_ptrs.ptrs_freq_density;
|
||||
uint16_t *dmrsSymbPos = &rel15_ul->ul_dmrs_symb_pos;
|
||||
uint8_t symbInSlot = gNB ? (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols) : (1 + pssch_pdu->pssch_numsym);
|
||||
uint8_t sl_startSymbIndex = 1;
|
||||
uint8_t *startSymbIndex = gNB ? &rel15_ul->start_symbol_index : &sl_startSymbIndex;
|
||||
uint8_t *nbSymb = gNB ? &rel15_ul->nr_of_symbols : &pssch_pdu->pssch_numsym;
|
||||
uint8_t *L_ptrs = gNB ? &rel15_ul->pusch_ptrs.ptrs_time_density : NULL;
|
||||
uint8_t *K_ptrs = gNB ? &rel15_ul->pusch_ptrs.ptrs_freq_density:NULL;
|
||||
uint16_t *dmrsSymbPos = gNB ? &rel15_ul->ul_dmrs_symb_pos : &pssch_pdu->dmrs_symbol_position;
|
||||
uint16_t *ptrsSymbPos = &pusch_vars->ptrs_symbols;
|
||||
uint8_t *ptrsSymbIdx = &pusch_vars->ptrs_symbol_index;
|
||||
uint8_t *dmrsConfigType = &rel15_ul->dmrs_config_type;
|
||||
uint16_t *nb_rb = &rel15_ul->rb_size;
|
||||
uint8_t *ptrsReOffset = &rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset;
|
||||
uint8_t sl_dmrsConfigType = 0;
|
||||
uint8_t *dmrsConfigType = gNB ? &rel15_ul->dmrs_config_type : &sl_dmrsConfigType;
|
||||
uint16_t sl_nb_rb = pssch_pdu->num_subch * pssch_pdu->subchannel_size;
|
||||
uint16_t *nb_rb = gNB ? &rel15_ul->rb_size : &sl_nb_rb;
|
||||
uint8_t *ptrsReOffset = gNB ? &rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset : NULL;
|
||||
|
||||
/* loop over antennas */
|
||||
for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
/** @addtogroup _PHY_PARAMETER_ESTIMATION_BLOCKS_
|
||||
* @{
|
||||
*/
|
||||
@@ -41,12 +42,16 @@
|
||||
*/
|
||||
|
||||
int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
int rxFSz,
|
||||
c16_t rxdataF[][rxFSz],
|
||||
unsigned char Ns,
|
||||
unsigned short p,
|
||||
unsigned char symbol,
|
||||
int ul_id,
|
||||
unsigned short bwp_start_subcarrier,
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
sl_nr_rx_config_pssch_sci_pdu_t *pssch_pdu,
|
||||
int *max_ch,
|
||||
uint32_t *nvar);
|
||||
|
||||
@@ -54,7 +59,8 @@ void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB);
|
||||
|
||||
void gNB_I0_measurements(PHY_VARS_gNB *gNB,int slot,int first_symb,int num_symb);
|
||||
|
||||
void nr_gnb_measurements(PHY_VARS_gNB *gNB,
|
||||
void nr_gnb_measurements(PHY_MEASUREMENTS_gNB *meas,
|
||||
NR_DL_FRAME_PARMS *fp,
|
||||
NR_gNB_ULSCH_t *ulsch,
|
||||
NR_gNB_PUSCH *pusch_vars,
|
||||
unsigned char symbol,
|
||||
@@ -68,8 +74,10 @@ int nr_est_timing_advance_srs(const NR_DL_FRAME_PARMS *frame_parms,
|
||||
const int32_t srs_estimated_channel_time[][frame_parms->ofdm_symbol_size]);
|
||||
|
||||
void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
|
||||
struct PHY_VARS_NR_UE_s *ue,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
nfapi_nr_pusch_pdu_t *rel15_ul,
|
||||
sl_nr_rx_config_pssch_sci_pdu_t *pssch_pdu,
|
||||
uint8_t ulsch_id,
|
||||
uint8_t nr_tti_rx,
|
||||
unsigned char symbol,
|
||||
|
||||
@@ -63,7 +63,7 @@ int nr_pusch_dmrs_delta(uint8_t dmrs_config_type, unsigned short p) {
|
||||
}
|
||||
}
|
||||
|
||||
int nr_pusch_dmrs_rx(PHY_VARS_gNB *gNB,
|
||||
int nr_pusch_dmrs_rx(int Ncp,
|
||||
unsigned int Ns,
|
||||
unsigned int *nr_gold_pusch,
|
||||
int32_t *output,
|
||||
@@ -86,7 +86,7 @@ int nr_pusch_dmrs_rx(PHY_VARS_gNB *gNB,
|
||||
LOG_E(PHY,"PUSCH DMRS config type %d not valid\n", dmrs_type+1);
|
||||
|
||||
if ((p>=1000) && (p<((dmrs_type==pusch_dmrs_type1) ? 1008 : 1012))) {
|
||||
if (gNB->frame_parms.Ncp == NORMAL) {
|
||||
if (Ncp == NORMAL) {
|
||||
nb_dmrs = ((dmrs_type==pusch_dmrs_type1) ? 6:4);
|
||||
for (int i=dmrs_offset; i<dmrs_offset+(nb_pusch_rb*nb_dmrs); i++) {
|
||||
k = i-dmrs_offset;
|
||||
@@ -197,22 +197,30 @@ int nr_pdcch_dmrs_rx(PHY_VARS_NR_UE *ue,
|
||||
|
||||
int nr_pbch_dmrs_rx(int symbol,
|
||||
unsigned int *nr_gold_pbch,
|
||||
int32_t *output)
|
||||
int32_t *output,
|
||||
bool sidelink)
|
||||
{
|
||||
int m,m0,m1;
|
||||
uint8_t idx=0;
|
||||
AssertFatal(symbol>=0 && symbol <3,"illegal symbol %d\n",symbol);
|
||||
if (symbol == 0) {
|
||||
m0=0;
|
||||
m1=60;
|
||||
}
|
||||
else if (symbol == 1) {
|
||||
m0=60;
|
||||
m1=84;
|
||||
}
|
||||
else {
|
||||
m0=84;
|
||||
m1=144;
|
||||
if (sidelink) {
|
||||
AssertFatal(symbol== 0 || (symbol>=5 && symbol <=12),"illegal symbol %d\n",symbol);
|
||||
m0 = (symbol) ? (symbol - 4) * 33 : 0;
|
||||
m1 = (symbol) ? (symbol - 3) * 33 : 33;
|
||||
|
||||
} else {
|
||||
AssertFatal(symbol>=0 && symbol <3,"illegal symbol %d\n",symbol);
|
||||
if (symbol == 0) {
|
||||
m0=0;
|
||||
m1=60;
|
||||
}
|
||||
else if (symbol == 1) {
|
||||
m0=60;
|
||||
m1=84;
|
||||
}
|
||||
else {
|
||||
m0=84;
|
||||
m1=144;
|
||||
}
|
||||
}
|
||||
// printf("Generating pilots symbol %d, m0 %d, m1 %d\n",symbol,m0,m1);
|
||||
/// QPSK modulation
|
||||
|
||||
@@ -53,12 +53,10 @@ void nr_init_pbch_dmrs(PHY_VARS_gNB* gNB)
|
||||
|
||||
}
|
||||
|
||||
void nr_init_pdcch_dmrs(PHY_VARS_gNB* gNB, uint32_t Nid)
|
||||
void nr_init_pdcch_dmrs(NR_DL_FRAME_PARMS *fp, uint32_t ***pdcch_dmrs, uint32_t Nid)
|
||||
{
|
||||
uint32_t x1 = 0, x2 = 0;
|
||||
uint8_t reset;
|
||||
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
|
||||
uint32_t ***pdcch_dmrs = gNB->nr_gold_pdcch_dmrs;
|
||||
int pdcch_dmrs_init_length = (((fp->N_RB_DL<<1)*3)>>5)+1;
|
||||
|
||||
for (uint8_t slot=0; slot<fp->slots_per_frame; slot++) {
|
||||
|
||||
@@ -51,21 +51,20 @@ void nr_gold_pbch(PHY_VARS_NR_UE* ue)
|
||||
|
||||
}
|
||||
|
||||
void nr_gold_pdcch(PHY_VARS_NR_UE* ue,
|
||||
unsigned short nid)
|
||||
void nr_gold_pdcch(NR_DL_FRAME_PARMS *fp, uint32_t ***nr_gold,uint16_t nid)
|
||||
{
|
||||
unsigned int n = 0, x1 = 0, x2 = 0, x2tmp0 = 0;
|
||||
uint8_t reset;
|
||||
int pdcch_dmrs_init_length = (((ue->frame_parms.N_RB_DL << 1) * 3) >> 5) + 1;
|
||||
int pdcch_dmrs_init_length = (((fp->N_RB_DL << 1) * 3) >> 5) + 1;
|
||||
|
||||
for (int ns = 0; ns < ue->frame_parms.slots_per_frame; ns++) {
|
||||
for (int l = 0; l < ue->frame_parms.symbols_per_slot; l++) {
|
||||
for (int ns = 0; ns < fp->slots_per_frame; ns++) {
|
||||
for (int l = 0; l < fp->symbols_per_slot; l++) {
|
||||
reset = 1;
|
||||
x2tmp0 = ((ue->frame_parms.symbols_per_slot * ns + l + 1) * ((nid << 1) + 1));
|
||||
x2tmp0 = ((fp->symbols_per_slot * ns + l + 1) * ((nid << 1) + 1));
|
||||
x2tmp0 <<= 17;
|
||||
x2 = (x2tmp0 + (nid << 1)) % (1U << 31); //cinit
|
||||
for (n=0; n<pdcch_dmrs_init_length; n++) {
|
||||
ue->nr_gold_pdcch[0][ns][l][n] = lte_gold_generic(&x1, &x2, reset);
|
||||
nr_gold[ns][l][n] = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
}
|
||||
}
|
||||
@@ -118,6 +117,24 @@ void nr_init_pusch_dmrs(PHY_VARS_NR_UE* ue,
|
||||
}
|
||||
}
|
||||
|
||||
void nr_init_pssch_dmrs_oneshot(NR_DL_FRAME_PARMS *fp,
|
||||
uint16_t N_id,
|
||||
uint32_t *pssch_dmrs,
|
||||
int slot,
|
||||
int symb)
|
||||
{
|
||||
uint32_t x1 = 0, x2 = 0, n = 0;
|
||||
int pusch_dmrs_init_length = ((fp->N_RB_UL * 12) >> 5) + 1;
|
||||
|
||||
int reset = 1;
|
||||
x2 = ((1U << 17) * (fp->symbols_per_slot*slot + symb + 1) * ((N_id << 1) + 1) + (N_id << 1) );
|
||||
LOG_D(PHY,"DMRS slot %d, symb %d x2 %x\n", slot, symb, x2);
|
||||
for (n=0; n<pusch_dmrs_init_length; n++) {
|
||||
pssch_dmrs[n] = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void init_nr_gold_prs(PHY_VARS_NR_UE* ue)
|
||||
{
|
||||
unsigned int x1 = 0, x2 = 0;
|
||||
|
||||
@@ -43,7 +43,7 @@ void nr_init_prs(PHY_VARS_gNB* gNB);
|
||||
@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
|
||||
*/
|
||||
void nr_init_pdcch_dmrs(PHY_VARS_gNB* gNB, uint32_t Nid);
|
||||
void nr_init_pdcch_dmrs(NR_DL_FRAME_PARMS *fp,uint32_t ***pdcch_dmrs, uint32_t Nid);
|
||||
void nr_init_pdsch_dmrs(PHY_VARS_gNB* gNB, uint8_t nscid, uint32_t Nid);
|
||||
void nr_init_csi_rs(const NR_DL_FRAME_PARMS *fp, uint32_t ***csi_rs, uint32_t Nid);
|
||||
|
||||
@@ -51,7 +51,7 @@ void nr_gold_pusch(PHY_VARS_gNB* gNB, int nscid, uint32_t nid);
|
||||
|
||||
int nr_pusch_dmrs_delta(uint8_t dmrs_config_type, unsigned short p);
|
||||
|
||||
int nr_pusch_dmrs_rx(PHY_VARS_gNB *gNB,
|
||||
int nr_pusch_dmrs_rx(int Ncp,
|
||||
unsigned int Ns,
|
||||
unsigned int *nr_gold_pusch,
|
||||
int32_t *output,
|
||||
|
||||
@@ -27,13 +27,32 @@
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/LTE_REFSIG/lte_refsig.h"
|
||||
|
||||
typedef struct port_freq_indices {
|
||||
uint8_t p;
|
||||
uint16_t k;
|
||||
} port_freq_indices_t;
|
||||
|
||||
typedef struct csi_rs_params {
|
||||
uint8_t size;
|
||||
uint8_t j[16];
|
||||
uint8_t k_n[6];
|
||||
uint8_t kprime;
|
||||
uint8_t lprime;
|
||||
uint8_t ports;
|
||||
uint8_t koverline[16];
|
||||
uint8_t loverline[16];
|
||||
double rho;
|
||||
double alpha;
|
||||
uint8_t gs;
|
||||
} csi_rs_params_t;
|
||||
|
||||
/*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PBCH DMRS.
|
||||
@param PHY_VARS_NR_UE* ue structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables
|
||||
*/
|
||||
int nr_pbch_dmrs_rx(int dmrss,
|
||||
unsigned int *nr_gold_pbch,
|
||||
int32_t *output);
|
||||
int32_t *output,
|
||||
bool sidelink);
|
||||
|
||||
/*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PDCCH DMRS.
|
||||
@param PHY_VARS_NR_UE* ue structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables
|
||||
@@ -56,8 +75,8 @@ int nr_pdsch_dmrs_rx(PHY_VARS_NR_UE *ue,
|
||||
|
||||
void nr_gold_pbch(PHY_VARS_NR_UE* ue);
|
||||
|
||||
void nr_gold_pdcch(PHY_VARS_NR_UE* ue,
|
||||
unsigned short n_idDMRS);
|
||||
void nr_gold_pdcch(NR_DL_FRAME_PARMS *fp,
|
||||
uint32_t ***nr_gold, uint16_t nid);
|
||||
|
||||
void nr_gold_pdsch(PHY_VARS_NR_UE* ue,
|
||||
int nscid,
|
||||
@@ -67,7 +86,21 @@ void nr_init_pusch_dmrs(PHY_VARS_NR_UE* ue,
|
||||
uint16_t N_n_scid,
|
||||
uint8_t n_scid);
|
||||
|
||||
void nr_init_pssch_dmrs_oneshot(NR_DL_FRAME_PARMS *fp,
|
||||
uint16_t N_id,
|
||||
uint32_t *pssch_dmrs,
|
||||
int slot,
|
||||
int symb);
|
||||
|
||||
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);
|
||||
|
||||
void get_csi_rs_freq_ind_sl(const NR_DL_FRAME_PARMS* frame_parms,
|
||||
uint16_t n,
|
||||
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t* csi_params,
|
||||
csi_rs_params_t* table_params,
|
||||
port_freq_indices_t* port_freq_indices);
|
||||
|
||||
void get_csi_rs_params_from_table(const nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params,
|
||||
csi_rs_params_t* table_params);
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -30,7 +30,7 @@
|
||||
* \warning
|
||||
*/
|
||||
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "nr_dci.h"
|
||||
#include "nr_dlsch.h"
|
||||
#include "nr_sch_dmrs.h"
|
||||
@@ -45,12 +45,13 @@ void nr_pdcch_scrambling(uint32_t *in,
|
||||
uint32_t size,
|
||||
uint32_t Nid,
|
||||
uint32_t scrambling_RNTI,
|
||||
uint32_t *out) {
|
||||
uint32_t *out,
|
||||
int sci_flag) {
|
||||
uint8_t reset;
|
||||
uint32_t x1 = 0, x2 = 0, s = 0;
|
||||
reset = 1;
|
||||
x2 = (scrambling_RNTI<<16) + Nid;
|
||||
LOG_D(PHY,"PDCCH Scrambling x2 %x : scrambling_RNTI %x \n", x2, scrambling_RNTI);
|
||||
if (sci_flag==0) x2 = (scrambling_RNTI<<16) + Nid;
|
||||
else x2 = (Nid<<15) + 1010;
|
||||
for (int i=0; i<size; i++) {
|
||||
if ((i&0x1f)==0) {
|
||||
s = lte_gold_generic(&x1, &x2, reset);
|
||||
@@ -66,28 +67,36 @@ void nr_pdcch_scrambling(uint32_t *in,
|
||||
}
|
||||
}
|
||||
|
||||
void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
|
||||
int32_t *txdataF,
|
||||
int16_t amp,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
int slot) {
|
||||
uint32_t nr_generate_dci(PHY_VARS_gNB *gNB, PHY_VARS_NR_UE *ue,
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
|
||||
int32_t *txdataF,
|
||||
int16_t amp,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
int slot) {
|
||||
|
||||
uint16_t cset_start_sc;
|
||||
uint8_t cset_start_symb, cset_nsymb;
|
||||
int k,l,k_prime,dci_idx, dmrs_idx;
|
||||
|
||||
AssertFatal((gNB&&(!ue)) || (ue&&(!gNB)),"This should be either for gNB (%p) or UE (%p)\n",gNB,ue);
|
||||
|
||||
// fill reg list per symbol
|
||||
int reg_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL * NR_NB_REG_PER_CCE];
|
||||
nr_fill_reg_list(reg_list, pdcch_pdu_rel15);
|
||||
if (gNB) nr_fill_reg_list(reg_list, pdcch_pdu_rel15);
|
||||
// compute rb_offset and n_prb based on frequency allocation
|
||||
int rb_offset;
|
||||
int n_rb;
|
||||
get_coreset_rballoc(pdcch_pdu_rel15->FreqDomainResource,&n_rb,&rb_offset);
|
||||
if (gNB) get_coreset_rballoc(pdcch_pdu_rel15->FreqDomainResource,&n_rb,&rb_offset);
|
||||
else {
|
||||
rb_offset=pdcch_pdu_rel15->FreqDomainResource[0];
|
||||
n_rb = pdcch_pdu_rel15->FreqDomainResource[1];
|
||||
}
|
||||
cset_start_sc = frame_parms->first_carrier_offset + (pdcch_pdu_rel15->BWPStart + rb_offset) * NR_NB_SC_PER_RB;
|
||||
|
||||
int16_t mod_dmrs[pdcch_pdu_rel15->StartSymbolIndex+pdcch_pdu_rel15->DurationSymbols][(((n_rb+rb_offset+pdcch_pdu_rel15->BWPStart)*6+15)>>4)<<4] __attribute__((aligned(16))); // 3 for the max coreset duration
|
||||
|
||||
uint32_t tcrc[pdcch_pdu_rel15->numDlDci];
|
||||
|
||||
for (int d=0;d<pdcch_pdu_rel15->numDlDci;d++) {
|
||||
/*The coreset is initialised
|
||||
* in frequency: the first subcarrier is obtained by adding the first CRB overlapping the SSB and the rb_offset for coreset 0
|
||||
@@ -95,21 +104,22 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
* in time: by its first slot and its first symbol*/
|
||||
const nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[d];
|
||||
|
||||
if(dci_pdu->ScramblingId != gNB->pdcch_gold_init) {
|
||||
if(gNB && dci_pdu->ScramblingId != gNB->pdcch_gold_init) {
|
||||
gNB->pdcch_gold_init = dci_pdu->ScramblingId;
|
||||
nr_init_pdcch_dmrs(gNB, dci_pdu->ScramblingId);
|
||||
nr_init_pdcch_dmrs(&gNB->frame_parms,gNB->nr_gold_pdcch_dmrs, dci_pdu->ScramblingId);
|
||||
}
|
||||
|
||||
uint32_t **gold_pdcch_dmrs = gNB->nr_gold_pdcch_dmrs[slot];
|
||||
|
||||
uint32_t **gold_pdcch_dmrs=NULL;
|
||||
if (gNB) gold_pdcch_dmrs= gNB->nr_gold_pdcch_dmrs[slot];
|
||||
else if (ue) gold_pdcch_dmrs = ue->nr_gold_pscch_dmrs[slot];
|
||||
|
||||
cset_start_symb = pdcch_pdu_rel15->StartSymbolIndex;
|
||||
cset_nsymb = pdcch_pdu_rel15->DurationSymbols;
|
||||
dci_idx = 0;
|
||||
LOG_D(PHY, "pdcch: Coreset rb_offset %d, nb_rb %d BWP Start %d\n",rb_offset,n_rb,pdcch_pdu_rel15->BWPStart);
|
||||
LOG_D(PHY, "pdcch: Coreset starting subcarrier %d on symbol %d (%d symbols)\n", cset_start_sc, cset_start_symb, cset_nsymb);
|
||||
LOG_D(NR_PHY, "pdcch: Coreset rb_offset %d, nb_rb %d BWP Start %d\n",rb_offset,n_rb,pdcch_pdu_rel15->BWPStart);
|
||||
LOG_D(NR_PHY, "pdcch: Coreset starting subcarrier %d on symbol %d (%d symbols)\n", cset_start_sc, cset_start_symb, cset_nsymb);
|
||||
// DMRS length is per OFDM symbol
|
||||
uint32_t dmrs_length = (n_rb+pdcch_pdu_rel15->BWPStart)*6; //2(QPSK)*3(per RB)*6(REG per CCE)
|
||||
uint32_t encoded_length = dci_pdu->AggregationLevel*108; //2(QPSK)*9(per RB)*6(REG per CCE)
|
||||
uint32_t encoded_length = gNB ? dci_pdu->AggregationLevel*108:dci_pdu->AggregationLevel*18; //2(QPSK)*9(per RB)*6(REG per CCE)
|
||||
if (dci_pdu->RNTI != 0xFFFF)
|
||||
LOG_D(PHY, "DL_DCI : rb_offset %d, nb_rb %d, DMRS length per symbol %d\t DCI encoded length %d (precoder_granularity %d, reg_mapping %d), Scrambling_Id %d, ScramblingRNTI %x, PayloadSizeBits %d\n",
|
||||
rb_offset, n_rb,dmrs_length, encoded_length,pdcch_pdu_rel15->precoderGranularity,pdcch_pdu_rel15->CceRegMappingType,
|
||||
@@ -137,9 +147,9 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
uint16_t n_RNTI = dci_pdu->RNTI;
|
||||
uint16_t Nid = dci_pdu->ScramblingId;
|
||||
uint16_t scrambling_RNTI = dci_pdu->ScramblingRNTI;
|
||||
|
||||
polar_encoder_fast((uint64_t*)dci_pdu->Payload, (void*)encoder_output, n_RNTI, 1,
|
||||
NR_POLAR_DCI_MESSAGE_TYPE, dci_pdu->PayloadSizeBits, dci_pdu->AggregationLevel);
|
||||
polar_encoder_fast((uint64_t*)dci_pdu->Payload, (void*)encoder_output, &tcrc[d],n_RNTI, 1,
|
||||
gNB ? NR_POLAR_DCI_MESSAGE_TYPE : NR_POLAR_SCI_MESSAGE_TYPE,
|
||||
dci_pdu->PayloadSizeBits, dci_pdu->AggregationLevel);
|
||||
#ifdef DEBUG_CHANNEL_CODING
|
||||
//debug dump dci
|
||||
printf("polar rnti %x,length %d, L %d\n",n_RNTI, dci_pdu->PayloadSizeBits,pdcch_pdu_rel15->dci_pdu->AggregationLevel);
|
||||
@@ -154,15 +164,15 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
#endif
|
||||
/// Scrambling
|
||||
uint32_t scrambled_output[NR_MAX_DCI_SIZE_DWORD]= {0};
|
||||
nr_pdcch_scrambling(encoder_output, encoded_length, Nid, scrambling_RNTI, scrambled_output);
|
||||
nr_pdcch_scrambling(encoder_output, encoded_length, Nid, scrambling_RNTI, scrambled_output,0);
|
||||
#ifdef DEBUG_CHANNEL_CODING
|
||||
printf("scrambled output: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\t [4]->0x%08x\t [5]->0x%08x\t \
|
||||
printf("scrambled output: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\t [4]->0x%08x\t [5]->0x%08x\n \
|
||||
[6]->0x%08x \t [7]->0x%08x \t [8]->0x%08x \t [9]->0x%08x\t [10]->0x%08x\t [11]->0x%08x\n",
|
||||
scrambled_output[0], scrambled_output[1], scrambled_output[2], scrambled_output[3], scrambled_output[4],scrambled_output[5],
|
||||
scrambled_output[6], scrambled_output[7], scrambled_output[8], scrambled_output[9], scrambled_output[10],scrambled_output[11] );
|
||||
#endif
|
||||
/// QPSK modulation
|
||||
int16_t mod_dci[NR_MAX_DCI_SIZE>>1] __attribute__((aligned(16)));
|
||||
int16_t mod_dci[encoded_length] __attribute__((aligned(16)));
|
||||
nr_modulation(scrambled_output, encoded_length, DMRS_MOD_ORDER, mod_dci); //Qm = 2 as DMRS is QPSK modulated
|
||||
#ifdef DEBUG_DCI
|
||||
|
||||
@@ -176,23 +186,26 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
if (cset_start_sc >= frame_parms->ofdm_symbol_size)
|
||||
cset_start_sc -= frame_parms->ofdm_symbol_size;
|
||||
|
||||
int num_regs = dci_pdu->AggregationLevel * NR_NB_REG_PER_CCE / pdcch_pdu_rel15->DurationSymbols;
|
||||
int num_regs = gNB ? dci_pdu->AggregationLevel * NR_NB_REG_PER_CCE / pdcch_pdu_rel15->DurationSymbols : dci_pdu->AggregationLevel/pdcch_pdu_rel15->DurationSymbols;
|
||||
|
||||
/*Mapping the encoded DCI along with the DMRS */
|
||||
for(int symbol_idx = 0; symbol_idx < pdcch_pdu_rel15->DurationSymbols; symbol_idx++) {
|
||||
// allocating rbs per symbol
|
||||
for (int reg_count = 0; reg_count < num_regs; reg_count++) {
|
||||
k = cset_start_sc + reg_list[d][reg_count] * NR_NB_SC_PER_RB;
|
||||
LOG_D(PHY, "REG %d k %d\n", reg_list[d][reg_count], k);
|
||||
if (gNB) {
|
||||
k = cset_start_sc + reg_list[d][reg_count] * NR_NB_SC_PER_RB;
|
||||
LOG_D(PHY, "REG %d k %d\n", reg_list[d][reg_count], k);
|
||||
}
|
||||
else if (reg_count ==0) k=cset_start_sc+pdcch_pdu_rel15->dci_pdu[d].CceIndex * NR_NB_SC_PER_RB;
|
||||
if (k >= frame_parms->ofdm_symbol_size)
|
||||
k -= frame_parms->ofdm_symbol_size;
|
||||
|
||||
l = cset_start_symb + symbol_idx;
|
||||
|
||||
// dmrs index depends on reference point for k according to 38.211 7.4.1.3.2
|
||||
if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG)
|
||||
dmrs_idx = (reg_list[d][reg_count] + pdcch_pdu_rel15->BWPStart) * 3;
|
||||
dmrs_idx = (gNB ? reg_list[d][reg_count] + pdcch_pdu_rel15->BWPStart : reg_count) * 3;
|
||||
else
|
||||
dmrs_idx = (reg_list[d][reg_count] + rb_offset) * 3;
|
||||
dmrs_idx = gNB ? ((reg_list[d][reg_count] + rb_offset) * 3) : (pdcch_pdu_rel15->dci_pdu[d].CceIndex + rb_offset + reg_count) * 3;
|
||||
|
||||
k_prime = 0;
|
||||
|
||||
@@ -237,11 +250,12 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
} // reg_count
|
||||
} // symbol_idx
|
||||
|
||||
LOG_D(PHY,
|
||||
LOG_D(NR_PHY,
|
||||
"DCI: payloadSize = %d | payload = %llx\n",
|
||||
dci_pdu->PayloadSizeBits,
|
||||
*(unsigned long long *)dci_pdu->Payload);
|
||||
} // for (int d=0;d<pdcch_pdu_rel15->numDlDci;d++)
|
||||
return(tcrc[0]); // this is for SCI, it should be passed in another way after so we can get more than 1
|
||||
}
|
||||
|
||||
void nr_generate_dci_top(processingData_L1tx_t *msgTx,
|
||||
@@ -251,9 +265,9 @@ void nr_generate_dci_top(processingData_L1tx_t *msgTx,
|
||||
NR_DL_FRAME_PARMS *frame_parms) {
|
||||
|
||||
for (int i=0; i<msgTx->num_ul_pdcch; i++)
|
||||
nr_generate_dci(msgTx->gNB,&msgTx->ul_pdcch_pdu[i].pdcch_pdu.pdcch_pdu_rel15,txdataF,amp,frame_parms,slot);
|
||||
nr_generate_dci(msgTx->gNB,NULL,&msgTx->ul_pdcch_pdu[i].pdcch_pdu.pdcch_pdu_rel15,txdataF,amp,frame_parms,slot);
|
||||
for (int i=0; i<msgTx->num_dl_pdcch; i++)
|
||||
nr_generate_dci(msgTx->gNB,&msgTx->pdcch_pdu[i].pdcch_pdu_rel15,txdataF,amp,frame_parms,slot);
|
||||
nr_generate_dci(msgTx->gNB,NULL,&msgTx->pdcch_pdu[i].pdcch_pdu_rel15,txdataF,amp,frame_parms,slot);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ void nr_pdcch_scrambling(uint32_t *in,
|
||||
uint32_t size,
|
||||
uint32_t Nid,
|
||||
uint32_t n_RNTI,
|
||||
uint32_t *out);
|
||||
uint32_t *out,
|
||||
int sci_flag);
|
||||
|
||||
int16_t find_nr_pdcch(int frame,int slot, PHY_VARS_gNB *gNB,find_type_t type);
|
||||
|
||||
|
||||
@@ -302,7 +302,7 @@ int nr_generate_pbch(nfapi_nr_dl_tti_ssb_pdu *ssb_pdu,
|
||||
a_reversed |= (((uint64_t)pbch->pbch_a_prime>>i)&1)<<(31-i);
|
||||
|
||||
/// CRC, coding and rate matching
|
||||
polar_encoder_fast (&a_reversed, (void*)pbch->pbch_e, 0, 0,
|
||||
polar_encoder_fast (&a_reversed, (void*)pbch->pbch_e, NULL,0, 0,
|
||||
NR_POLAR_PBCH_MESSAGE_TYPE, NR_POLAR_PBCH_PAYLOAD_BITS, NR_POLAR_PBCH_AGGREGATION_LEVEL);
|
||||
|
||||
#ifdef DEBUG_PBCH_ENCODING
|
||||
|
||||
@@ -40,6 +40,18 @@ uint32_t nr_get_G(uint16_t nb_rb, uint16_t nb_symb_sch,uint8_t nb_re_dmrs,uint16
|
||||
return(G);
|
||||
}
|
||||
|
||||
uint32_t nr_get_G_SL(uint16_t nb_rb, uint16_t nb_symb_sch, uint8_t nb_re_dmrs, uint16_t length_dmrs, uint8_t sci1_dmrs_overlap, uint16_t sci1_re, uint16_t sci1_rb, uint16_t sci2_re, uint16_t csi_rs_re, uint8_t Qm, uint8_t Nl) {
|
||||
|
||||
uint32_t G_SL, slsch_re;
|
||||
slsch_re = ((NR_NB_SC_PER_RB*nb_symb_sch) - (nb_re_dmrs*length_dmrs)) * nb_rb;
|
||||
if (sci1_dmrs_overlap > 0) slsch_re += (nb_re_dmrs * sci1_rb); // return the dmrs that are not transmitted due to SCI1
|
||||
slsch_re -= sci1_re; // REs taken by SCI1
|
||||
slsch_re -= sci2_re; // REs taken by SCI2
|
||||
slsch_re -= csi_rs_re; // REs taken by CSI_RS
|
||||
G_SL = slsch_re * Qm * Nl;
|
||||
return(G_SL);
|
||||
}
|
||||
|
||||
uint32_t nr_get_E(uint32_t G, uint8_t C, uint8_t Qm, uint8_t Nl, uint8_t r) {
|
||||
uint32_t E;
|
||||
uint8_t Cprime = C; //assume CBGTI not present
|
||||
|
||||
@@ -59,6 +59,19 @@ uint32_t nr_get_G(uint16_t nb_rb, uint16_t nb_symb_sch, uint8_t nb_re_dmrs, uint
|
||||
|
||||
uint32_t nr_get_E(uint32_t G, uint8_t C, uint8_t Qm, uint8_t Nl, uint8_t r);
|
||||
|
||||
int get_NREsci2_2(const int sci2_alpha,
|
||||
const int sci2_payload_len,
|
||||
const int sci2_beta_offset,
|
||||
const int pssch_numsym,
|
||||
const int pscch_numsym,
|
||||
const int pscch_numrbs,
|
||||
const int l_subch,
|
||||
const int subchannel_size,
|
||||
const int target_coderate,
|
||||
const int mcs_table_index);
|
||||
|
||||
uint32_t nr_get_G_SL(uint16_t nb_rb, uint16_t nb_symb_sch, uint8_t nb_re_dmrs, uint16_t length_dmrs, uint8_t sci1_dmrs_overlap, uint16_t sci1_re, uint16_t sci1_rb, uint16_t sci2_re, uint16_t csi_rs_re, uint8_t Qm, uint8_t Nl);
|
||||
|
||||
void compute_nr_prach_seq(uint8_t short_sequence, uint8_t num_sequences, uint8_t rootSequenceIndex, c16_t X_u[64][839]);
|
||||
|
||||
void nr_fill_du(uint16_t N_ZC, const uint16_t *prach_root_sequence_map);
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
|
||||
#define NR_PBCH_PDU_BITS 24
|
||||
|
||||
@@ -126,10 +127,17 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch, uint16_t N_RB, const NR_DL_FRAME_PARM
|
||||
@param harq_pid HARQ process ID
|
||||
*/
|
||||
void nr_rx_pusch(PHY_VARS_gNB *gNB,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
nr_phy_data_t *phy_data,
|
||||
int rxFSz,
|
||||
c16_t rxdataF[][rxFSz],
|
||||
uint8_t UE_id,
|
||||
uint32_t frame,
|
||||
uint8_t slot,
|
||||
unsigned char harq_pid);
|
||||
unsigned char harq_pid,
|
||||
bool *is_csi_rs_slot
|
||||
);
|
||||
|
||||
/** \brief This function performs RB extraction (signal and channel estimates) (currently signal only until channel estimation and compensation are implemented)
|
||||
@param rxdataF pointer to the received frequency domain signal
|
||||
@@ -140,13 +148,21 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
|
||||
@param nb_rb_pusch The number of RBs allocated (used for Resource Allocation Type 1 in NR)
|
||||
@param frame_parms, Pointer to frame descriptor structure
|
||||
*/
|
||||
void nr_ulsch_extract_rbs(c16_t **rxdataF,
|
||||
void nr_ulsch_extract_rbs(int rxFSz,
|
||||
c16_t rxdataF[][rxFSz],
|
||||
NR_gNB_PUSCH *pusch_vars,
|
||||
int slot,
|
||||
unsigned char symbol,
|
||||
uint8_t is_dmrs_symbol,
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
NR_DL_FRAME_PARMS *frame_parms);
|
||||
uint8_t is_csirs_symbol,
|
||||
uint32_t bwp_start,
|
||||
uint32_t rb_start,
|
||||
uint32_t rb_size,
|
||||
uint32_t nrOfLayers,
|
||||
uint32_t num_dmrs_cdm_grps_no_data,
|
||||
uint32_t dmrs_config_type,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params);
|
||||
|
||||
void nr_ulsch_scale_channel(int32_t **ul_ch_estimates_ext,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
*/
|
||||
|
||||
#include "nr_dci.h"
|
||||
# include "executables/softmodem-common.h"
|
||||
|
||||
void nr_group_sequence_hopping (pucch_GroupHopping_t PUCCH_GroupHopping,
|
||||
uint32_t n_id,
|
||||
@@ -63,7 +64,11 @@ void nr_group_sequence_hopping (pucch_GroupHopping_t PUCCH_GroupHopping,
|
||||
uint8_t f_ss=0,f_gh=0;
|
||||
*u=0;
|
||||
*v=0;
|
||||
uint32_t c_init = 0;
|
||||
uint32_t c_init = 0;
|
||||
if (get_softmodem_params()->sl_mode) {
|
||||
*u = n_id % 30;
|
||||
return;
|
||||
}
|
||||
uint32_t x1,s; // TS 38.211 Subclause 5.2.1
|
||||
int l = 32, minShift = ((2*nr_slot_tx+n_hop)<<3);
|
||||
int tmpShift =0;
|
||||
@@ -139,29 +144,31 @@ double nr_cyclic_shift_hopping(uint32_t n_id,
|
||||
uint32_t c_init = n_id; // we initialize c_init again to calculate n_cs
|
||||
|
||||
uint32_t x1,s = lte_gold_generic(&x1, &c_init, 1); // TS 38.211 Subclause 5.2.1
|
||||
uint8_t n_cs=0;
|
||||
int l = 32, minShift = (14*8*nr_slot_tx )+ 8*(lnormal+lprime);
|
||||
int tmpShift =0;
|
||||
uint8_t n_cs = 0;
|
||||
int l = 32;
|
||||
lnormal = get_softmodem_params()->sl_mode ? 0 : lnormal;
|
||||
int minShift = (14 * 8 * nr_slot_tx) + 8 * (lnormal + lprime);
|
||||
int tmpShift = 0;
|
||||
#ifdef DEBUG_NR_PUCCH_TX
|
||||
printf("\t\t [nr_cyclic_shift_hopping] calculating alpha (cyclic shift) using c_init=%u -> \n",c_init);
|
||||
#endif
|
||||
|
||||
for (int m=0; m<8; m++) {
|
||||
for (int m = 0; m < 8; m++) {
|
||||
while(minShift >= l) {
|
||||
s = lte_gold_generic(&x1, &c_init, 0);
|
||||
l = l+32;
|
||||
l = l + 32;
|
||||
}
|
||||
|
||||
tmpShift = (minShift&((1<<5)-1)); //minShift%32;
|
||||
tmpShift = (minShift & ((1 << 5) - 1)); //minShift%32;
|
||||
minShift ++;
|
||||
n_cs = n_cs+((1<<m)*((uint8_t)((s>>tmpShift)&1)));
|
||||
n_cs = n_cs + ((1 << m) * ((uint8_t)((s >> (tmpShift + m)) & 1)));
|
||||
// calculating n_cs (Not sure we have to use nr_slot_tx FIXME!!!)
|
||||
// n_cs = n_cs+((1<<m)*((uint8_t)((s>>((14*8*nr_slot_tx) + 8*(lnormal+lprime) + m))&1)));
|
||||
}
|
||||
|
||||
alpha = (alpha * (double)((m0+mcs+n_cs)%12));
|
||||
alpha = (alpha * (double)((m0 + mcs + n_cs) % 12));
|
||||
#ifdef DEBUG_NR_PUCCH_TX
|
||||
printf("n_cs=%d -> %lf\n",n_cs,alpha);
|
||||
printf("n_cs = %d -> %lf\n", n_cs, alpha);
|
||||
#endif
|
||||
return(alpha);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
*/
|
||||
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "common/utils/threadPool/thread-pool.h"
|
||||
|
||||
void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch, uint16_t N_RB_UL);
|
||||
@@ -50,6 +51,7 @@ NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL);
|
||||
*/
|
||||
|
||||
int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
|
||||
struct PHY_VARS_NR_UE_s *UE,
|
||||
uint8_t UE_id,
|
||||
short *ulsch_llr,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
@@ -57,7 +59,11 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
|
||||
uint32_t frame,
|
||||
uint8_t nr_tti_rx,
|
||||
uint8_t harq_pid,
|
||||
uint32_t G);
|
||||
uint32_t G,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
nr_phy_data_t *phy_data,
|
||||
int8_t *ack_nack_rcvd,
|
||||
uint8_t num_acks);
|
||||
|
||||
/*! \brief Perform PUSCH unscrambling. TS 38.211 V15.4.0 subclause 6.3.1.1
|
||||
@param llr, Pointer to llr bits
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
// [from gNB coding]
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/CODING/coding_extern.h"
|
||||
@@ -43,10 +44,12 @@
|
||||
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
|
||||
#include "SCHED_NR/sched_nr.h"
|
||||
#include "SCHED_NR/fapi_nr_l1.h"
|
||||
#include "defs.h"
|
||||
#include "openair1/SCHED_NR_UE/defs.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include <syscall.h>
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
|
||||
//#define DEBUG_ULSCH_DECODING
|
||||
//#define gNB_DEBUG_TRACE
|
||||
|
||||
@@ -155,9 +158,9 @@ static void nr_processULSegment(void *arg)
|
||||
|
||||
t_nrLDPC_time_stats procTime = {0};
|
||||
t_nrLDPC_time_stats *p_procTime = &procTime;
|
||||
|
||||
// start_meas(&phy_vars_gNB->ulsch_deinterleaving_stats);
|
||||
|
||||
#ifdef DEBUG_ULSCH_DECODING
|
||||
start_meas(&phy_vars_gNB->ulsch_deinterleaving_stats);
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////// nr_deinterleaving_ldpc ///////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -169,21 +172,20 @@ static void nr_processULSegment(void *arg)
|
||||
|
||||
nr_deinterleaving_ldpc(E, Qm, harq_e, ulsch_llr + r_offset);
|
||||
|
||||
// for (int i =0; i<16; i++)
|
||||
// printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,ulsch_harq->w[r][i], r_offset);
|
||||
|
||||
#ifdef DEBUG_ULSCH_DECODING
|
||||
for (int i =0; i<16; i++)
|
||||
printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,ulsch_harq->w[r][i], r_offset);
|
||||
stop_meas(&phy_vars_gNB->ulsch_deinterleaving_stats);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////// nr_rate_matching_ldpc_rx ////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////// ulsch_harq->e =====> ulsch_harq->d /////////////////////////
|
||||
|
||||
// start_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
|
||||
|
||||
#ifdef DEBUG_ULSCH_DECODING
|
||||
start_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
|
||||
#endif
|
||||
if (nr_rate_matching_ldpc_rx(rdata->tbslbrm,
|
||||
p_decoderParms->BG,
|
||||
p_decoderParms->Z,
|
||||
@@ -196,17 +198,19 @@ static void nr_processULSegment(void *arg)
|
||||
ulsch_harq->F,
|
||||
Kr - ulsch_harq->F - 2 * (p_decoderParms->Z))
|
||||
== -1) {
|
||||
#ifdef DEBUG_ULSCH_DECODING
|
||||
stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
|
||||
|
||||
#endif
|
||||
LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n");
|
||||
rdata->decodeIterations = max_ldpc_iterations + 1;
|
||||
return;
|
||||
} else {
|
||||
#ifdef DEBUG_ULSCH_DECODING
|
||||
stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
|
||||
#endif
|
||||
}
|
||||
|
||||
ulsch_harq->d_to_be_cleared[r] = false;
|
||||
|
||||
memset(ulsch_harq->c[r], 0, Kr_bytes);
|
||||
|
||||
if (ulsch_harq->C == 1) {
|
||||
@@ -220,9 +224,9 @@ static void nr_processULSegment(void *arg)
|
||||
crc_type = CRC24_B;
|
||||
length_dec = (ulsch_harq->B + 24 * ulsch_harq->C) / ulsch_harq->C;
|
||||
}
|
||||
|
||||
// start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats);
|
||||
|
||||
#ifdef DEBUG_ULSCH_DECODING
|
||||
start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats);
|
||||
#endif
|
||||
// set first 2*Z_c bits to zeros
|
||||
memset(&z[0], 0, 2 * ulsch_harq->Z * sizeof(int16_t));
|
||||
// set Filler bits
|
||||
@@ -235,7 +239,6 @@ static void nr_processULSegment(void *arg)
|
||||
for (i = 0, j = 0; j < ((kc * ulsch_harq->Z) >> 4) + 1; i += 2, j++) {
|
||||
pl[j] = _mm_packs_epi16(pv[i], pv[i + 1]);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////// nrLDPC_decoder /////////////////////////////////////
|
||||
@@ -248,19 +251,30 @@ static void nr_processULSegment(void *arg)
|
||||
|
||||
if (rdata->decodeIterations <= p_decoderParms->numMaxIter)
|
||||
memcpy(ulsch_harq->c[r],llrProcBuf, Kr>>3);
|
||||
//stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats);
|
||||
#ifdef DEBUG_ULSCH_DECODING
|
||||
stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
|
||||
uint8_t ULSCH_id,
|
||||
short *ulsch_llr,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
uint32_t frame,
|
||||
uint8_t nr_tti_rx,
|
||||
uint8_t harq_pid,
|
||||
uint32_t G)
|
||||
struct PHY_VARS_NR_UE_s *UE,
|
||||
uint8_t ULSCH_id,
|
||||
short *ulsch_llr,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
uint32_t frame,
|
||||
uint8_t nr_tti_rx,
|
||||
uint8_t harq_pid,
|
||||
uint32_t G,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
nr_phy_data_t *phy_data,
|
||||
int8_t *ack_nack_rcvd,
|
||||
uint8_t num_acks)
|
||||
{
|
||||
AssertFatal((phy_vars_gNB && !UE) || (!phy_vars_gNB && UE),"Only one of gNB or UE must be non-null`");
|
||||
if (!ulsch_llr) {
|
||||
LOG_E(PHY, "ulsch_decoding.c: NULL ulsch_llr pointer\n");
|
||||
return -1;
|
||||
@@ -268,8 +282,8 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 1);
|
||||
|
||||
NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id];
|
||||
NR_gNB_PUSCH *pusch = &phy_vars_gNB->pusch_vars[ULSCH_id];
|
||||
NR_gNB_ULSCH_t *ulsch = phy_vars_gNB ? &phy_vars_gNB->ulsch[ULSCH_id] : &UE->slsch[ULSCH_id];
|
||||
NR_gNB_PUSCH *pusch = phy_vars_gNB ? &phy_vars_gNB->pusch_vars[ULSCH_id] : &UE->pssch_vars[ULSCH_id];
|
||||
NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process;
|
||||
|
||||
if (!harq_process) {
|
||||
@@ -382,7 +396,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
|
||||
Kr_bytes = Kr >> 3;
|
||||
|
||||
uint32_t offset = 0;
|
||||
if (phy_vars_gNB->ldpc_offload_flag && mcs > 9) {
|
||||
if (phy_vars_gNB && phy_vars_gNB->ldpc_offload_flag && mcs > 9) {
|
||||
int8_t llrProcBuf[22 * 384];
|
||||
// if (dtx_det==0) {
|
||||
int16_t z_ol[68 * 384];
|
||||
@@ -464,17 +478,17 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 0);
|
||||
|
||||
if (harq_process->processedSegments == harq_process->C) {
|
||||
LOG_D(PHY, "[gNB %d] ULSCH: Setting ACK for slot %d TBS %d\n", phy_vars_gNB->Mod_id, ulsch->slot, harq_process->TBS);
|
||||
LOG_D(NR_PHY, "[%s %d] ULSCH: Setting ACK for slot %d TBS %d\n", phy_vars_gNB ? "gNB" : "UE", phy_vars_gNB ? phy_vars_gNB->Mod_id : 0, ulsch->slot, harq_process->TBS);
|
||||
ulsch->active = false;
|
||||
harq_process->round = 0;
|
||||
|
||||
LOG_D(PHY, "ULSCH received ok \n");
|
||||
nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 0, 0);
|
||||
|
||||
} else {
|
||||
LOG_D(PHY,
|
||||
"[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d)\n",
|
||||
phy_vars_gNB->Mod_id,
|
||||
LOG_E(PHY,
|
||||
"[%s %d] ULSCH %d in error: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d)\n",
|
||||
phy_vars_gNB ? "gNB" : "UE", phy_vars_gNB ? phy_vars_gNB->Mod_id : 0,
|
||||
ULSCH_id,
|
||||
ulsch->frame,
|
||||
ulsch->slot,
|
||||
harq_pid,
|
||||
@@ -483,7 +497,6 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
|
||||
harq_process->TBS);
|
||||
ulsch->handled = 1;
|
||||
decodeIterations = ulsch->max_ldpc_iterations + 1;
|
||||
LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id);
|
||||
nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 1, 0);
|
||||
}
|
||||
ulsch->last_iteration_cnt = decodeIterations;
|
||||
@@ -492,13 +505,16 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
|
||||
else {
|
||||
dtx_det = 0;
|
||||
set_abort(&harq_process->abort_decode, false);
|
||||
notifiedFIFO_t nf;
|
||||
if (UE) initNotifiedFIFO(&nf);
|
||||
for (int r = 0; r < harq_process->C; r++) {
|
||||
int E = nr_get_E(G, harq_process->C, Qm, n_layers, r);
|
||||
union ldpcReqUnion id = {.s = {ulsch->rnti, frame, nr_tti_rx, 0, 0}};
|
||||
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(ldpcDecode_t), id.p, &phy_vars_gNB->respDecode, &nr_processULSegment);
|
||||
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(ldpcDecode_t), id.p, phy_vars_gNB ? &phy_vars_gNB->respDecode : &nf, &nr_processULSegment);
|
||||
ldpcDecode_t *rdata = (ldpcDecode_t *)NotifiedFifoData(req);
|
||||
decParams.R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index, E, decParams.BG, decParams.Z, &harq_process->llrLen, harq_process->round);
|
||||
rdata->gNB = phy_vars_gNB;
|
||||
rdata->UE = UE;
|
||||
rdata->ulsch_harq = harq_process;
|
||||
rdata->decoderParms = decParams;
|
||||
rdata->ulsch_llr = ulsch_llr;
|
||||
@@ -516,12 +532,24 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
|
||||
rdata->ulsch = ulsch;
|
||||
rdata->ulsch_id = ULSCH_id;
|
||||
rdata->tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes;
|
||||
pushTpool(&phy_vars_gNB->threadPool, req);
|
||||
pushTpool(phy_vars_gNB ? &phy_vars_gNB->threadPool : &get_nrUE_params()->Tpool, req);
|
||||
LOG_D(PHY, "Added a block to decode, in pipe: %d\n", r);
|
||||
r_offset += E;
|
||||
offset += (Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
if (UE) {
|
||||
int nbDecode = harq_process->C;
|
||||
while (nbDecode) {
|
||||
notifiedFIFO_elt_t *req=pullTpool(&nf, &get_nrUE_params()->Tpool);
|
||||
if (req == NULL)
|
||||
break; // Tpool has been stopped
|
||||
nr_postDecode_slsch(UE, req, proc, phy_data, ack_nack_rcvd, num_acks);
|
||||
delNotifiedFIFO_elt(req);
|
||||
nbDecode--;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return harq_process->C;
|
||||
}
|
||||
|
||||
@@ -3,11 +3,16 @@
|
||||
#include "nr_transport_proto.h"
|
||||
#include "PHY/impl_defs_top.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_sch_dmrs.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "PHY/NR_REFSIG/dmrs_nr.h"
|
||||
#include "PHY/NR_REFSIG/ptrs_nr.h"
|
||||
#include "PHY/NR_ESTIMATION/nr_ul_estimation.h"
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
#include "SCHED_NR_UE/defs.h"
|
||||
#include "openair1/PHY/MODULATION/modulation_UE.h"
|
||||
|
||||
//#define DEBUG_CH_COMP
|
||||
//#define DEBUG_RB_EXT
|
||||
@@ -16,8 +21,8 @@
|
||||
|
||||
#define INVALID_VALUE 255
|
||||
|
||||
void nr_idft(int32_t *z, uint32_t Msc_PUSCH)
|
||||
{
|
||||
void nr_idft(int32_t *z, uint32_t Msc_PUSCH) {
|
||||
|
||||
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
__m128i idft_in128[1][3240], idft_out128[1][3240];
|
||||
@@ -303,14 +308,22 @@ void nr_idft(int32_t *z, uint32_t Msc_PUSCH)
|
||||
}
|
||||
|
||||
|
||||
void nr_ulsch_extract_rbs(c16_t **rxdataF,
|
||||
void nr_ulsch_extract_rbs(int rxFSz,
|
||||
c16_t rxdataF[][rxFSz],
|
||||
NR_gNB_PUSCH *pusch_vars,
|
||||
int slot,
|
||||
unsigned char symbol,
|
||||
uint8_t is_dmrs_symbol,
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
NR_DL_FRAME_PARMS *frame_parms) {
|
||||
|
||||
uint8_t is_csirs_symbol,
|
||||
uint32_t bwp_start,
|
||||
uint32_t rb_start,
|
||||
uint32_t rb_size,
|
||||
uint32_t nrOfLayers,
|
||||
uint32_t num_dmrs_cdm_grps_no_data,
|
||||
uint32_t dmrs_config_type,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params) {
|
||||
|
||||
unsigned short start_re, re, nb_re_pusch;
|
||||
unsigned char aarx, aatx;
|
||||
uint32_t rxF_ext_index = 0;
|
||||
@@ -318,16 +331,16 @@ void nr_ulsch_extract_rbs(c16_t **rxdataF,
|
||||
uint32_t ul_ch0_index = 0;
|
||||
int16_t *rxF,*rxF_ext;
|
||||
int *ul_ch0,*ul_ch0_ext;
|
||||
int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size;
|
||||
int soffset = 0; /*(slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size;*/
|
||||
|
||||
#ifdef DEBUG_RB_EXT
|
||||
printf("--------------------symbol = %d-----------------------\n", symbol);
|
||||
printf("--------------------ch_ext_index = %d-----------------------\n", symbol*NR_NB_SC_PER_RB * pusch_pdu->rb_size);
|
||||
printf("--------------------ch_ext_index = %d-----------------------\n", symbol*NR_NB_SC_PER_RB * rb_size);
|
||||
#endif
|
||||
|
||||
uint8_t is_data_re;
|
||||
start_re = (frame_parms->first_carrier_offset + (pusch_pdu->rb_start + pusch_pdu->bwp_start) * NR_NB_SC_PER_RB)%frame_parms->ofdm_symbol_size;
|
||||
nb_re_pusch = NR_NB_SC_PER_RB * pusch_pdu->rb_size;
|
||||
start_re = (frame_parms->first_carrier_offset + (rb_start + bwp_start) * NR_NB_SC_PER_RB)%frame_parms->ofdm_symbol_size;
|
||||
nb_re_pusch = NR_NB_SC_PER_RB * rb_size;
|
||||
|
||||
int nb_re_pusch2 = nb_re_pusch + (nb_re_pusch&7);
|
||||
|
||||
@@ -335,26 +348,73 @@ void nr_ulsch_extract_rbs(c16_t **rxdataF,
|
||||
|
||||
rxF = (int16_t *)&rxdataF[aarx][soffset+(symbol * frame_parms->ofdm_symbol_size)];
|
||||
rxF_ext = (int16_t *)&pusch_vars->rxdataF_ext[aarx][symbol * nb_re_pusch2]; // [hna] rxdataF_ext isn't contiguous in order to solve an alignment problem ib llr computation in case of mod_order = 4, 6
|
||||
|
||||
AssertFatal(soffset + (symbol * frame_parms->ofdm_symbol_size) + start_re < rxFSz, "rxF offset is greater than the buffer size\n");
|
||||
AssertFatal(symbol * nb_re_pusch2 + nb_re_pusch < nb_re_pusch2 * frame_parms->symbols_per_slot, "Copied PUSCH data is more than rxF_ext size\n");
|
||||
LOG_D(NR_PHY,"symbol %d : rxF energy %d\n",symbol,dB_fixed(signal_energy_nodc((int32_t*)rxF,frame_parms->ofdm_symbol_size)));
|
||||
if (is_dmrs_symbol == 0) {
|
||||
if (start_re + nb_re_pusch <= frame_parms->ofdm_symbol_size) {
|
||||
memcpy1((void*)rxF_ext, (void*)&rxF[start_re*2], nb_re_pusch*sizeof(int32_t));
|
||||
if (is_csirs_symbol == 0) {
|
||||
if (start_re + nb_re_pusch <= frame_parms->ofdm_symbol_size) {
|
||||
memcpy1((void*)rxF_ext, (void*)&rxF[start_re*2], nb_re_pusch*sizeof(int32_t));
|
||||
} else {
|
||||
int neg_length = frame_parms->ofdm_symbol_size-start_re;
|
||||
int pos_length = nb_re_pusch-neg_length;
|
||||
memcpy1((void*)rxF_ext, (void*)&rxF[start_re*2], neg_length*sizeof(int32_t));
|
||||
memcpy1((void*)&rxF_ext[2*neg_length], (void*)rxF, pos_length*sizeof(int32_t));
|
||||
}
|
||||
|
||||
for (aatx = 0; aatx < nrOfLayers; aatx++) {
|
||||
ul_ch0 = &pusch_vars->ul_ch_estimates[aatx*frame_parms->nb_antennas_rx+aarx][pusch_vars->dmrs_symbol*frame_parms->ofdm_symbol_size]; // update channel estimates if new dmrs symbol are available
|
||||
ul_ch0_ext = &pusch_vars->ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*nb_re_pusch2];
|
||||
memcpy1((void*)ul_ch0_ext, (void*)ul_ch0,nb_re_pusch*sizeof(int32_t));
|
||||
}
|
||||
} else {
|
||||
int neg_length = frame_parms->ofdm_symbol_size-start_re;
|
||||
int pos_length = nb_re_pusch-neg_length;
|
||||
memcpy1((void*)rxF_ext,(void*)&rxF[start_re*2],neg_length*sizeof(int32_t));
|
||||
memcpy1((void*)&rxF_ext[2*neg_length],(void*)rxF,pos_length*sizeof(int32_t));
|
||||
}
|
||||
int16_t csi_rs_rb = csi_params->start_rb;
|
||||
for (aatx = 0; aatx < nrOfLayers; aatx++) {
|
||||
ul_ch0 = &pusch_vars->ul_ch_estimates[aatx*frame_parms->nb_antennas_rx+aarx][pusch_vars->dmrs_symbol*frame_parms->ofdm_symbol_size]; // update channel estimates if new dmrs symbol are available
|
||||
ul_ch0_ext = &pusch_vars->ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*nb_re_pusch2];
|
||||
|
||||
for (aatx = 0; aatx < pusch_pdu->nrOfLayers; aatx++) {
|
||||
ul_ch0 = &pusch_vars->ul_ch_estimates[aatx*frame_parms->nb_antennas_rx+aarx][pusch_vars->dmrs_symbol*frame_parms->ofdm_symbol_size]; // update channel estimates if new dmrs symbol are available
|
||||
ul_ch0_ext = &pusch_vars->ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*nb_re_pusch2];
|
||||
memcpy1((void*)ul_ch0_ext,(void*)ul_ch0,nb_re_pusch*sizeof(int32_t));
|
||||
}
|
||||
rxF_ext_index = 0;
|
||||
ul_ch0_ext_index = 0;
|
||||
ul_ch0_index = 0;
|
||||
for (re = 0; re < nb_re_pusch; re++) {
|
||||
uint8_t is_csi_rs = 0;
|
||||
uint16_t k = start_re + re;
|
||||
if ((k >= csi_params->start_rb * NR_NB_SC_PER_RB) && (re % NR_NB_SC_PER_RB == 0) && (csi_rs_rb < csi_params->nr_of_rbs)) {
|
||||
csi_rs_params_t table_params;
|
||||
get_csi_rs_params_from_table(csi_params, &table_params);
|
||||
port_freq_indices_t *port_freq_indices = (port_freq_indices_t *)malloc(table_params.ports*sizeof(port_freq_indices));
|
||||
get_csi_rs_freq_ind_sl(frame_parms, csi_rs_rb, csi_params, &table_params, port_freq_indices);
|
||||
if (k == port_freq_indices[aatx].k) {
|
||||
is_csi_rs = 1;
|
||||
csi_rs_rb++;
|
||||
}
|
||||
free(port_freq_indices);
|
||||
port_freq_indices = NULL;
|
||||
}
|
||||
|
||||
if (++k >= frame_parms->ofdm_symbol_size) {
|
||||
k -= frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
|
||||
// save only data and respective channel estimates
|
||||
if (is_csi_rs == 0) {
|
||||
if (aatx == 0) {
|
||||
rxF_ext[rxF_ext_index] = (rxF[ ((start_re + re)*2) % (frame_parms->ofdm_symbol_size*2)]);
|
||||
rxF_ext[rxF_ext_index + 1] = (rxF[(((start_re + re)*2) + 1) % (frame_parms->ofdm_symbol_size*2)]);
|
||||
rxF_ext_index +=2;
|
||||
}
|
||||
|
||||
ul_ch0_ext[ul_ch0_ext_index] = ul_ch0[ul_ch0_index];
|
||||
ul_ch0_ext_index++;
|
||||
|
||||
}
|
||||
ul_ch0_index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
for (aatx = 0; aatx < pusch_pdu->nrOfLayers; aatx++) {
|
||||
for (aatx = 0; aatx < nrOfLayers; aatx++) {
|
||||
ul_ch0 = &pusch_vars->ul_ch_estimates[aatx*frame_parms->nb_antennas_rx+aarx][pusch_vars->dmrs_symbol*frame_parms->ofdm_symbol_size]; // update channel estimates if new dmrs symbol are available
|
||||
ul_ch0_ext = &pusch_vars->ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*nb_re_pusch2];
|
||||
|
||||
@@ -363,7 +423,7 @@ void nr_ulsch_extract_rbs(c16_t **rxdataF,
|
||||
ul_ch0_index = 0;
|
||||
for (re = 0; re < nb_re_pusch; re++) {
|
||||
uint16_t k = start_re + re;
|
||||
is_data_re = allowed_xlsch_re_in_dmrs_symbol(k, start_re, frame_parms->ofdm_symbol_size, pusch_pdu->num_dmrs_cdm_grps_no_data, pusch_pdu->dmrs_config_type);
|
||||
is_data_re = allowed_xlsch_re_in_dmrs_symbol(k, start_re, frame_parms->ofdm_symbol_size, num_dmrs_cdm_grps_no_data, dmrs_config_type);
|
||||
if (++k >= frame_parms->ofdm_symbol_size) {
|
||||
k -= frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
@@ -388,7 +448,7 @@ void nr_ulsch_extract_rbs(c16_t **rxdataF,
|
||||
is_dmrs_symbol,rxF_ext_index>>1, rxF_ext[rxF_ext_index],rxF_ext[rxF_ext_index+1],
|
||||
ul_ch0_ext_index, ((int16_t*)&ul_ch0_ext[ul_ch0_ext_index])[0], ((int16_t*)&ul_ch0_ext[ul_ch0_ext_index])[1]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
ul_ch0_index++;
|
||||
}
|
||||
}
|
||||
@@ -591,13 +651,13 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext,
|
||||
rxF = (int16_t *) &rxdataF_ext[aarx][symbol * (off + (nb_rb * 12))];
|
||||
ul_ch = (int16_t *) &ul_ch_estimates_ext[nl * frame_parms->nb_antennas_rx + aarx][symbol * (off + (nb_rb * 12))];
|
||||
|
||||
printf("--------symbol = %d, mod_order = %d, output_shift = %d, layer %i, antenna rx = %d -----------\n",
|
||||
LOG_I(NR_PHY,"--------symbol = %d, mod_order = %d, output_shift = %d, layer %i, antenna rx = %d -----------\n",
|
||||
symbol, mod_order, output_shift, nl, aarx);
|
||||
printf("----------------Before compensation------------------\n");
|
||||
LOG_I(NR_PHY,"----------------Before compensation------------------\n");
|
||||
|
||||
for (prnt_idx = 0; prnt_idx < 12 * 5 * 2; prnt_idx += 2) {
|
||||
printf("rxF[%d] = (%d,%d)\n", prnt_idx >> 1, rxF[prnt_idx], rxF[prnt_idx + 1]);
|
||||
printf("ul_ch[%d] = (%d,%d)\n", prnt_idx >> 1, ul_ch[prnt_idx], ul_ch[prnt_idx + 1]);
|
||||
LOG_I(NR_PHY,"rxF[%d] = (%d,%d)\n", prnt_idx >> 1, rxF[prnt_idx], rxF[prnt_idx + 1]);
|
||||
LOG_I(NR_PHY,"ul_ch[%d] = (%d,%d)\n", prnt_idx >> 1, ul_ch[prnt_idx], ul_ch[prnt_idx + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1049,10 +1109,10 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext,
|
||||
for (int aarx2=0; aarx2<frame_parms->nb_antennas_rx; aarx2++) {
|
||||
rxF = (int16_t *)&rxdataF_comp[nl2*frame_parms->nb_antennas_rx+aarx2][(symbol*(off+(nb_rb*12)))];
|
||||
|
||||
printf("--------After compansation, layer %i, antenna rx %i----------\n", nl2, aarx2);
|
||||
LOG_I(NR_PHY,"--------After compansation, layer %i, antenna rx %i----------\n", nl2, aarx2);
|
||||
|
||||
for (prnt_idx=0;prnt_idx<12*5*2;prnt_idx+=2){
|
||||
printf("rxF[%d] = (%d,%d)\n", prnt_idx>>1, rxF[prnt_idx],rxF[prnt_idx+1]);
|
||||
LOG_I(NR_PHY,"rxF[%d] = (%d,%d)\n", prnt_idx>>1, rxF[prnt_idx],rxF[prnt_idx+1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1893,160 +1953,249 @@ uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms,
|
||||
|
||||
/* Main Function */
|
||||
void nr_rx_pusch(PHY_VARS_gNB *gNB,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
nr_phy_data_t *phy_data,
|
||||
int rxFSz,
|
||||
c16_t rxdataF[][rxFSz],
|
||||
uint8_t ulsch_id,
|
||||
uint32_t frame,
|
||||
uint8_t slot,
|
||||
unsigned char harq_pid)
|
||||
unsigned char harq_pid,
|
||||
bool *is_csi_rs_slot)
|
||||
{
|
||||
|
||||
uint8_t aarx, aatx;
|
||||
uint32_t nb_re_pusch, bwp_start_subcarrier;
|
||||
int avgs = 0;
|
||||
|
||||
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
|
||||
NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ulsch_id];
|
||||
nfapi_nr_pusch_pdu_t *rel15_ul = &ulsch->harq_process->ulsch_pdu;
|
||||
int avg[frame_parms->nb_antennas_rx*rel15_ul->nrOfLayers];
|
||||
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params = NULL;
|
||||
AssertFatal((gNB && !ue) || (!gNB && ue),"Both gNB and UE cannot be non-null\n");
|
||||
NR_DL_FRAME_PARMS *frame_parms = gNB ? &gNB->frame_parms : &ue->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
NR_gNB_ULSCH_t *ulsch = gNB ? &gNB->ulsch[ulsch_id] : &ue->slsch[ulsch_id];
|
||||
nfapi_nr_pusch_pdu_t *rel15_ul = gNB ? &ulsch->harq_process->ulsch_pdu : NULL;
|
||||
sl_nr_rx_config_pssch_sci_pdu_t *pssch_pdu = ue ? ulsch->harq_process->pssch_pdu : NULL;
|
||||
uint32_t nrOfLayers = pssch_pdu ? pssch_pdu->num_layers : rel15_ul->nrOfLayers;
|
||||
uint32_t rb_start = pssch_pdu ? pssch_pdu->startrb : rel15_ul->rb_start;
|
||||
uint32_t bwp_start = pssch_pdu ? 0 : rel15_ul->bwp_start;
|
||||
uint32_t rnti = pssch_pdu ? 0 : rel15_ul->rnti;
|
||||
|
||||
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id];
|
||||
uint32_t rb_size = pssch_pdu ? pssch_pdu->num_subch*pssch_pdu->subchannel_size : rel15_ul->rb_size;
|
||||
uint32_t qam_mod_order = pssch_pdu ? pssch_pdu->mod_order : rel15_ul->qam_mod_order;
|
||||
uint32_t start_symbol_index = pssch_pdu ? 1 : rel15_ul->start_symbol_index;
|
||||
uint32_t nr_of_symbols = pssch_pdu ? pssch_pdu->pssch_numsym : rel15_ul->nr_of_symbols;
|
||||
uint32_t dmrs_config_type = pssch_pdu ? 0 : rel15_ul->dmrs_config_type;
|
||||
uint32_t num_dmrs_cdm_grps_no_data = pssch_pdu ? 1 : rel15_ul->num_dmrs_cdm_grps_no_data;
|
||||
uint32_t ul_dmrs_symb_pos = pssch_pdu ? pssch_pdu->dmrs_symbol_position : rel15_ul->ul_dmrs_symb_pos;
|
||||
uint32_t dmrs_ports = pssch_pdu ? pssch_pdu->num_layers : rel15_ul->dmrs_ports;
|
||||
int sci1_re_per_symb = pssch_pdu ? (pssch_pdu->pscch_numrbs*NR_NB_SC_PER_RB) : 0;
|
||||
int sci2_re = pssch_pdu ? get_NREsci2_2(pssch_pdu->sci2_alpha_times_100,
|
||||
pssch_pdu->sci2_len,
|
||||
pssch_pdu->sci2_beta_offset,
|
||||
pssch_pdu->pssch_numsym,
|
||||
pssch_pdu->pscch_numsym,
|
||||
pssch_pdu->pscch_numrbs,
|
||||
pssch_pdu->l_subch,
|
||||
pssch_pdu->subchannel_size,
|
||||
pssch_pdu->targetCodeRate,
|
||||
0) : 0;
|
||||
int16_t sci2_llrs[(sci2_re*2)] __attribute__((aligned(16)));
|
||||
int16_t unscrambled_sci2_llrs[(sci2_re*2)] __attribute__((aligned(16)));
|
||||
int sci2_cnt=0;
|
||||
int sci2_left = sci2_re;
|
||||
|
||||
int avg[frame_parms->nb_antennas_rx*nrOfLayers];
|
||||
int16_t *temp_llr = (int16_t *)malloc16_clear((8 * ((3 * 8 * 6144) + 12)) * sizeof(int16_t));
|
||||
int32_t *temp_symbol = (int32_t *) malloc16_clear(rb_size * NR_NB_SC_PER_RB * sizeof(int32_t));
|
||||
NR_gNB_PUSCH *pusch_vars = gNB ? &gNB->pusch_vars[ulsch_id] : &ue->pssch_vars[ulsch_id];
|
||||
pusch_vars->dmrs_symbol = INVALID_VALUE;
|
||||
pusch_vars->cl_done = 0;
|
||||
|
||||
bwp_start_subcarrier = ((rel15_ul->rb_start + rel15_ul->bwp_start)*NR_NB_SC_PER_RB + frame_parms->first_carrier_offset) % frame_parms->ofdm_symbol_size;
|
||||
LOG_D(PHY,"pusch %d.%d : bwp_start_subcarrier %d, rb_start %d, first_carrier_offset %d\n", frame,slot,bwp_start_subcarrier, rel15_ul->rb_start, frame_parms->first_carrier_offset);
|
||||
LOG_D(PHY,"pusch %d.%d : ul_dmrs_symb_pos %x\n",frame,slot,rel15_ul->ul_dmrs_symb_pos);
|
||||
LOG_D(PHY,"ulsch RX %x : start_rb %d nb_rb %d mcs %d Nl %d Tpmi %d bwp_start %d start_sc %d start_symbol %d num_symbols %d cdmgrpsnodata %d num_dmrs %d dmrs_ports %d\n",
|
||||
rel15_ul->rnti,rel15_ul->rb_start,rel15_ul->rb_size,rel15_ul->mcs_index,
|
||||
rel15_ul->nrOfLayers,0,rel15_ul->bwp_start,0,rel15_ul->start_symbol_index,rel15_ul->nr_of_symbols,
|
||||
rel15_ul->num_dmrs_cdm_grps_no_data,rel15_ul->ul_dmrs_symb_pos,rel15_ul->dmrs_ports);
|
||||
bwp_start_subcarrier = ((rb_start + bwp_start)*NR_NB_SC_PER_RB + frame_parms->first_carrier_offset) % frame_parms->ofdm_symbol_size;
|
||||
LOG_D(PHY,"pusch %d.%d : bwp_start_subcarrier %d, rb_start %d, first_carrier_offset %d\n", frame,slot,bwp_start_subcarrier, rb_start, frame_parms->first_carrier_offset);
|
||||
LOG_D(PHY,"pusch %d.%d : ul_dmrs_symb_pos %x\n",frame,slot,ul_dmrs_symb_pos);
|
||||
LOG_D(PHY,"ulsch RX %x : start_rb %d nb_rb %d Nl %d Tpmi %d bwp_start %d start_sc %d start_symbol %d num_symbols %d cdmgrpsnodata %d num_dmrs %d dmrs_ports %d\n",
|
||||
rnti,rb_start,rb_size,
|
||||
nrOfLayers,0,bwp_start,0,start_symbol_index,nr_of_symbols,
|
||||
num_dmrs_cdm_grps_no_data,ul_dmrs_symb_pos,dmrs_ports);
|
||||
//----------------------------------------------------------
|
||||
//--------------------- Channel estimation ---------------------
|
||||
//----------------------------------------------------------
|
||||
start_meas(&gNB->ulsch_channel_estimation_stats);
|
||||
if (gNB) start_meas(&gNB->ulsch_channel_estimation_stats);
|
||||
int max_ch = 0;
|
||||
uint32_t nvar = 0;
|
||||
for(uint8_t symbol = rel15_ul->start_symbol_index; symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); symbol++) {
|
||||
uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01;
|
||||
for(uint8_t symbol = start_symbol_index; symbol < (start_symbol_index + nr_of_symbols); symbol++) {
|
||||
uint8_t dmrs_symbol_flag = (ul_dmrs_symb_pos >> symbol) & 0x01;
|
||||
LOG_D(PHY, "symbol %d, dmrs_symbol_flag :%d\n", symbol, dmrs_symbol_flag);
|
||||
|
||||
if (dmrs_symbol_flag == 1) {
|
||||
if (pusch_vars->dmrs_symbol == INVALID_VALUE)
|
||||
pusch_vars->dmrs_symbol = symbol;
|
||||
|
||||
for (int nl=0; nl<rel15_ul->nrOfLayers; nl++) {
|
||||
for (int nl=0; nl<nrOfLayers; nl++) {
|
||||
uint32_t nvar_tmp = 0;
|
||||
nr_pusch_channel_estimation(gNB,
|
||||
int dmrs_port = get_dmrs_port(nl,dmrs_ports);
|
||||
if (dmrs_port<0) return;
|
||||
nr_pusch_channel_estimation(gNB,ue,rxFSz,rxdataF,
|
||||
slot,
|
||||
get_dmrs_port(nl,rel15_ul->dmrs_ports),
|
||||
dmrs_port,
|
||||
symbol,
|
||||
ulsch_id,
|
||||
bwp_start_subcarrier,
|
||||
rel15_ul,
|
||||
pssch_pdu,
|
||||
&max_ch,
|
||||
&nvar_tmp);
|
||||
nvar += nvar_tmp;
|
||||
}
|
||||
|
||||
nr_gnb_measurements(gNB, ulsch, pusch_vars, symbol, rel15_ul->nrOfLayers);
|
||||
PHY_MEASUREMENTS_gNB *meas = gNB ? &gNB->measurements : ue->sl_measurements;
|
||||
nr_gnb_measurements(meas, frame_parms,ulsch, pusch_vars, symbol, nrOfLayers);
|
||||
allocCast2D(n0_subband_power,
|
||||
unsigned int,
|
||||
gNB->measurements.n0_subband_power,
|
||||
meas->n0_subband_power,
|
||||
frame_parms->nb_antennas_rx,
|
||||
frame_parms->N_RB_UL,
|
||||
false);
|
||||
for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
|
||||
if (symbol == rel15_ul->start_symbol_index) {
|
||||
if (symbol == start_symbol_index) {
|
||||
pusch_vars->ulsch_power[aarx] = 0;
|
||||
pusch_vars->ulsch_noise_power[aarx] = 0;
|
||||
}
|
||||
for (aatx = 0; aatx < rel15_ul->nrOfLayers; aatx++) {
|
||||
for (aatx = 0; aatx < nrOfLayers; aatx++) {
|
||||
pusch_vars->ulsch_power[aarx] += signal_energy_nodc(
|
||||
&pusch_vars->ul_ch_estimates[aatx * gNB->frame_parms.nb_antennas_rx + aarx][symbol * frame_parms->ofdm_symbol_size],
|
||||
rel15_ul->rb_size * 12);
|
||||
&pusch_vars->ul_ch_estimates[aatx * frame_parms->nb_antennas_rx + aarx][symbol * frame_parms->ofdm_symbol_size],
|
||||
rb_size * 12);
|
||||
}
|
||||
for (int rb = 0; rb < rel15_ul->rb_size; rb++) {
|
||||
for (int rb = 0; rb < rb_size; rb++) {
|
||||
pusch_vars->ulsch_noise_power[aarx] +=
|
||||
n0_subband_power[aarx][rel15_ul->bwp_start + rel15_ul->rb_start + rb] / rel15_ul->rb_size;
|
||||
n0_subband_power[aarx][bwp_start + rb_start + rb] / rb_size;
|
||||
}
|
||||
LOG_D(PHY,
|
||||
"aa %d, bwp_start%d, rb_start %d, rb_size %d: ulsch_power %d, ulsch_noise_power %d\n",
|
||||
aarx,
|
||||
rel15_ul->bwp_start,
|
||||
rel15_ul->rb_start,
|
||||
rel15_ul->rb_size,
|
||||
LOG_D(NR_PHY,
|
||||
"aa %d, symbol %d, bwp_start%d, rb_start %d, rb_size %d: ulsch_power %d, ulsch_noise_power %d\n",
|
||||
aarx,symbol,
|
||||
bwp_start,
|
||||
rb_start,
|
||||
rb_size,
|
||||
pusch_vars->ulsch_power[aarx],
|
||||
pusch_vars->ulsch_noise_power[aarx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nvar /= (rel15_ul->nr_of_symbols * rel15_ul->nrOfLayers * frame_parms->nb_antennas_rx);
|
||||
nvar /= (nr_of_symbols * nrOfLayers * frame_parms->nb_antennas_rx);
|
||||
|
||||
if (gNB->chest_time == 1) { // averaging time domain channel estimates
|
||||
if (gNB && gNB->chest_time == 1) { // averaging time domain channel estimates
|
||||
nr_chest_time_domain_avg(frame_parms,
|
||||
pusch_vars->ul_ch_estimates,
|
||||
rel15_ul->nr_of_symbols,
|
||||
rel15_ul->start_symbol_index,
|
||||
rel15_ul->ul_dmrs_symb_pos,
|
||||
rel15_ul->rb_size);
|
||||
nr_of_symbols,
|
||||
start_symbol_index,
|
||||
ul_dmrs_symb_pos,
|
||||
rb_size);
|
||||
|
||||
pusch_vars->dmrs_symbol =
|
||||
get_next_dmrs_symbol_in_slot(rel15_ul->ul_dmrs_symb_pos, rel15_ul->start_symbol_index, rel15_ul->nr_of_symbols);
|
||||
get_next_dmrs_symbol_in_slot(ul_dmrs_symb_pos, start_symbol_index, nr_of_symbols);
|
||||
}
|
||||
stop_meas(&gNB->ulsch_channel_estimation_stats);
|
||||
if (gNB) stop_meas(&gNB->ulsch_channel_estimation_stats);
|
||||
|
||||
int off = ((rel15_ul->rb_size&1) == 1)? 4:0;
|
||||
int off = ((rb_size&1) == 1)? 4:0;
|
||||
uint32_t rxdataF_ext_offset = 0;
|
||||
uint8_t shift_ch_ext = rel15_ul->nrOfLayers > 1 ? log2_approx(max_ch >> 11) : 0;
|
||||
uint8_t shift_ch_ext = nrOfLayers > 1 ? log2_approx(max_ch >> 11) : 0;
|
||||
|
||||
// Flag to select the receiver: (true) Nonlinear ML receiver, (false) Linear MMSE receiver
|
||||
// By default, we are using the Nonlinear ML receiver, except
|
||||
// - for 256QAM as Nonlinear ML receiver is not implemented for 256QAM
|
||||
// - for 64QAM as Nonlinear ML receiver requires more processing time than MMSE, and many machines are not powerful enough
|
||||
bool ml_rx = true;
|
||||
if (rel15_ul->nrOfLayers != 2 || rel15_ul->qam_mod_order >= 6) {
|
||||
if (nrOfLayers != 2 || qam_mod_order >= 6) {
|
||||
ml_rx = false;
|
||||
}
|
||||
|
||||
int ad_shift = 0;
|
||||
if (rel15_ul->nrOfLayers == 1) {
|
||||
if (nrOfLayers == 1) {
|
||||
ad_shift = 1 + log2_approx(frame_parms->nb_antennas_rx >> 2);
|
||||
} else if (ml_rx == false) {
|
||||
ad_shift = -3; // For 2-layers, we are already doing a bit shift in the nr_ulsch_mmse_2layers() function, so we can use more bits
|
||||
}
|
||||
|
||||
for(uint8_t symbol = rel15_ul->start_symbol_index; symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); symbol++) {
|
||||
uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01;
|
||||
if (dmrs_symbol_flag == 1) {
|
||||
if ((rel15_ul->ul_dmrs_symb_pos >> ((symbol + 1) % frame_parms->symbols_per_slot)) & 0x01)
|
||||
for(uint8_t symbol = start_symbol_index; symbol < (start_symbol_index + nr_of_symbols); symbol++) {
|
||||
|
||||
uint8_t csi_rs_symbol_flag = 0;
|
||||
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_CSI_RS) {
|
||||
*is_csi_rs_slot = true;
|
||||
csi_params = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)&ue->csirs_vars[0]->csirs_config_pdu;
|
||||
} else {
|
||||
*is_csi_rs_slot = false;
|
||||
}
|
||||
if (*is_csi_rs_slot && (csi_params->symb_l0 == symbol)) {
|
||||
csi_rs_symbol_flag = 1;
|
||||
AssertFatal(csi_params->freq_density > 0, "freq_density MUST be greater than zero");
|
||||
AssertFatal(csi_params->nr_of_rbs > 0, "nr_of_rbs MUST be greater than zero");
|
||||
LOG_D(NR_PHY, "%d.%d symbol %i, freq_density %i symb_l0 %i csi_type %i power_control_offset %i power_control_offset_ss %i measurement_bitmap %i cdm_type %i row %i freq_domain %i start_rb %i nr_of_rbs %i\n",
|
||||
frame,
|
||||
slot,
|
||||
symbol,
|
||||
csi_params->freq_density,
|
||||
csi_params->symb_l0,
|
||||
csi_params->csi_type,
|
||||
csi_params->power_control_offset,
|
||||
csi_params->power_control_offset_ss,
|
||||
csi_params->measurement_bitmap,
|
||||
csi_params->cdm_type,
|
||||
csi_params->row,
|
||||
csi_params->freq_domain,
|
||||
csi_params->start_rb,
|
||||
csi_params->nr_of_rbs);
|
||||
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_CSI_RS) {
|
||||
// FIXIT: Reconsider index of csirs_vars[0] for multiple connected UEs case
|
||||
if (ue->csirs_vars[0]->active == 1) {
|
||||
LOG_D(NR_PHY, "%d.%d Received CSI-RS\n", proc->frame_rx, proc->nr_slot_rx);
|
||||
nr_slot_fep(ue, frame_parms, proc, symbol, rxdataF, link_type_sl);
|
||||
nr_ue_csi_rs_procedures(ue, proc, rxdataF);
|
||||
ue->csirs_vars[0]->active = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t dmrs_symbol_flag = (ul_dmrs_symb_pos >> symbol) & 0x01;
|
||||
int sci2_cnt_thissymb=0;
|
||||
if (csi_rs_symbol_flag) {
|
||||
uint8_t freq_subcarriers_per_rb = 12;
|
||||
uint8_t nr_rbs_w_csi_rs = csi_params->nr_of_rbs / csi_params->freq_density;
|
||||
uint8_t nr_rbs_wo_csi_rs = (rb_size - nr_rbs_w_csi_rs);
|
||||
// Actually, kprime + 1 sub-carriers are used by csi-rs. kprime can be 0 or 1 but nb_antennas_tx can be greater than 2.
|
||||
uint8_t subcarriers_used = get_nrUE_params()->nb_antennas_tx > 2 ? 2 : get_nrUE_params()->nb_antennas_tx;
|
||||
nb_re_pusch = nr_rbs_wo_csi_rs * freq_subcarriers_per_rb + nr_rbs_w_csi_rs * (freq_subcarriers_per_rb - subcarriers_used);
|
||||
} else if (dmrs_symbol_flag == 1) {
|
||||
if ((ul_dmrs_symb_pos >> ((symbol + 1) % frame_parms->symbols_per_slot)) & 0x01)
|
||||
AssertFatal(1==0,"Double DMRS configuration is not yet supported\n");
|
||||
|
||||
if (gNB->chest_time == 0) // Non averaging time domain channel estimates
|
||||
if (ue || gNB->chest_time == 0) // Non averaging time domain channel estimates
|
||||
pusch_vars->dmrs_symbol = symbol;
|
||||
|
||||
if (rel15_ul->dmrs_config_type == 0) {
|
||||
if (dmrs_config_type == 0) {
|
||||
// if no data in dmrs cdm group is 1 only even REs have no data
|
||||
// if no data in dmrs cdm group is 2 both odd and even REs have no data
|
||||
nb_re_pusch = rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*6));
|
||||
nb_re_pusch = rb_size *(12 - (num_dmrs_cdm_grps_no_data*6));
|
||||
}
|
||||
else {
|
||||
nb_re_pusch = rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*4));
|
||||
nb_re_pusch = rb_size *(12 - (num_dmrs_cdm_grps_no_data*4));
|
||||
}
|
||||
}
|
||||
else {
|
||||
nb_re_pusch = rel15_ul->rb_size * NR_NB_SC_PER_RB;
|
||||
nb_re_pusch = rb_size * NR_NB_SC_PER_RB;
|
||||
}
|
||||
|
||||
pusch_vars->ul_valid_re_per_slot[symbol] = nb_re_pusch;
|
||||
LOG_D(PHY, "symbol %d: nb_re_pusch %d, DMRS symbl used for Chest :%d \n", symbol, nb_re_pusch, pusch_vars->dmrs_symbol);
|
||||
|
||||
//----------------------------------------------------------
|
||||
//--------------------- RBs extraction ---------------------
|
||||
//----------------------------------------------------------
|
||||
if (nb_re_pusch > 0) {
|
||||
start_meas(&gNB->ulsch_rbs_extraction_stats);
|
||||
nr_ulsch_extract_rbs(gNB->common_vars.rxdataF, pusch_vars, slot, symbol, dmrs_symbol_flag, rel15_ul, frame_parms);
|
||||
stop_meas(&gNB->ulsch_rbs_extraction_stats);
|
||||
LOG_D(NR_PHY,"extract RBs : frame %d, slot %d symbol %d nb_re_pusch %d\n", frame,slot,symbol, nb_re_pusch);
|
||||
if (gNB) start_meas(&gNB->ulsch_rbs_extraction_stats);
|
||||
nr_ulsch_extract_rbs(rxFSz, rxdataF, pusch_vars, slot, symbol, dmrs_symbol_flag, csi_rs_symbol_flag, bwp_start, rb_start, rb_size, nrOfLayers, num_dmrs_cdm_grps_no_data, dmrs_config_type, frame_parms, csi_params);
|
||||
if (gNB) stop_meas(&gNB->ulsch_rbs_extraction_stats);
|
||||
|
||||
//----------------------------------------------------------
|
||||
//--------------------- Channel Scaling --------------------
|
||||
@@ -2057,8 +2206,8 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
|
||||
symbol,
|
||||
dmrs_symbol_flag,
|
||||
nb_re_pusch,
|
||||
rel15_ul->nrOfLayers,
|
||||
rel15_ul->rb_size,
|
||||
nrOfLayers,
|
||||
rb_size,
|
||||
shift_ch_ext);
|
||||
|
||||
if (pusch_vars->cl_done == 0) {
|
||||
@@ -2067,12 +2216,12 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
|
||||
avg,
|
||||
symbol,
|
||||
nb_re_pusch,
|
||||
rel15_ul->nrOfLayers,
|
||||
rel15_ul->rb_size);
|
||||
nrOfLayers,
|
||||
rb_size);
|
||||
|
||||
avgs = 0;
|
||||
|
||||
for (aatx=0;aatx<rel15_ul->nrOfLayers;aatx++)
|
||||
for (aatx=0;aatx<nrOfLayers;aatx++)
|
||||
for (aarx=0;aarx<frame_parms->nb_antennas_rx;aarx++)
|
||||
avgs = cmax(avgs,avg[aatx*frame_parms->nb_antennas_rx+aarx]);
|
||||
|
||||
@@ -2086,57 +2235,57 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
|
||||
//----------------------------------------------------------
|
||||
//--------------------- Channel Compensation ---------------
|
||||
//----------------------------------------------------------
|
||||
start_meas(&gNB->ulsch_channel_compensation_stats);
|
||||
LOG_D(PHY, "Doing channel compensations log2_maxh %d, avgs %d (%d,%d)\n" ,pusch_vars->log2_maxh, avgs,avg[0], avg[1]);
|
||||
if (gNB) start_meas(&gNB->ulsch_channel_compensation_stats);
|
||||
//LOG_I(PHY, "Doing channel compensations log2_maxh %d, avgs %d (%d,%d)\n" ,pusch_vars->log2_maxh, avgs,avg[0], avg[1]);
|
||||
nr_ulsch_channel_compensation(pusch_vars->rxdataF_ext,
|
||||
pusch_vars->ul_ch_estimates_ext,
|
||||
pusch_vars->ul_ch_mag0,
|
||||
pusch_vars->ul_ch_magb0,
|
||||
pusch_vars->ul_ch_magc0,
|
||||
pusch_vars->rxdataF_comp,
|
||||
(rel15_ul->nrOfLayers > 1) ? pusch_vars->rho : NULL,
|
||||
(nrOfLayers > 1) ? pusch_vars->rho : NULL,
|
||||
frame_parms,
|
||||
symbol,
|
||||
nb_re_pusch,
|
||||
dmrs_symbol_flag,
|
||||
rel15_ul->qam_mod_order,
|
||||
rel15_ul->nrOfLayers,
|
||||
rel15_ul->rb_size,
|
||||
qam_mod_order,
|
||||
nrOfLayers,
|
||||
rb_size,
|
||||
pusch_vars->log2_maxh);
|
||||
stop_meas(&gNB->ulsch_channel_compensation_stats);
|
||||
if (gNB) stop_meas(&gNB->ulsch_channel_compensation_stats);
|
||||
|
||||
start_meas(&gNB->ulsch_mrc_stats);
|
||||
if (gNB) start_meas(&gNB->ulsch_mrc_stats);
|
||||
nr_ulsch_detection_mrc(frame_parms,
|
||||
pusch_vars->rxdataF_comp,
|
||||
pusch_vars->ul_ch_mag0,
|
||||
pusch_vars->ul_ch_magb0,
|
||||
pusch_vars->ul_ch_magc0,
|
||||
(rel15_ul->nrOfLayers > 1) ? pusch_vars->rho : NULL,
|
||||
rel15_ul->nrOfLayers,
|
||||
(nrOfLayers > 1) ? pusch_vars->rho : NULL,
|
||||
nrOfLayers,
|
||||
symbol,
|
||||
rel15_ul->rb_size,
|
||||
rb_size,
|
||||
nb_re_pusch);
|
||||
|
||||
// Apply MMSE for 2 Tx layers
|
||||
if (ml_rx == false && rel15_ul->nrOfLayers == 2) {
|
||||
if (ml_rx == false && nrOfLayers == 2) {
|
||||
nr_ulsch_mmse_2layers(frame_parms,
|
||||
pusch_vars->rxdataF_comp,
|
||||
pusch_vars->ul_ch_mag0,
|
||||
pusch_vars->ul_ch_magb0,
|
||||
pusch_vars->ul_ch_magc0,
|
||||
pusch_vars->ul_ch_estimates_ext,
|
||||
rel15_ul->rb_size,
|
||||
rb_size,
|
||||
frame_parms->nb_antennas_rx,
|
||||
rel15_ul->qam_mod_order,
|
||||
qam_mod_order,
|
||||
pusch_vars->log2_maxh,
|
||||
symbol,
|
||||
nb_re_pusch,
|
||||
nvar);
|
||||
}
|
||||
|
||||
stop_meas(&gNB->ulsch_mrc_stats);
|
||||
if (gNB) stop_meas(&gNB->ulsch_mrc_stats);
|
||||
|
||||
if (rel15_ul->transform_precoding == transformPrecoder_enabled) {
|
||||
if (gNB && rel15_ul->transform_precoding == transformPrecoder_enabled) {
|
||||
// For odd number of resource blocks need byte alignment to multiple of 8
|
||||
int nb_re_pusch2 = nb_re_pusch + (nb_re_pusch&7);
|
||||
|
||||
@@ -2150,16 +2299,17 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
|
||||
//----------------------------------------------------------
|
||||
/* In case PTRS is enabled then LLR will be calculated after PTRS symbols are processed *
|
||||
* otherwise LLR are calculated for each symbol based upon DMRS channel estimates only. */
|
||||
if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
|
||||
start_meas(&gNB->ulsch_ptrs_processing_stats);
|
||||
nr_pusch_ptrs_processing(gNB,
|
||||
if (gNB && rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
|
||||
if (gNB) start_meas(&gNB->ulsch_ptrs_processing_stats);
|
||||
nr_pusch_ptrs_processing(gNB,ue,
|
||||
frame_parms,
|
||||
rel15_ul,
|
||||
pssch_pdu,
|
||||
ulsch_id,
|
||||
slot,
|
||||
symbol,
|
||||
nb_re_pusch);
|
||||
stop_meas(&gNB->ulsch_ptrs_processing_stats);
|
||||
if (gNB) stop_meas(&gNB->ulsch_ptrs_processing_stats);
|
||||
|
||||
/* Subtract total PTRS RE's in the symbol from PUSCH RE's */
|
||||
pusch_vars->ul_valid_re_per_slot[symbol] -= pusch_vars->ptrs_re_per_slot;
|
||||
@@ -2168,38 +2318,125 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
|
||||
/*---------------------------------------------------------------------------------------------------- */
|
||||
/*-------------------- LLRs computation -------------------------------------------------------------*/
|
||||
/*-----------------------------------------------------------------------------------------------------*/
|
||||
start_meas(&gNB->ulsch_llr_stats);
|
||||
if (ml_rx == false || rel15_ul->nrOfLayers == 1) {
|
||||
for (aatx=0; aatx < rel15_ul->nrOfLayers; aatx++) {
|
||||
nr_ulsch_compute_llr(&pusch_vars->rxdataF_comp[aatx * frame_parms->nb_antennas_rx][symbol * (off + rel15_ul->rb_size * NR_NB_SC_PER_RB)],
|
||||
pusch_vars->ul_ch_mag0[aatx * frame_parms->nb_antennas_rx],
|
||||
pusch_vars->ul_ch_magb0[aatx * frame_parms->nb_antennas_rx],
|
||||
pusch_vars->ul_ch_magc0[aatx * frame_parms->nb_antennas_rx],
|
||||
&pusch_vars->llr_layers[aatx][rxdataF_ext_offset * rel15_ul->qam_mod_order],
|
||||
rel15_ul->rb_size,
|
||||
pusch_vars->ul_valid_re_per_slot[symbol],
|
||||
symbol,
|
||||
rel15_ul->qam_mod_order);
|
||||
if (gNB) start_meas(&gNB->ulsch_llr_stats);
|
||||
int sci1_offset=0;
|
||||
if (symbol <= pssch_pdu->pscch_numsym) {
|
||||
pusch_vars->ul_valid_re_per_slot[symbol] -= sci1_re_per_symb;
|
||||
sci1_offset=sci1_re_per_symb;
|
||||
}
|
||||
if (ml_rx == false || nrOfLayers == 1) {
|
||||
if (pssch_pdu && sci2_left>0){
|
||||
LOG_D(NR_PHY, "valid_re_per_slot[%d] %d\n", symbol, pusch_vars->ul_valid_re_per_slot[symbol]);
|
||||
int available_sci2_res_in_symb = pusch_vars->ul_valid_re_per_slot[symbol];
|
||||
int slsch_res_in_symbol;
|
||||
LOG_D(NR_PHY,"available_sci2_res_in_symb[%d] %d (sci1_re %d)\n",symbol,available_sci2_res_in_symb,sci1_re_per_symb);
|
||||
int sci2_cnt_prev = sci2_cnt;
|
||||
if (available_sci2_res_in_symb < sci2_left) {
|
||||
sci2_cnt += available_sci2_res_in_symb; // take all of the PSSCH REs for SCI2
|
||||
memcpy(&sci2_llrs[2*sci2_cnt_prev],&pusch_vars->rxdataF_comp[0][(symbol * (off + rb_size * NR_NB_SC_PER_RB))+sci1_offset],
|
||||
available_sci2_res_in_symb*sizeof(int32_t));
|
||||
sci2_left-= available_sci2_res_in_symb;
|
||||
LOG_D(NR_PHY,"SCI2 taking all available REs. sci2_left %d\n",sci2_left);
|
||||
pusch_vars->ul_valid_re_per_slot[symbol] = 0;
|
||||
sci2_cnt_thissymb=available_sci2_res_in_symb;
|
||||
}
|
||||
else { // we finish SCI2 off here
|
||||
memcpy(&sci2_llrs[2*sci2_cnt_prev],&pusch_vars->rxdataF_comp[0][(symbol * (off + rb_size * NR_NB_SC_PER_RB))+sci1_re_per_symb],
|
||||
sci2_left*sizeof(int32_t));
|
||||
slsch_res_in_symbol=available_sci2_res_in_symb-sci2_left;
|
||||
LOG_D(NR_PHY, "SCI2 taking %d REs, SLSCH taking %d\n", sci2_left, slsch_res_in_symbol);
|
||||
pusch_vars->ul_valid_re_per_slot[symbol]=slsch_res_in_symbol;
|
||||
sci2_cnt_thissymb=sci2_left;
|
||||
sci2_left=0;
|
||||
//for (int i=0;i<sci2_re;i++) LOG_I(NR_PHY,"sci2_llrs [%d] %d,%d\n",i,sci2_llrs[i<<1],sci2_llrs[1+(i<<1)]);
|
||||
//unscramble the SCI2 payload
|
||||
nr_pdcch_unscrambling(sci2_llrs, 1010,sci2_re*2,pssch_pdu->Nid,unscrambled_sci2_llrs,1);
|
||||
// for (int i=0;i<sci2_re;i++) LOG_I(NR_PHY,"sci2_llrs [%d] %d,%d\n",i,unscrambled_sci2_llrs[i<<1],unscrambled_sci2_llrs[1+(i<<1)]);
|
||||
|
||||
uint64_t sci_estimation[2]={0};
|
||||
uint16_t dummy;
|
||||
uint16_t crc = polar_decoder_int16(unscrambled_sci2_llrs,
|
||||
sci_estimation,
|
||||
&dummy,
|
||||
1,
|
||||
NR_POLAR_SCI2_MESSAGE_TYPE,
|
||||
pssch_pdu->sci2_len,
|
||||
sci2_re);
|
||||
// send SCI indication with SCI2 payload and get SLSCH information if CRC is OK
|
||||
LOG_D(NR_PHY,"SCI indication (crc %x)\n",crc);
|
||||
if (crc==0) ue->SL_UE_PHY_PARAMS.pssch.rx_sci2_ok++;
|
||||
else ue->SL_UE_PHY_PARAMS.pssch.rx_sci2_errors++;
|
||||
sl_nr_sci_indication_t sci_ind={0};
|
||||
sci_ind.sfn = frame;
|
||||
sci_ind.slot = slot;
|
||||
sci_ind.sensing_result = 0;
|
||||
sci_ind.pssch_rsrp = 0; // setting this flag to zero; measuring from sci1
|
||||
sci_ind.sci_pdu[sci_ind.number_of_SCIs].sci_format_type = SL_SCI_FORMAT_2_ON_PSSCH;
|
||||
sci_ind.sci_pdu[sci_ind.number_of_SCIs].subch_index = 0;
|
||||
sci_ind.sci_pdu[sci_ind.number_of_SCIs].pscch_rsrp = 0; // setting this flag to zero; measuring from sci1
|
||||
sci_ind.sci_pdu[sci_ind.number_of_SCIs].sci_payloadlen = pssch_pdu->sci2_len;
|
||||
sci_ind.sci_pdu[sci_ind.number_of_SCIs].Nid = dummy&65535;
|
||||
|
||||
memcpy(sci_ind.sci_pdu[sci_ind.number_of_SCIs].sci_payloadBits,&sci_estimation,8);
|
||||
sci_ind.number_of_SCIs++;
|
||||
nr_sidelink_indication_t sl_indication;
|
||||
nr_fill_sl_indication(&sl_indication, NULL, &sci_ind, proc, ue, phy_data);
|
||||
ue->if_inst->sl_indication(&sl_indication);
|
||||
LOG_D(NR_PHY,"Returning from SCI2 SL indication\n");
|
||||
//
|
||||
}
|
||||
} // (not ML || nrOfLayers==1 ) AND pssch and sci2 REs to handle
|
||||
if (pssch_pdu) LOG_D(NR_PHY, "symbol %d: PSSCH REs %d (sci1 %d,sci2 %d)\n", symbol, pusch_vars->ul_valid_re_per_slot[symbol], sci1_offset, sci2_cnt_thissymb);
|
||||
for (aatx=0; aatx < nrOfLayers; aatx++) {
|
||||
if ((sci1_offset > 0 || sci2_cnt_thissymb > 0) && (qam_mod_order > 2)) {
|
||||
memset(temp_symbol, 0, (sci1_offset + sci2_cnt_thissymb) * sizeof(int32_t));
|
||||
memcpy(temp_symbol + sci1_offset + sci2_cnt_thissymb,
|
||||
&pusch_vars->rxdataF_comp[aatx * frame_parms->nb_antennas_rx][symbol * (off + rb_size * NR_NB_SC_PER_RB) + sci1_offset+sci2_cnt_thissymb],
|
||||
(rb_size * NR_NB_SC_PER_RB - (sci1_offset + sci2_cnt_thissymb)) * sizeof(int32_t));
|
||||
nr_ulsch_compute_llr(temp_symbol,
|
||||
pusch_vars->ul_ch_mag0[aatx * frame_parms->nb_antennas_rx],
|
||||
pusch_vars->ul_ch_magb0[aatx * frame_parms->nb_antennas_rx],
|
||||
pusch_vars->ul_ch_magc0[aatx * frame_parms->nb_antennas_rx],
|
||||
temp_llr,
|
||||
rb_size,
|
||||
rb_size * NR_NB_SC_PER_RB,
|
||||
symbol,
|
||||
qam_mod_order);
|
||||
memcpy(&pusch_vars->llr_layers[aatx][rxdataF_ext_offset * qam_mod_order],
|
||||
temp_llr + (sci1_offset + sci2_cnt_thissymb) * qam_mod_order,
|
||||
(rb_size * NR_NB_SC_PER_RB - (sci1_offset + sci2_cnt_thissymb)) * 2 * qam_mod_order);
|
||||
} else {
|
||||
nr_ulsch_compute_llr(&pusch_vars->rxdataF_comp[aatx * frame_parms->nb_antennas_rx][symbol * (off + rb_size * NR_NB_SC_PER_RB) + sci1_offset + sci2_cnt_thissymb],
|
||||
pusch_vars->ul_ch_mag0[aatx * frame_parms->nb_antennas_rx],
|
||||
pusch_vars->ul_ch_magb0[aatx * frame_parms->nb_antennas_rx],
|
||||
pusch_vars->ul_ch_magc0[aatx * frame_parms->nb_antennas_rx],
|
||||
&pusch_vars->llr_layers[aatx][rxdataF_ext_offset * qam_mod_order],
|
||||
rb_size,
|
||||
pusch_vars->ul_valid_re_per_slot[symbol],
|
||||
symbol,
|
||||
qam_mod_order);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else { // this is MIMO case with ML
|
||||
if (pssch_pdu) AssertFatal(1==0,"We need to handle the MIMO case for SCI2\n");
|
||||
nr_ulsch_compute_ML_llr(pusch_vars->rxdataF_comp,
|
||||
pusch_vars->ul_ch_mag0,
|
||||
pusch_vars->rho,
|
||||
pusch_vars->llr_layers,
|
||||
frame_parms->nb_antennas_rx,
|
||||
rel15_ul->rb_size,
|
||||
rb_size,
|
||||
nb_re_pusch,
|
||||
symbol,
|
||||
rxdataF_ext_offset,
|
||||
rel15_ul->qam_mod_order);
|
||||
qam_mod_order);
|
||||
|
||||
if (rel15_ul->qam_mod_order == 2) {
|
||||
nr_ulsch_shift_llr(pusch_vars->llr_layers, nb_re_pusch, rxdataF_ext_offset, rel15_ul->qam_mod_order, 4);
|
||||
if (qam_mod_order == 2) {
|
||||
nr_ulsch_shift_llr(pusch_vars->llr_layers, nb_re_pusch, rxdataF_ext_offset, qam_mod_order, 4);
|
||||
}
|
||||
|
||||
#ifdef ML_DEBUG
|
||||
c16_t *llr_layers0 = (c16_t *)&pusch_vars->llr_layers[0][rxdataF_ext_offset * rel15_ul->qam_mod_order];
|
||||
c16_t *llr_layers1 = (c16_t *)&pusch_vars->llr_layers[1][rxdataF_ext_offset * rel15_ul->qam_mod_order];
|
||||
c16_t *llr_layers0 = (c16_t *)&pusch_vars->llr_layers[0][rxdataF_ext_offset * qam_mod_order];
|
||||
c16_t *llr_layers1 = (c16_t *)&pusch_vars->llr_layers[1][rxdataF_ext_offset * qam_mod_order];
|
||||
printf("===============================\n");
|
||||
printf("AFTER nr_ulsch_compute_ML_llr()\n");
|
||||
printf("===============================\n");
|
||||
@@ -2214,4 +2451,6 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
|
||||
rxdataF_ext_offset += pusch_vars->ul_valid_re_per_slot[symbol];
|
||||
}
|
||||
} // symbol loop
|
||||
free(temp_llr);
|
||||
free(temp_symbol);
|
||||
}
|
||||
|
||||
@@ -116,36 +116,6 @@ int get_pucch0_cs_lut_index(PHY_VARS_gNB *gNB,nfapi_nr_pucch_pdu_t* pucch_pdu) {
|
||||
gNB->pucch0_lut.nb_id++;
|
||||
return(gNB->pucch0_lut.nb_id-1);
|
||||
}
|
||||
|
||||
static const int16_t idft12_re[12][12] = {
|
||||
{23170,23170,23170,23170,23170,23170,23170,23170,23170,23170,23170,23170},
|
||||
{23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585,0,11585,20066},
|
||||
{23170,11585,-11585,-23170,-11585,11585,23170,11585,-11585,-23170,-11585,11585},
|
||||
{23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170,0},
|
||||
{23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585},
|
||||
{23170,-20066,11585,0,-11585,20066,-23170,20066,-11585,0,11585,-20066},
|
||||
{23170,-23170,23170,-23170,23170,-23170,23170,-23170,23170,-23170,23170,-23170},
|
||||
{23170,-20066,11585,0,-11585,20066,-23170,20066,-11585,0,11585,-20066},
|
||||
{23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585},
|
||||
{23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170,0},
|
||||
{23170,11585,-11585,-23170,-11585,11585,23170,11585,-11585,-23170,-11585,11585},
|
||||
{23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585,0,11585,20066}
|
||||
};
|
||||
|
||||
static const int16_t idft12_im[12][12] = {
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0},
|
||||
{0,11585,20066,23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585},
|
||||
{0,20066,20066,0,-20066,-20066,0,20066,20066,0,-20066,-20066},
|
||||
{0,23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170},
|
||||
{0,20066,-20066,0,20066,-20066,0,20066,-20066,0,20066,-20066},
|
||||
{0,11585,-20066,23170,-20066,11585,0,-11585,20066,-23170,20066,-11585},
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0},
|
||||
{0,-11585,20066,-23170,20066,-11585,0,11585,-20066,23170,-20066,11585},
|
||||
{0,-20066,20066,0,-20066,20066,0,-20066,20066,0,-20066,20066},
|
||||
{0,-23170,0,23170,0,-23170,0,23170,0,-23170,0,23170},
|
||||
{0,-20066,-20066,0,20066,20066,0,-20066,-20066,0,20066,20066},
|
||||
{0,-11585,-20066,-23170,-20066,-11585,0,11585,20066,23170,20066,11585}
|
||||
};
|
||||
|
||||
void nr_decode_pucch0(PHY_VARS_gNB *gNB,
|
||||
int frame,
|
||||
@@ -1691,7 +1661,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
|
||||
} // symb
|
||||
|
||||
// run polar decoder on llrs
|
||||
decoderState = polar_decoder_int16((int16_t *)llrs, decodedPayload, 0, NR_POLAR_UCI_PUCCH_MESSAGE_TYPE, nb_bit, pucch_pdu->prb_size);
|
||||
decoderState = polar_decoder_int16((int16_t *)llrs, decodedPayload, NULL, 0, NR_POLAR_UCI_PUCCH_MESSAGE_TYPE, nb_bit, pucch_pdu->prb_size);
|
||||
|
||||
LOG_D(PHY,"UCI decoderState %d, payload[0] %llu\n",decoderState,(unsigned long long)decodedPayload[0]);
|
||||
if (decoderState>0) decoderState=1;
|
||||
|
||||
@@ -44,6 +44,9 @@
|
||||
#define CH_INTERP 0
|
||||
#define NO_INTERP 1
|
||||
|
||||
// 10*log10(pow(2,30))
|
||||
#define pow_2_30_dB 90
|
||||
extern openair0_config_t openair0_cfg[];
|
||||
/* 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)
|
||||
{
|
||||
@@ -608,7 +611,7 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
#endif
|
||||
|
||||
// generate pilot
|
||||
nr_pbch_dmrs_rx(dmrss,ue->nr_gold_pbch[n_hf][ssb_index], &pilot[0]);
|
||||
nr_pbch_dmrs_rx(dmrss,ue->nr_gold_pbch[n_hf][ssb_index], &pilot[0],0);
|
||||
|
||||
for (int aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
|
||||
@@ -729,15 +732,18 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
|
||||
int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
NR_DL_FRAME_PARMS *fp,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
struct complex16 dl_ch_estimates_time[][ue->frame_parms.ofdm_symbol_size],
|
||||
struct complex16 dl_ch_estimates_time[][fp->ofdm_symbol_size],
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
unsigned char symbol,
|
||||
int dmrss,
|
||||
uint8_t ssb_index,
|
||||
uint8_t n_hf,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
|
||||
c16_t rxdataF[][fp->samples_per_slot_wCP],
|
||||
bool sidelink,
|
||||
uint16_t Nid)
|
||||
{
|
||||
int Ns = proc->nr_slot_rx;
|
||||
int pilot[200] __attribute__((aligned(16)));
|
||||
@@ -748,25 +754,48 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
int ch_offset,symbol_offset;
|
||||
//int slot_pbch;
|
||||
|
||||
uint8_t nushift;
|
||||
nushift = ue->frame_parms.Nid_cell%4;
|
||||
ue->frame_parms.nushift = nushift;
|
||||
unsigned int ssb_offset = ue->frame_parms.first_carrier_offset + ue->frame_parms.ssb_start_subcarrier;
|
||||
if (ssb_offset>= ue->frame_parms.ofdm_symbol_size) ssb_offset-=ue->frame_parms.ofdm_symbol_size;
|
||||
uint8_t nushift = 0, lastsymbol = 0;
|
||||
|
||||
ch_offset = ue->frame_parms.ofdm_symbol_size*symbol;
|
||||
uint32_t *gold_seq = NULL;
|
||||
|
||||
AssertFatal(dmrss >= 0 && dmrss < 3,
|
||||
if (sidelink) {
|
||||
|
||||
AssertFatal(dmrss == 0 || (dmrss >= 5 && dmrss <= 12),
|
||||
"symbol %d is illegal for PSBCH DM-RS \n",
|
||||
dmrss);
|
||||
|
||||
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
|
||||
|
||||
LOG_D(PHY,"PSBCH Channel Estimation SLSSID:%d\n", Nid);
|
||||
|
||||
gold_seq = sl_phy_params->init_params.psbch_dmrs_gold_sequences[Nid];
|
||||
lastsymbol = 12;
|
||||
|
||||
} else {
|
||||
|
||||
nushift = fp->Nid_cell%4;
|
||||
fp->nushift = nushift;
|
||||
|
||||
AssertFatal(dmrss >= 0 && dmrss < 3,
|
||||
"symbol %d is illegal for PBCH DM-RS \n",
|
||||
dmrss);
|
||||
|
||||
symbol_offset = ue->frame_parms.ofdm_symbol_size*symbol;
|
||||
gold_seq = ue->nr_gold_pbch[n_hf][ssb_index];
|
||||
lastsymbol = 2;
|
||||
}
|
||||
|
||||
unsigned int ssb_offset = fp->first_carrier_offset + fp->ssb_start_subcarrier;
|
||||
if (ssb_offset>= fp->ofdm_symbol_size) ssb_offset-= fp->ofdm_symbol_size;
|
||||
|
||||
ch_offset = fp->ofdm_symbol_size*symbol;
|
||||
|
||||
symbol_offset = fp->ofdm_symbol_size*symbol;
|
||||
|
||||
|
||||
k = nushift;
|
||||
|
||||
#ifdef DEBUG_PBCH
|
||||
printf("PBCH Channel Estimation : gNB_id %d ch_offset %d, OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n", proc->gNB_id, ch_offset, ue->frame_parms.ofdm_symbol_size, ue->frame_parms.Ncp, Ns, k, symbol);
|
||||
printf("PBCH Channel Estimation : gNB_id %d ch_offset %d, OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n", proc->gNB_id, ch_offset, fp->ofdm_symbol_size, fp->Ncp, Ns, k, symbol);
|
||||
#endif
|
||||
|
||||
switch (k) {
|
||||
@@ -802,7 +831,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
|
||||
idft_size_idx_t idftsizeidx;
|
||||
|
||||
switch (ue->frame_parms.ofdm_symbol_size) {
|
||||
switch (fp->ofdm_symbol_size) {
|
||||
case 128:
|
||||
idftsizeidx = IDFT_128;
|
||||
break;
|
||||
@@ -849,20 +878,20 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
|
||||
// generate pilot
|
||||
nr_pbch_dmrs_rx(dmrss,ue->nr_gold_pbch[n_hf][ssb_index], &pilot[0]);
|
||||
nr_pbch_dmrs_rx(dmrss,gold_seq, &pilot[0], sidelink);
|
||||
|
||||
for (int aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
for (int aarx=0; aarx<fp->nb_antennas_rx; aarx++) {
|
||||
|
||||
int re_offset = ssb_offset;
|
||||
pil = (int16_t *)&pilot[0];
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
dl_ch = (int16_t *)&dl_ch_estimates[aarx][ch_offset];
|
||||
|
||||
memset(dl_ch,0,sizeof(struct complex16)*(ue->frame_parms.ofdm_symbol_size));
|
||||
memset(dl_ch,0,sizeof(struct complex16)*(fp->ofdm_symbol_size));
|
||||
|
||||
#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("pbch ch est pilot addr %p RB_DL %d\n",&pilot[0], fp->N_RB_DL);
|
||||
printf("k %d, first_carrier %d\n",k,fp->first_carrier_offset);
|
||||
printf("rxF addr %p\n", rxF);
|
||||
printf("dl_ch addr %p\n",dl_ch);
|
||||
#endif
|
||||
@@ -881,7 +910,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
dl_ch,
|
||||
16);
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
re_offset = (re_offset+4) % fp->ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
|
||||
//for (int i= 0; i<8; i++)
|
||||
@@ -899,7 +928,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
dl_ch,
|
||||
16);
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
re_offset = (re_offset+4) % fp->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);
|
||||
@@ -914,7 +943,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
dl_ch,
|
||||
16);
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
re_offset = (re_offset+4) % fp->ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
dl_ch += 24;
|
||||
|
||||
@@ -926,7 +955,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
// in 2nd symbol, skip middle REs (48 with DMRS, 144 for SSS, and another 48 with DMRS)
|
||||
if (dmrss == 1 && pilot_cnt == 12) {
|
||||
pilot_cnt=48;
|
||||
re_offset = (re_offset+144) % ue->frame_parms.ofdm_symbol_size;
|
||||
re_offset = (re_offset+144) % fp->ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
dl_ch += 288;
|
||||
}
|
||||
@@ -945,7 +974,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
// printf("pilot_cnt %d dl_ch %d %d\n", pilot_cnt, dl_ch+i, *(dl_ch+i));
|
||||
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
re_offset = (re_offset+4) % fp->ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
|
||||
|
||||
@@ -960,7 +989,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
dl_ch,
|
||||
16);
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
re_offset = (re_offset+4) % fp->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);
|
||||
@@ -975,13 +1004,13 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
dl_ch,
|
||||
16);
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
re_offset = (re_offset+4) % fp->ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
dl_ch += 24;
|
||||
|
||||
}
|
||||
|
||||
if( dmrss == 2) // update time statistics for last PBCH symbol
|
||||
if( dmrss == lastsymbol) // update time statistics for last PBCH symbol
|
||||
{
|
||||
// do ifft of channel estimate
|
||||
LOG_D(PHY,"Channel Impulse Computation Slot %d Symbol %d ch_offset %d\n", Ns, symbol, ch_offset);
|
||||
@@ -992,27 +1021,34 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
}
|
||||
|
||||
if (dmrss == 2)
|
||||
if (dmrss == lastsymbol) {
|
||||
|
||||
enum scopeDataType typ = (sidelink) ? psbchDlChEstimateTime
|
||||
: pbchDlChEstimateTime;
|
||||
|
||||
UEscopeCopy(ue,
|
||||
pbchDlChEstimateTime,
|
||||
typ,
|
||||
(void *)dl_ch_estimates_time,
|
||||
sizeof(c16_t),
|
||||
ue->frame_parms.nb_antennas_rx,
|
||||
ue->frame_parms.ofdm_symbol_size,
|
||||
fp->nb_antennas_rx,
|
||||
fp->ofdm_symbol_size,
|
||||
0);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int pscch_flag,
|
||||
unsigned char symbol,
|
||||
fapi_nr_coreset_t *coreset,
|
||||
uint16_t first_carrier_offset,
|
||||
uint16_t BWPStart,
|
||||
int32_t pdcch_est_size,
|
||||
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
|
||||
int16_t *rsrp_dBm)
|
||||
{
|
||||
|
||||
int Ns = proc->nr_slot_rx;
|
||||
@@ -1022,6 +1058,9 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
unsigned int pilot_cnt;
|
||||
int16_t ch[2],*pil,*rxF,*dl_ch;
|
||||
int ch_offset,symbol_offset;
|
||||
uint16_t meas_count = 0;
|
||||
int32_t rsrp_sum = 0;
|
||||
int rsrp = 0;
|
||||
|
||||
ch_offset = ue->frame_parms.ofdm_symbol_size*symbol;
|
||||
|
||||
@@ -1029,12 +1068,16 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
|
||||
int nb_rb_coreset=0;
|
||||
int coreset_start_rb=0;
|
||||
get_coreset_rballoc(coreset->frequency_domain_resource,&nb_rb_coreset,&coreset_start_rb);
|
||||
if (pscch_flag == 0) get_coreset_rballoc(coreset->frequency_domain_resource,&nb_rb_coreset,&coreset_start_rb);
|
||||
else {
|
||||
coreset_start_rb = coreset->frequency_domain_resource[0];
|
||||
nb_rb_coreset = coreset->frequency_domain_resource[1];
|
||||
}
|
||||
if(nb_rb_coreset==0) return;
|
||||
|
||||
#ifdef DEBUG_PDCCH
|
||||
printf("pdcch_channel_estimation: first_carrier_offset %d, BWPStart %d, coreset_start_rb %d, coreset_nb_rb %d\n",
|
||||
first_carrier_offset, BWPStart, coreset_start_rb, nb_rb_coreset);
|
||||
printf("pdcch_channel_estimation: first_carrier_offset %d, BWPStart %d, coreset_start_rb %d, coreset_nb_rb %d, symbold %d\n",
|
||||
first_carrier_offset, BWPStart, coreset_start_rb, nb_rb_coreset,symbol);
|
||||
#endif
|
||||
|
||||
unsigned short coreset_start_subcarrier = first_carrier_offset+(BWPStart + coreset_start_rb)*12;
|
||||
@@ -1052,17 +1095,20 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
|
||||
unsigned short scrambling_id = coreset->pdcch_dmrs_scrambling_id;
|
||||
// checking if re-initialization of scrambling IDs is needed (should be done here but scrambling ID for PDCCH is not taken from RRC)
|
||||
if (scrambling_id != ue->scramblingID_pdcch){
|
||||
if (pscch_flag == 0 && scrambling_id != ue->scramblingID_pdcch){
|
||||
ue->scramblingID_pdcch = scrambling_id;
|
||||
nr_gold_pdcch(ue,ue->scramblingID_pdcch);
|
||||
nr_gold_pdcch(&ue->frame_parms,ue->nr_gold_pdcch[gNB_id],ue->scramblingID_pdcch);
|
||||
}
|
||||
|
||||
|
||||
int dmrs_ref = 0;
|
||||
if (coreset->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG)
|
||||
dmrs_ref = BWPStart;
|
||||
// generate pilot
|
||||
int pilot[(nb_rb_coreset + dmrs_ref) * 3] __attribute__((aligned(16)));
|
||||
nr_pdcch_dmrs_rx(ue,Ns,ue->nr_gold_pdcch[gNB_id][Ns][symbol], &pilot[0],2000,(nb_rb_coreset+dmrs_ref));
|
||||
if (pscch_flag ==0)
|
||||
nr_pdcch_dmrs_rx(ue,Ns,ue->nr_gold_pdcch[gNB_id][Ns][symbol], &pilot[0],2000,(nb_rb_coreset+dmrs_ref));
|
||||
else
|
||||
nr_pdcch_dmrs_rx(ue,Ns,ue->nr_gold_pscch[Ns][symbol], &pilot[0],2000,(nb_rb_coreset+dmrs_ref));
|
||||
|
||||
for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
|
||||
@@ -1212,6 +1258,8 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
#else //ELSE CH_INTERP
|
||||
int ch_sum[2] = {0, 0};
|
||||
|
||||
c16_t rx_signal = rxdataF[aarx][(symbol_offset + k + 1)];
|
||||
|
||||
for (pilot_cnt = 0; pilot_cnt < 3*nb_rb_coreset; pilot_cnt++) {
|
||||
if (k >= ue->frame_parms.ofdm_symbol_size) {
|
||||
k -= ue->frame_parms.ofdm_symbol_size;
|
||||
@@ -1220,11 +1268,15 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
#ifdef DEBUG_PDCCH
|
||||
printf("pilot[%u] = (%d, %d)\trxF[%d] = (%d, %d)\n", pilot_cnt, pil[0], pil[1], k+1, rxF[0], rxF[1]);
|
||||
#endif
|
||||
rsrp_sum += (((int32_t)(rx_signal.r) * rx_signal.r) + ((int32_t)(rx_signal.i) * rx_signal.i));
|
||||
LOG_D(NR_PHY, "r: %d, i: %d, k %d, offset %d\n", rx_signal.r, rx_signal.i, k, (symbol_offset + k + 1));
|
||||
meas_count++;
|
||||
ch_sum[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch_sum[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
pil += 2;
|
||||
rxF += 8;
|
||||
k += 4;
|
||||
rx_signal = rxdataF[aarx][(symbol_offset + k + 1)];
|
||||
|
||||
if (pilot_cnt % 3 == 2) {
|
||||
ch[0] = ch_sum[0] / 3;
|
||||
@@ -1245,6 +1297,11 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
rsrp = rsrp_sum / meas_count;
|
||||
*rsrp_dBm = dB_fixed(rsrp) + 30 - pow_2_30_dB
|
||||
- ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size);
|
||||
LOG_D(NR_PHY, "%4d.%2d rsrp %d, rsrp_dBm %d, rsrp_sum %d, meas_count %d\n", proc->frame_rx, proc->nr_slot_rx, rsrp, *rsrp_dBm, rsrp_sum, meas_count);
|
||||
}
|
||||
|
||||
void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms,
|
||||
|
||||
@@ -52,13 +52,15 @@ void peak_estimator(int32_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t
|
||||
*/
|
||||
void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int pscch_flag,
|
||||
unsigned char symbol,
|
||||
fapi_nr_coreset_t *coreset,
|
||||
uint16_t first_carrier_offset,
|
||||
uint16_t BWPStart,
|
||||
int32_t pdcch_est_size,
|
||||
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
|
||||
int16_t* rsrp_dBm);
|
||||
|
||||
int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
@@ -68,15 +70,18 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
NR_DL_FRAME_PARMS *fp,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
struct complex16 dl_ch_estimates_time[][ue->frame_parms.ofdm_symbol_size],
|
||||
struct complex16 dl_ch_estimates_time[][fp->ofdm_symbol_size],
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
unsigned char symbol,
|
||||
int dmrss,
|
||||
uint8_t ssb_index,
|
||||
uint8_t n_hf,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
c16_t rxdataF[][fp->samples_per_slot_wCP],
|
||||
bool sidelink,
|
||||
uint16_t Nid);
|
||||
|
||||
int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
@@ -141,4 +146,9 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
|
||||
|
||||
float_t get_nr_RSRP(module_id_t Mod_id,uint8_t CC_id,uint8_t gNB_index);
|
||||
|
||||
|
||||
void nr_sl_psbch_rsrp_measurements(sl_nr_ue_phy_params_t *sl_phy_params,
|
||||
NR_DL_FRAME_PARMS *fp,
|
||||
c16_t rxdataF[][fp->samples_per_slot_wCP],
|
||||
bool use_SSS);
|
||||
#endif
|
||||
|
||||
@@ -313,3 +313,56 @@ void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue,
|
||||
ue->measurements.n0_power_tot_dB + 30 - 10*log10(pow(2, 30)) - dB_fixed(ue->frame_parms.ofdm_symbol_size) - ((int)rx_gain - (int)rx_gain_offset));
|
||||
|
||||
}
|
||||
|
||||
//PSBCH RSRP calculations according to 38.215 section 5.1.22
|
||||
void nr_sl_psbch_rsrp_measurements(sl_nr_ue_phy_params_t *sl_phy_params,
|
||||
NR_DL_FRAME_PARMS *fp,
|
||||
c16_t rxdataF[][fp->samples_per_slot_wCP],
|
||||
bool use_SSS)
|
||||
{
|
||||
|
||||
SL_NR_UE_PSBCH_t *psbch_rx = &sl_phy_params->psbch;
|
||||
uint8_t numsym = (fp->Ncp) ? SL_NR_NUM_SYMBOLS_SSB_EXT_CP
|
||||
: SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP;
|
||||
uint32_t re_offset = fp->first_carrier_offset + fp->ssb_start_subcarrier;
|
||||
uint32_t rsrp = 0, num_re = 0;
|
||||
|
||||
LOG_D(PHY, "PSBCH RSRP MEAS: numsym:%d, re_offset:%d\n",numsym, re_offset);
|
||||
|
||||
for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++) {
|
||||
|
||||
//Calculate PSBCH RSRP based from DMRS REs
|
||||
for (uint8_t symbol=0; symbol<numsym;) {
|
||||
|
||||
struct complex16 *rxF = &rxdataF[aarx][symbol*fp->ofdm_symbol_size];
|
||||
|
||||
for (int re=0;re<SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL;re++) {
|
||||
|
||||
if (re%4 == 0) { //DMRS RE
|
||||
uint16_t offset = (re_offset + re) % fp->ofdm_symbol_size;
|
||||
|
||||
rsrp += rxF[offset].r*rxF[offset].r + rxF[offset].i*rxF[offset].i;
|
||||
num_re++;
|
||||
}
|
||||
}
|
||||
symbol = (symbol == 0) ? 5 : symbol+1;
|
||||
}
|
||||
}
|
||||
|
||||
if (use_SSS) {
|
||||
//TBD...
|
||||
//UE can decide between using only PSBCH DMRS or PSBCH DMRS and SSS for PSBCH RSRP computation.
|
||||
//If needed this can be implemented. Reference Spec 38.215
|
||||
}
|
||||
|
||||
psbch_rx->rsrp_dB_per_RE = 10*log10(rsrp / num_re);
|
||||
psbch_rx->rsrp_dBm_per_RE = psbch_rx->rsrp_dB_per_RE +
|
||||
30 - 10*log10(pow(2,30)) -
|
||||
((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) -
|
||||
dB_fixed(fp->ofdm_symbol_size);
|
||||
|
||||
|
||||
LOG_D(PHY, "PSBCH RSRP (DMRS REs): numREs:%d RSRP :%d dB/RE ,RSRP:%d dBm/RE\n",
|
||||
num_re, psbch_rx->rsrp_dB_per_RE, psbch_rx->rsrp_dBm_per_RE);
|
||||
|
||||
}
|
||||
@@ -39,14 +39,15 @@
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/NR_UE_ESTIMATION/filt16a_32.h"
|
||||
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
|
||||
// 10*log10(pow(2,30))
|
||||
#define pow_2_30_dB 90
|
||||
|
||||
// Additional memory allocation, because of applying the filter and the memory offset to ensure memory alignment
|
||||
#define FILTER_MARGIN 32
|
||||
|
||||
//#define NR_CSIRS_DEBUG
|
||||
// #define DEBUG_CSI_PRINTS // To enable CSI SNR debug logs
|
||||
extern short nr_qpsk_mod_table[8];
|
||||
// #define NR_CSIRS_DEBUG
|
||||
#define METRICS
|
||||
//#define NR_CSIIM_DEBUG
|
||||
|
||||
void nr_det_A_MF_2x2(int32_t *a_mf_00,
|
||||
@@ -205,7 +206,7 @@ int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue,
|
||||
for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) {
|
||||
|
||||
// for freq density 0.5 checks if even or odd RB
|
||||
if(csirs_config_pdu->freq_density <= 1 && csirs_config_pdu->freq_density != (rb % 2)) {
|
||||
if(csirs_config_pdu->freq_density <= 1 && get_softmodem_params()->sl_mode ? 0 : csirs_config_pdu->freq_density != (rb % 2)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -230,12 +231,12 @@ int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue,
|
||||
((int32_t)(rx_csi_rs_signal[k].i)*rx_csi_rs_signal[k].i));
|
||||
|
||||
meas_count++;
|
||||
|
||||
LOG_D(NR_PHY, "RX CSI-RS symbol_offset %li k %i symbol_offset+k=%li\n", symbol_offset, k, symbol_offset+k);
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
int dataF_offset = proc->nr_slot_rx*ue->frame_parms.samples_per_slot_wCP;
|
||||
int dataF_offset = get_softmodem_params()->sl_mode == 2 ? 0 : proc->nr_slot_rx * ue->frame_parms.samples_per_slot_wCP;
|
||||
uint16_t port_tx = s+j_cdm[cdm_id]*CDM_group_size;
|
||||
c16_t *tx_csi_rs_signal = (c16_t*)&nr_csi_info->csi_rs_generated_signal[port_tx][symbol_offset+dataF_offset];
|
||||
LOG_I(NR_PHY, "l,k (%2d,%4d) |\tport_tx %d (%4d,%4d)\tant_rx %d (%4d,%4d)\n",
|
||||
LOG_D(NR_PHY, "l,k (%2d,%4d) |\tport_tx %d (%4d,%4d)\tant_rx %d (%4d,%4d)\n",
|
||||
symb,
|
||||
k,
|
||||
port_tx+3000,
|
||||
@@ -257,7 +258,7 @@ int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue,
|
||||
*rsrp_dBm = dB_fixed(*rsrp) + 30 - pow_2_30_dB
|
||||
- ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size);
|
||||
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
#ifdef METRICS
|
||||
LOG_I(NR_PHY, "RSRP = %i (%i dBm)\n", *rsrp, *rsrp_dBm);
|
||||
#endif
|
||||
|
||||
@@ -270,7 +271,7 @@ uint32_t calc_power_csirs(const uint16_t *x, const fapi_nr_dl_config_csirs_pdu_r
|
||||
uint64_t sum_x2 = 0;
|
||||
uint16_t size = 0;
|
||||
for (int rb = 0; rb < csirs_config_pdu->nr_of_rbs; rb++) {
|
||||
if (csirs_config_pdu->freq_density <= 1 && csirs_config_pdu->freq_density != ((rb + csirs_config_pdu->start_rb) % 2)) {
|
||||
if (csirs_config_pdu->freq_density <= 1 && get_softmodem_params()->sl_mode ? 0 : csirs_config_pdu->freq_density != ((rb + csirs_config_pdu->start_rb) % 2)) {
|
||||
continue;
|
||||
}
|
||||
sum_x = sum_x + x[rb];
|
||||
@@ -300,9 +301,8 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
int16_t *log2_re,
|
||||
int16_t *log2_maxh,
|
||||
uint32_t *noise_power) {
|
||||
|
||||
const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
const int dataF_offset = proc->nr_slot_rx*ue->frame_parms.samples_per_slot_wCP;
|
||||
const int dataF_offset = get_softmodem_params()->sl_mode == 2 ? 0 : proc->nr_slot_rx * ue->frame_parms.samples_per_slot_wCP;
|
||||
*noise_power = 0;
|
||||
int maxh = 0;
|
||||
int count = 0;
|
||||
@@ -318,7 +318,7 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) {
|
||||
|
||||
// for freq density 0.5 checks if even or odd RB
|
||||
if(csirs_config_pdu->freq_density <= 1 && csirs_config_pdu->freq_density != (rb % 2)) {
|
||||
if(csirs_config_pdu->freq_density <= 1 && get_softmodem_params()->sl_mode ? 0 : csirs_config_pdu->freq_density != (rb % 2)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -360,19 +360,19 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
continue;
|
||||
}
|
||||
for(int k = 0; k<frame_parms->ofdm_symbol_size; k++) {
|
||||
LOG_I(NR_PHY, "l,k (%2d,%4d) | ", symb, k);
|
||||
LOG_D(NR_PHY, "l,k (%2d,%4d) | ", symb, k);
|
||||
for(uint16_t port_tx = 0; port_tx<N_ports; port_tx++) {
|
||||
uint64_t symbol_offset = symb*frame_parms->ofdm_symbol_size;
|
||||
c16_t *tx_csi_rs_signal = (c16_t*)&csi_rs_generated_signal[port_tx][symbol_offset+dataF_offset];
|
||||
c16_t *rx_csi_rs_signal = (c16_t*)&csi_rs_received_signal[ant_rx][symbol_offset];
|
||||
c16_t *csi_rs_ls_estimated_channel16 = (c16_t*)&csi_rs_ls_estimated_channel[ant_rx][port_tx][0];
|
||||
printf("port_tx %d --> ant_rx %d, tx (%4d,%4d), rx (%4d,%4d), ls (%4d,%4d) | ",
|
||||
port_tx+3000, ant_rx,
|
||||
tx_csi_rs_signal[k].r, tx_csi_rs_signal[k].i,
|
||||
rx_csi_rs_signal[k].r, rx_csi_rs_signal[k].i,
|
||||
csi_rs_ls_estimated_channel16[k].r, csi_rs_ls_estimated_channel16[k].i);
|
||||
// printf("port_tx %d --> ant_rx %d, tx (%4d,%4d), rx (%4d,%4d), ls (%4d,%4d) | ",
|
||||
// port_tx+3000, ant_rx,
|
||||
// tx_csi_rs_signal[k].r, tx_csi_rs_signal[k].i,
|
||||
// rx_csi_rs_signal[k].r, rx_csi_rs_signal[k].i,
|
||||
// csi_rs_ls_estimated_channel16[k].r, csi_rs_ls_estimated_channel16[k].i);
|
||||
}
|
||||
printf("\n");
|
||||
// printf("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -386,7 +386,7 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) {
|
||||
|
||||
// for freq density 0.5 checks if even or odd RB
|
||||
if(csirs_config_pdu->freq_density <= 1 && csirs_config_pdu->freq_density != (rb % 2)) {
|
||||
if(csirs_config_pdu->freq_density <= 1 && get_softmodem_params()->sl_mode ? 0 : csirs_config_pdu->freq_density != (rb % 2)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -412,7 +412,7 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
uint16_t noise_real[frame_parms->nb_antennas_rx][N_ports][csirs_config_pdu->nr_of_rbs];
|
||||
uint16_t noise_imag[frame_parms->nb_antennas_rx][N_ports][csirs_config_pdu->nr_of_rbs];
|
||||
for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) {
|
||||
if (csirs_config_pdu->freq_density <= 1 && csirs_config_pdu->freq_density != (rb % 2)) {
|
||||
if (csirs_config_pdu->freq_density <= 1 && get_softmodem_params()->sl_mode ? 0 : csirs_config_pdu->freq_density != (rb % 2)) {
|
||||
continue;
|
||||
}
|
||||
uint16_t k = (frame_parms->first_carrier_offset + rb*NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size;
|
||||
@@ -425,8 +425,9 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
maxh = cmax3(maxh, abs(csi_rs_estimated_channel16->r), abs(csi_rs_estimated_channel16->i));
|
||||
}
|
||||
}
|
||||
|
||||
for(uint16_t port_tx = 0; port_tx<N_ports; port_tx++) {
|
||||
*noise_power += (calc_power_csirs(noise_real[ant_rx][port_tx], csirs_config_pdu) + calc_power_csirs(noise_imag[ant_rx][port_tx],csirs_config_pdu));
|
||||
*noise_power += (calc_power_csirs(noise_real[ant_rx][port_tx], csirs_config_pdu) + calc_power_csirs(noise_imag[ant_rx][port_tx], csirs_config_pdu));
|
||||
}
|
||||
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
@@ -434,18 +435,18 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
int rb = k >= frame_parms->first_carrier_offset ?
|
||||
(k - frame_parms->first_carrier_offset)/NR_NB_SC_PER_RB :
|
||||
(k + frame_parms->ofdm_symbol_size - frame_parms->first_carrier_offset)/NR_NB_SC_PER_RB;
|
||||
LOG_I(NR_PHY, "(k = %4d) |\t", k);
|
||||
LOG_D(NR_PHY, "(k = %4d) |\t", k);
|
||||
for(uint16_t port_tx = 0; port_tx<N_ports; port_tx++) {
|
||||
c16_t *csi_rs_ls_estimated_channel16 = (c16_t*)&csi_rs_ls_estimated_channel[ant_rx][port_tx][0];
|
||||
c16_t *csi_rs_estimated_channel16 = (c16_t *)&csi_rs_estimated_channel_freq[ant_rx][port_tx][mem_offset];
|
||||
printf("Channel port_tx %d --> ant_rx %d : ls (%4d,%4d), int (%4d,%4d), noise (%4d,%4d) | ",
|
||||
port_tx+3000, ant_rx,
|
||||
csi_rs_ls_estimated_channel16[k].r, csi_rs_ls_estimated_channel16[k].i,
|
||||
csi_rs_estimated_channel16[k].r, csi_rs_estimated_channel16[k].i,
|
||||
rb >= csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs ? 0 : noise_real[ant_rx][port_tx][rb-csirs_config_pdu->start_rb],
|
||||
rb >= csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs ? 0 : noise_imag[ant_rx][port_tx][rb-csirs_config_pdu->start_rb]);
|
||||
// printf("Channel port_tx %d --> ant_rx %d : ls (%4d,%4d), int (%4d,%4d), noise (%4d,%4d) | ",
|
||||
// port_tx+3000, ant_rx,
|
||||
// csi_rs_ls_estimated_channel16[k].r, csi_rs_ls_estimated_channel16[k].i,
|
||||
// csi_rs_estimated_channel16[k].r, csi_rs_estimated_channel16[k].i,
|
||||
// rb >= csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs ? 0 : noise_real[ant_rx][port_tx][rb-csirs_config_pdu->start_rb],
|
||||
// rb >= csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs ? 0 : noise_imag[ant_rx][port_tx][rb-csirs_config_pdu->start_rb]);
|
||||
}
|
||||
printf("\n");
|
||||
// printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -634,7 +635,7 @@ int nr_csi_rs_pmi_estimation(const PHY_VARS_NR_UE *ue,
|
||||
|
||||
for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) {
|
||||
|
||||
if (csirs_config_pdu->freq_density <= 1 && csirs_config_pdu->freq_density != (rb % 2)) {
|
||||
if (csirs_config_pdu->freq_density <= 1 && get_softmodem_params()->sl_mode ? 0 : csirs_config_pdu->freq_density != (rb % 2)) {
|
||||
continue;
|
||||
}
|
||||
uint16_t k = (frame_parms->first_carrier_offset + rb * NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size;
|
||||
@@ -697,6 +698,53 @@ int nr_csi_rs_pmi_estimation(const PHY_VARS_NR_UE *ue,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nr_csi_rs_sinr_estimation(const PHY_VARS_NR_UE *ue,
|
||||
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
|
||||
const uint8_t N_ports,
|
||||
uint8_t mem_offset,
|
||||
const int32_t csi_rs_estimated_channel_freq[][N_ports][ue->frame_parms.ofdm_symbol_size + FILTER_MARGIN],
|
||||
const uint32_t interference_plus_noise_power,
|
||||
const int16_t log2_re,
|
||||
int32_t *precoded_sinr_dB) {
|
||||
|
||||
const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
|
||||
if (interference_plus_noise_power == 0) {
|
||||
*precoded_sinr_dB = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t sum_re = 0;
|
||||
int32_t sum_im = 0;
|
||||
int32_t sum2_re = 0;
|
||||
int32_t sum2_im = 0;
|
||||
int32_t tested_precoded_sinr = 0;
|
||||
|
||||
for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) {
|
||||
|
||||
if (csirs_config_pdu->freq_density <= 1 && get_softmodem_params()->sl_mode ? 0 : csirs_config_pdu->freq_density != (rb % 2)) {
|
||||
continue;
|
||||
}
|
||||
uint16_t k = (frame_parms->first_carrier_offset + rb * NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size;
|
||||
uint16_t k_offset = k + mem_offset;
|
||||
for (int ant_rx = 0; ant_rx < frame_parms->nb_antennas_rx; ant_rx++) {
|
||||
c16_t *csi_rs_estimated_channel_p = (c16_t *) &csi_rs_estimated_channel_freq[ant_rx][0][k_offset];
|
||||
|
||||
sum_re += csi_rs_estimated_channel_p->r;
|
||||
sum_im += csi_rs_estimated_channel_p->i;
|
||||
sum2_re += (csi_rs_estimated_channel_p->r * csi_rs_estimated_channel_p->r) >> log2_re;
|
||||
sum2_im += (csi_rs_estimated_channel_p->i * csi_rs_estimated_channel_p->i) >> log2_re;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t power_re = sum2_re - (sum_re >> log2_re) * (sum_re >> log2_re);
|
||||
int32_t power_im = sum2_im - (sum_im >> log2_re) * (sum_im >> log2_re);
|
||||
tested_precoded_sinr = (power_re + power_im) / (int32_t)interference_plus_noise_power;
|
||||
*precoded_sinr_dB = dB_fixed(tested_precoded_sinr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nr_csi_rs_cqi_estimation(const uint32_t precoded_sinr,
|
||||
uint8_t *cqi) {
|
||||
|
||||
@@ -809,6 +857,46 @@ int nr_csi_im_power_estimation(const PHY_VARS_NR_UE *ue,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nr_csi_rs_cqi_estimation_sl(const int32_t precoded_sinr,
|
||||
uint8_t *cqi) {
|
||||
|
||||
*cqi = 0;
|
||||
if (precoded_sinr >= -20 && precoded_sinr < -6) {
|
||||
*cqi = 1;
|
||||
} else if(precoded_sinr >= -6 && precoded_sinr < -3) {
|
||||
*cqi = 2;
|
||||
} else if(precoded_sinr >= -3 && precoded_sinr <= 0) {
|
||||
*cqi = 3;
|
||||
// Default SINR table for an AWGN channel for SISO scenario, considering 0.1 BLER condition and TS 38.214 Table 5.2.2.1-2
|
||||
} else if(precoded_sinr > 0 && precoded_sinr <= 2) {
|
||||
*cqi = 4;
|
||||
} else if(precoded_sinr == 3) {
|
||||
*cqi = 5;
|
||||
} else if(precoded_sinr > 3 && precoded_sinr <= 5) {
|
||||
*cqi = 6;
|
||||
} else if(precoded_sinr > 5 && precoded_sinr <= 7) {
|
||||
*cqi = 7;
|
||||
} else if(precoded_sinr > 7 && precoded_sinr <= 9) {
|
||||
*cqi = 8;
|
||||
} else if(precoded_sinr == 10) {
|
||||
*cqi = 9;
|
||||
} else if(precoded_sinr > 10 && precoded_sinr <= 12) {
|
||||
*cqi = 10;
|
||||
} else if(precoded_sinr > 12 && precoded_sinr <= 15) {
|
||||
*cqi = 11;
|
||||
} else if(precoded_sinr == 16) {
|
||||
*cqi = 12;
|
||||
} else if(precoded_sinr > 16 && precoded_sinr <= 18) {
|
||||
*cqi = 13;
|
||||
} else if(precoded_sinr == 19) {
|
||||
*cqi = 14;
|
||||
} else if(precoded_sinr > 19) {
|
||||
*cqi = 15;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
|
||||
|
||||
int gNB_id = proc->gNB_id;
|
||||
@@ -836,13 +924,13 @@ int nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t r
|
||||
|
||||
void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
|
||||
{
|
||||
|
||||
int gNB_id = proc->gNB_id;
|
||||
if(!ue->csirs_vars[gNB_id]->active) {
|
||||
// TODO: check the id whether it is working for multiple UEs
|
||||
int id = get_softmodem_params()->sl_mode == 2 ? 0 : proc->gNB_id;
|
||||
if (!ue->csirs_vars[id]->active) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu = (fapi_nr_dl_config_csirs_pdu_rel15_t*)&ue->csirs_vars[gNB_id]->csirs_config_pdu;
|
||||
fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu = (fapi_nr_dl_config_csirs_pdu_rel15_t*)&ue->csirs_vars[id]->csirs_config_pdu;
|
||||
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
LOG_I(NR_PHY, "csirs_config_pdu->subcarrier_spacing = %i\n", csirs_config_pdu->subcarrier_spacing);
|
||||
@@ -883,13 +971,20 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t
|
||||
uint32_t noise_power = 0;
|
||||
uint8_t rank_indicator = 0;
|
||||
uint32_t precoded_sinr_dB = 0;
|
||||
int32_t sl_sinr_dB = 0;
|
||||
uint8_t cqi = 0;
|
||||
uint8_t i1[3];
|
||||
uint8_t i2[1];
|
||||
|
||||
uint8_t num_of_layers = min(get_nrUE_params()->nb_antennas_tx, get_nrUE_params()->nb_antennas_rx);
|
||||
AssertFatal(num_of_layers > 0, "Number of layers MUST be greater than zero!!!");
|
||||
uint16_t beta_csirs = get_softmodem_params()->sl_mode ? (uint16_t)(AMP * (ceil(sqrt(num_of_layers / frame_parms->nb_antennas_tx)))) & 0xFFFF : AMP;
|
||||
csirs_config_pdu->scramb_id = ue->slsch[0].harq_process->pssch_pdu->Nid % (1 << 10);
|
||||
LOG_D(NR_PHY, "Rx beta_csirs: %d, scramb_id %i, frame.slot (%d.%d)\n", beta_csirs, csirs_config_pdu->scramb_id, proc->frame_rx, proc->nr_slot_rx);
|
||||
|
||||
nr_generate_csi_rs(frame_parms,
|
||||
ue->nr_csi_info->csi_rs_generated_signal,
|
||||
AMP,
|
||||
beta_csirs,
|
||||
ue->nr_csi_info,
|
||||
(nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *) csirs_config_pdu,
|
||||
proc->nr_slot_rx,
|
||||
@@ -964,22 +1059,43 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t
|
||||
|
||||
// bit 3 in bitmap to indicate RI measurment
|
||||
if (csirs_config_pdu->measurement_bitmap & 8) {
|
||||
nr_csi_rs_pmi_estimation(ue,
|
||||
csirs_config_pdu,
|
||||
ue->nr_csi_info,
|
||||
N_ports,
|
||||
mem_offset,
|
||||
csi_rs_estimated_channel_freq,
|
||||
ue->nr_csi_info->csi_im_meas_computed ? ue->nr_csi_info->interference_plus_noise_power : noise_power,
|
||||
rank_indicator,
|
||||
log2_re,
|
||||
i1,
|
||||
i2,
|
||||
&precoded_sinr_dB);
|
||||
// Sidelink mode 2 considers only one port (for now), in case of N_ports = 2, we need to revisit
|
||||
if (N_ports >= 2)
|
||||
nr_csi_rs_pmi_estimation(ue,
|
||||
csirs_config_pdu,
|
||||
ue->nr_csi_info,
|
||||
N_ports,
|
||||
mem_offset,
|
||||
csi_rs_estimated_channel_freq,
|
||||
ue->nr_csi_info->csi_im_meas_computed ? ue->nr_csi_info->interference_plus_noise_power : noise_power,
|
||||
rank_indicator,
|
||||
log2_re,
|
||||
i1,
|
||||
i2,
|
||||
&precoded_sinr_dB);
|
||||
else
|
||||
nr_csi_rs_sinr_estimation(ue,
|
||||
csirs_config_pdu,
|
||||
N_ports,
|
||||
mem_offset,
|
||||
csi_rs_estimated_channel_freq,
|
||||
noise_power,
|
||||
log2_re,
|
||||
&sl_sinr_dB);
|
||||
|
||||
// bit 4 in bitmap to indicate RI measurment
|
||||
if(csirs_config_pdu->measurement_bitmap & 16)
|
||||
nr_csi_rs_cqi_estimation(precoded_sinr_dB, &cqi);
|
||||
if (csirs_config_pdu->measurement_bitmap & 16) {
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
nr_csi_rs_cqi_estimation_sl(sl_sinr_dB, &cqi);
|
||||
get_nrUE_params()->snr = sl_sinr_dB;
|
||||
LOG_I(NR_PHY, "Rx CSI-RS %4d.%2d sl_sinr %i rsrp %d dBm cqi %d\n",
|
||||
proc->frame_rx, proc->nr_slot_rx, sl_sinr_dB, rsrp_dBm, cqi);
|
||||
} else {
|
||||
nr_csi_rs_cqi_estimation(precoded_sinr_dB, &cqi);
|
||||
LOG_I(NR_PHY, "Rx %4d.%2d snr %u rsrp %d dBm cqi %d\n",
|
||||
proc->frame_rx, proc->nr_slot_rx, precoded_sinr_dB, rsrp_dBm, cqi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (csirs_config_pdu->measurement_bitmap) {
|
||||
@@ -991,7 +1107,7 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t
|
||||
rank_indicator + 1, i1[0], i1[1], i1[2], i2[0], precoded_sinr_dB, cqi);
|
||||
break;
|
||||
case 27 :
|
||||
LOG_I(NR_PHY, "RSRP = %i dBm, RI = %i i1 = %i.%i.%i, i2 = %i, SINR = %i dB, CQI = %i\n",
|
||||
LOG_D(NR_PHY, "RSRP = %i dBm, RI = %i i1 = %i.%i.%i, i2 = %i, SINR = %i dB, CQI = %i\n",
|
||||
rsrp_dBm, rank_indicator + 1, i1[0], i1[1], i1[2], i2[0], precoded_sinr_dB, cqi);
|
||||
break;
|
||||
default :
|
||||
|
||||
@@ -79,7 +79,8 @@ char nr_dci_format_string[8][30] = {
|
||||
//static const int16_t conjugate[8]__attribute__((aligned(32))) = {-1,1,-1,1,-1,1,-1,1};
|
||||
|
||||
|
||||
static void nr_pdcch_demapping_deinterleaving(uint32_t *llr,
|
||||
static void nr_pdcch_demapping_deinterleaving(int pscch_flag,
|
||||
uint32_t *llr,
|
||||
uint32_t *e_rx,
|
||||
uint8_t coreset_time_dur,
|
||||
uint8_t start_symbol,
|
||||
@@ -146,7 +147,7 @@ static void nr_pdcch_demapping_deinterleaving(uint32_t *llr,
|
||||
int max_bundles = n_cce * num_bundles_per_cce;
|
||||
int f_bundle_j_list[max_bundles];
|
||||
// for each bundle
|
||||
for (int nb = 0; nb < max_bundles; nb++) {
|
||||
for (int nb = 0; nb < max_bundles && pscch_flag==0; nb++) {
|
||||
if (coreset_interleaved == 0)
|
||||
f_bundle_j = nb;
|
||||
else {
|
||||
@@ -162,7 +163,7 @@ static void nr_pdcch_demapping_deinterleaving(uint32_t *llr,
|
||||
|
||||
// Get cce_list indices by bundle index in ascending order
|
||||
int f_bundle_j_list_ord[number_of_candidates][max_bundles];
|
||||
for (int c_id = 0; c_id < number_of_candidates; c_id++ ) {
|
||||
for (int c_id = 0; c_id < number_of_candidates && pscch_flag==0; c_id++ ) {
|
||||
int start_bund_cand = CCE[c_id] * num_bundles_per_cce;
|
||||
int max_bund_per_cand = L[c_id] * num_bundles_per_cce;
|
||||
int f_bundle_j_list_id = 0;
|
||||
@@ -181,23 +182,28 @@ static void nr_pdcch_demapping_deinterleaving(uint32_t *llr,
|
||||
int data_sc = 9; // 9 sub-carriers with data per PRB
|
||||
for (int c_id = 0; c_id < number_of_candidates; c_id++ ) {
|
||||
for (int symbol_idx = start_symbol; symbol_idx < start_symbol+coreset_time_dur; symbol_idx++) {
|
||||
for (int cce_count = 0; cce_count < L[c_id]; cce_count ++) {
|
||||
for (int k=0; k<NR_NB_REG_PER_CCE/reg_bundle_size_L; k++) { // loop over REG bundles
|
||||
int f = f_bundle_j_list_ord[c_id][k+NR_NB_REG_PER_CCE*cce_count/reg_bundle_size_L];
|
||||
for(int rb=0; rb<B_rb; rb++) { // loop over the RBs of the bundle
|
||||
index_z = data_sc * rb_count;
|
||||
index_llr = (uint16_t) (f*B_rb + rb + symbol_idx * coreset_nbr_rb) * data_sc;
|
||||
for (int i = 0; i < data_sc; i++) {
|
||||
e_rx[index_z + i] = llr[index_llr + i];
|
||||
if (pscch_flag == 0) {
|
||||
for (int cce_count = 0; cce_count < L[c_id]; cce_count ++) {
|
||||
for (int k=0; k<NR_NB_REG_PER_CCE/reg_bundle_size_L; k++) { // loop over REG bundles
|
||||
int f = f_bundle_j_list_ord[c_id][k+NR_NB_REG_PER_CCE*cce_count/reg_bundle_size_L];
|
||||
for(int rb=0; rb<B_rb; rb++) { // loop over the RBs of the bundle
|
||||
index_z = data_sc * rb_count;
|
||||
index_llr = (uint16_t) (f*B_rb + rb + symbol_idx * coreset_nbr_rb) * data_sc;
|
||||
for (int i = 0; i < data_sc; i++) {
|
||||
e_rx[index_z + i] = llr[index_llr + i];
|
||||
#ifdef NR_PDCCH_DCI_DEBUG
|
||||
LOG_I(PHY,"[candidate=%d,symbol_idx=%d,cce=%d,REG bundle=%d,PRB=%d] z[%d]=(%d,%d) <-> \t llr[%d]=(%d,%d) \n",
|
||||
c_id,symbol_idx,cce_count,k,f*B_rb + rb,(index_z + i),*(int16_t *) &e_rx[index_z + i],*(1 + (int16_t *) &e_rx[index_z + i]),
|
||||
(index_llr + i),*(int16_t *) &llr[index_llr + i], *(1 + (int16_t *) &llr[index_llr + i]));
|
||||
LOG_I(PHY,"[candidate=%d,symbol_idx=%d,cce=%d,REG bundle=%d,PRB=%d] z[%d]=(%d,%d) <-> \t llr[%d]=(%d,%d) \n",
|
||||
c_id,symbol_idx,cce_count,k,f*B_rb + rb,(index_z + i),*(int16_t *) &e_rx[index_z + i],*(1 + (int16_t *) &e_rx[index_z + i]),
|
||||
(index_llr + i),*(int16_t *) &llr[index_llr + i], *(1 + (int16_t *) &llr[index_llr + i]));
|
||||
#endif
|
||||
}
|
||||
rb_count++;
|
||||
}
|
||||
rb_count++;
|
||||
}
|
||||
}
|
||||
} // pscch_flag == 0
|
||||
else { //this will need to be changed a bit when we scan for multiple SCI
|
||||
memcpy(e_rx,llr+(data_sc*coreset_nbr_rb),coreset_nbr_rb*coreset_time_dur*data_sc*sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -404,10 +410,11 @@ void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz,
|
||||
c_rb_by6 = c_rb/6;
|
||||
|
||||
// skip zeros in frequency domain bitmap
|
||||
while ((coreset_freq_dom[c_rb_by6>>3] & (1<<(7-(c_rb_by6&7)))) == 0) {
|
||||
c_rb+=6;
|
||||
c_rb_by6 = c_rb/6;
|
||||
}
|
||||
if (coreset_freq_dom)
|
||||
while ((coreset_freq_dom[c_rb_by6>>3] & (1<<(7-(c_rb_by6&7)))) == 0) {
|
||||
c_rb+=6;
|
||||
c_rb_by6 = c_rb/6;
|
||||
}
|
||||
|
||||
rxF=NULL;
|
||||
|
||||
@@ -665,6 +672,7 @@ void nr_pdcch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms,
|
||||
|
||||
int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int pscch_flag,
|
||||
int32_t pdcch_est_size,
|
||||
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
|
||||
int16_t *pdcch_e_rx,
|
||||
@@ -677,8 +685,11 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
|
||||
int32_t avgs;
|
||||
int32_t avgP[4];
|
||||
int n_rb,rb_offset;
|
||||
get_coreset_rballoc(rel15->coreset.frequency_domain_resource,&n_rb,&rb_offset);
|
||||
|
||||
if (pscch_flag == 0) get_coreset_rballoc(rel15->coreset.frequency_domain_resource,&n_rb,&rb_offset);
|
||||
else {
|
||||
rb_offset = rel15->coreset.frequency_domain_resource[0];
|
||||
n_rb = rel15->coreset.frequency_domain_resource[1];
|
||||
}
|
||||
// Pointers to extracted PDCCH symbols in frequency-domain.
|
||||
int32_t rx_size = ((4 * frame_parms->N_RB_DL * 12 + 31) >> 5) << 5;
|
||||
__attribute__ ((aligned(32))) int32_t rxdataF_ext[frame_parms->nb_antennas_rx][rx_size];
|
||||
@@ -693,10 +704,10 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
|
||||
|
||||
memset(llr, 0, sizeof(llr));
|
||||
|
||||
LOG_D(PHY,"pdcch coreset: freq %x, n_rb %d, rb_offset %d\n",
|
||||
LOG_D(NR_PHY,"pdcch coreset: freq %x, n_rb %d, rb_offset %d\n",
|
||||
rel15->coreset.frequency_domain_resource[0],n_rb,rb_offset);
|
||||
for (int s=rel15->coreset.StartSymbolIndex; s<(rel15->coreset.StartSymbolIndex+rel15->coreset.duration); s++) {
|
||||
LOG_D(PHY,"in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n");
|
||||
LOG_D(NR_PHY,"in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n");
|
||||
|
||||
nr_pdcch_extract_rbs_single(ue->frame_parms.samples_per_slot_wCP,
|
||||
rxdataF,
|
||||
@@ -707,10 +718,17 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
|
||||
pdcch_dl_ch_estimates_ext,
|
||||
s,
|
||||
frame_parms,
|
||||
rel15->coreset.frequency_domain_resource,
|
||||
pscch_flag ==0 ? rel15->coreset.frequency_domain_resource : NULL,
|
||||
n_rb,
|
||||
rel15->BWPStart);
|
||||
|
||||
/* if (pscch_flag == 1 && dB_fixed(signal_energy_nodc(&pdcch_dl_ch_estimates_ext[0][s*n_rb*NBR_RE_PER_RB_WITH_DMRS],n_rb*NBR_RE_PER_RB_WITH_DMRS)) > 40) {
|
||||
LOG_I(NR_PHY,"PSCCH: %d.%d rx level0_%d %d ch_level0_%d %d\n",proc->frame_rx,proc->nr_slot_rx, s, dB_fixed(signal_energy_nodc(&rxdataF_ext[0][s*n_rb*NBR_RE_PER_RB_WITH_DMRS],n_rb*NBR_RE_PER_RB_WITH_DMRS)),s,dB_fixed(signal_energy_nodc(&pdcch_dl_ch_estimates_ext[0][s*n_rb*NBR_RE_PER_RB_WITH_DMRS],n_rb*NBR_RE_PER_RB_WITH_DMRS)));
|
||||
LOG_M("sciF.m","scisF0",&rxdataF_ext[0][s*n_rb*NBR_RE_PER_RB_WITH_DMRS],n_rb*NBR_RE_PER_RB_WITH_DMRS,1,1);
|
||||
LOG_M("scicF.m","scicF0",&pdcch_dl_ch_estimates_ext[0][s*n_rb*NBR_RE_PER_RB_WITH_DMRS],n_rb*NBR_RE_PER_RB_WITH_DMRS,1,1);
|
||||
exit(-1);
|
||||
}
|
||||
*/
|
||||
LOG_D(PHY,"we enter nr_pdcch_channel_level(avgP=%d) => compute channel level based on ofdm symbol 0, pdcch_vars[eNB_id]->dl_ch_estimates_ext\n",*avgP);
|
||||
LOG_D(PHY,"in nr_pdcch_channel_level(dl_ch_estimates_ext -> dl_ch_estimates_ext)\n");
|
||||
// compute channel level based on ofdm symbol 0
|
||||
@@ -769,14 +787,12 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
|
||||
// T_INT(n_pdcch_symbols),
|
||||
// T_BUFFER(pdcch_vars[eNB_id]->rxdataF_comp, frame_parms->N_RB_DL*12*n_pdcch_symbols* 4));
|
||||
|
||||
#endif
|
||||
#ifdef DEBUG_DCI_DECODING
|
||||
printf("demapping: slot %u, mi %d\n",slot,get_mi(frame_parms,slot));
|
||||
#endif
|
||||
}
|
||||
|
||||
LOG_D(PHY,"we enter nr_pdcch_demapping_deinterleaving(), number of candidates %d\n",rel15->number_of_candidates);
|
||||
nr_pdcch_demapping_deinterleaving((uint32_t *) llr,
|
||||
nr_pdcch_demapping_deinterleaving(pscch_flag,
|
||||
(uint32_t *) llr,
|
||||
(uint32_t *) pdcch_e_rx,
|
||||
rel15->coreset.duration,
|
||||
rel15->coreset.StartSymbolIndex,
|
||||
@@ -800,7 +816,8 @@ void nr_pdcch_unscrambling(int16_t *e_rx,
|
||||
uint16_t scrambling_RNTI,
|
||||
uint32_t length,
|
||||
uint16_t pdcch_DMRS_scrambling_id,
|
||||
int16_t *z2) {
|
||||
int16_t *z2,
|
||||
int sci_flag) {
|
||||
int i;
|
||||
uint8_t reset;
|
||||
uint32_t x1 = 0, x2 = 0, s = 0;
|
||||
@@ -809,7 +826,7 @@ void nr_pdcch_unscrambling(int16_t *e_rx,
|
||||
reset = 1;
|
||||
// x1 is set in first call to lte_gold_generic
|
||||
n_id = pdcch_DMRS_scrambling_id;
|
||||
x2 = ((rnti<<16) + n_id); //mod 2^31 is implicit //this is c_init in 38.211 v15.1.0 Section 7.3.2.3
|
||||
x2 = sci_flag == 0 ? ((rnti<<16) + n_id) : ((n_id<<15) + 1010); //mod 2^31 is implicit //this is c_init in 38.211 v15.1.0 Section 7.3.2.3
|
||||
|
||||
LOG_D(PHY,"PDCCH Unscrambling x2 %x : scrambling_RNTI %x\n", x2, rnti);
|
||||
|
||||
@@ -840,7 +857,7 @@ static uint16_t nr_dci_false_detection(uint64_t *dci,
|
||||
) {
|
||||
|
||||
uint32_t encoder_output[NR_MAX_DCI_SIZE_DWORD];
|
||||
polar_encoder_fast(dci, (void*)encoder_output, rnti, 1,
|
||||
polar_encoder_fast(dci, (void*)encoder_output, NULL,rnti, 1,
|
||||
messageType, messageLength, aggregation_level);
|
||||
uint8_t *enout_p = (uint8_t*)encoder_output;
|
||||
uint16_t x = 0;
|
||||
@@ -860,15 +877,22 @@ static uint16_t nr_dci_false_detection(uint64_t *dci,
|
||||
|
||||
uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int pscch_flag,
|
||||
int16_t *pdcch_e_rx,
|
||||
fapi_nr_dci_indication_t *dci_ind,
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15) {
|
||||
void *ind,
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15,
|
||||
int16_t *rsrp_dBm) {
|
||||
|
||||
//int gNB_id = 0;
|
||||
int16_t tmp_e[16*108];
|
||||
rnti_t n_rnti;
|
||||
int e_rx_cand_idx = 0;
|
||||
|
||||
fapi_nr_dci_indication_t *dci_ind=NULL;
|
||||
sl_nr_sci_indication_t *sci_ind=NULL;
|
||||
if (pscch_flag == 0) dci_ind = (fapi_nr_dci_indication_t*)ind;
|
||||
else sci_ind = (sl_nr_sci_indication_t *)ind;
|
||||
|
||||
for (int j=0;j<rel15->number_of_candidates;j++) {
|
||||
int CCEind = rel15->CCE[j];
|
||||
int L = rel15->L[j];
|
||||
@@ -879,11 +903,13 @@ uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
|
||||
// skip this candidate if we've already found one with the
|
||||
// same rnti and format at a different aggregation level
|
||||
int dci_found=0;
|
||||
for (int ind=0;ind < dci_ind->number_of_dcis ; ind++) {
|
||||
if (rel15->rnti== dci_ind->dci_list[ind].rnti &&
|
||||
rel15->dci_format_options[k]==dci_ind->dci_list[ind].dci_format) {
|
||||
dci_found=1;
|
||||
break;
|
||||
if (dci_ind) {
|
||||
for (int ind=0;ind < dci_ind->number_of_dcis ; ind++) {
|
||||
if (rel15->rnti== dci_ind->dci_list[ind].rnti &&
|
||||
rel15->dci_format_options[k]==dci_ind->dci_list[ind].dci_format) {
|
||||
dci_found=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dci_found == 1)
|
||||
@@ -895,47 +921,72 @@ uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
|
||||
proc->frame_rx, proc->nr_slot_rx, j, rel15->number_of_candidates, CCEind, e_rx_cand_idx, L, dci_length, nr_dci_format_string[rel15->dci_format_options[k]]);
|
||||
|
||||
|
||||
nr_pdcch_unscrambling(&pdcch_e_rx[e_rx_cand_idx], rel15->coreset.scrambling_rnti, L*108, rel15->coreset.pdcch_dmrs_scrambling_id, tmp_e);
|
||||
nr_pdcch_unscrambling(&pdcch_e_rx[e_rx_cand_idx], rel15->coreset.scrambling_rnti, pscch_flag==0 ? L*108 : L*18, rel15->coreset.pdcch_dmrs_scrambling_id, tmp_e,0);
|
||||
|
||||
#ifdef DEBUG_DCI_DECODING
|
||||
uint32_t *z = (uint32_t *) &e_rx[e_rx_cand_idx];
|
||||
for (int index_z = 0; index_z < L*6; index_z++){
|
||||
uint32_t *z = (uint32_t *) &pdcch_e_rx[e_rx_cand_idx];
|
||||
for (int index_z = 0; index_z < (pscch_flag == 0 ? L*6 : L); index_z++){
|
||||
for (int i=0; i<9; i++) {
|
||||
LOG_I(PHY,"z[%d]=(%d,%d) \n", (9*index_z + i), *(int16_t *) &z[9*index_z + i],*(1 + (int16_t *) &z[9*index_z + i]));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
uint16_t Nid;
|
||||
uint16_t crc = polar_decoder_int16(tmp_e,
|
||||
dci_estimation,
|
||||
&Nid,
|
||||
1,
|
||||
NR_POLAR_DCI_MESSAGE_TYPE, dci_length, L);
|
||||
pscch_flag == 0 ? NR_POLAR_DCI_MESSAGE_TYPE : NR_POLAR_SCI_MESSAGE_TYPE, dci_length, L);
|
||||
|
||||
n_rnti = rel15->rnti;
|
||||
LOG_D(PHY, "(%i.%i) dci indication (rnti %x,dci format %s,n_CCE %d,payloadSize %d,payload %llx )\n",
|
||||
proc->frame_rx, proc->nr_slot_rx,n_rnti,nr_dci_format_string[rel15->dci_format_options[k]],CCEind,dci_length, *(unsigned long long*)dci_estimation);
|
||||
if (crc == 0) LOG_D(PHY, "(%i.%i) %s indication (rnti %x,format %s,n_CCE %d,payloadSize %d,payload %llx )\n",
|
||||
proc->frame_rx, proc->nr_slot_rx,pscch_flag==0?"dci":"sci",n_rnti,pscch_flag==0?nr_dci_format_string[rel15->dci_format_options[k]]:"1A",CCEind,dci_length, *(unsigned long long*)dci_estimation);
|
||||
if (crc == n_rnti) {
|
||||
LOG_D(PHY, "(%i.%i) Received dci indication (rnti %x,dci format %s,n_CCE %d,payloadSize %d,payload %llx)\n",
|
||||
proc->frame_rx, proc->nr_slot_rx,n_rnti,nr_dci_format_string[rel15->dci_format_options[k]],CCEind,dci_length,*(unsigned long long*)dci_estimation);
|
||||
uint16_t mb = nr_dci_false_detection(dci_estimation,tmp_e,L*108,n_rnti, NR_POLAR_DCI_MESSAGE_TYPE, dci_length, L);
|
||||
LOG_D(PHY, "(%i.%i) Received %s indication (rnti %x,dci format %s,n_CCE %d,payloadSize %d,payload %llx)\n",
|
||||
proc->frame_rx, proc->nr_slot_rx,pscch_flag==0?"dci":"sci",n_rnti,pscch_flag==0?nr_dci_format_string[rel15->dci_format_options[k]]:"1A",CCEind,dci_length,*(unsigned long long*)dci_estimation);
|
||||
uint16_t mb = nr_dci_false_detection(dci_estimation,
|
||||
tmp_e,
|
||||
pscch_flag == 0 ? L*108 : L*18,
|
||||
n_rnti,
|
||||
pscch_flag == 0 ? NR_POLAR_DCI_MESSAGE_TYPE : NR_POLAR_SCI_MESSAGE_TYPE,
|
||||
dci_length,
|
||||
L);
|
||||
ue->dci_thres = (ue->dci_thres + mb) / 2;
|
||||
if (mb > (ue->dci_thres+30)) {
|
||||
LOG_W(PHY,"DCI false positive. Dropping DCI index %d. Mismatched bits: %d/%d. Current DCI threshold: %d\n",j,mb,L*108,ue->dci_thres);
|
||||
LOG_W(PHY,"DCI false positive. Dropping DCI index %d. Mismatched bits: %d/%d. Current DCI threshold: %d\n",j,mb,pscch_flag==0?L*108:L*18,ue->dci_thres);
|
||||
continue;
|
||||
} else {
|
||||
dci_ind->SFN = proc->frame_rx;
|
||||
dci_ind->slot = proc->nr_slot_rx;
|
||||
dci_ind->dci_list[dci_ind->number_of_dcis].rnti = n_rnti;
|
||||
dci_ind->dci_list[dci_ind->number_of_dcis].n_CCE = CCEind;
|
||||
dci_ind->dci_list[dci_ind->number_of_dcis].N_CCE = L;
|
||||
dci_ind->dci_list[dci_ind->number_of_dcis].dci_format = rel15->dci_format_options[k];
|
||||
dci_ind->dci_list[dci_ind->number_of_dcis].ss_type = rel15->dci_type_options[k];
|
||||
dci_ind->dci_list[dci_ind->number_of_dcis].coreset_type = rel15->coreset.CoreSetType;
|
||||
int n_rb, rb_offset;
|
||||
get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &rb_offset);
|
||||
dci_ind->dci_list[dci_ind->number_of_dcis].cset_start = rel15->BWPStart + rb_offset;
|
||||
dci_ind->dci_list[dci_ind->number_of_dcis].payloadSize = dci_length;
|
||||
memcpy((void*)dci_ind->dci_list[dci_ind->number_of_dcis].payloadBits,(void*)dci_estimation,8);
|
||||
dci_ind->number_of_dcis++;
|
||||
if (pscch_flag == 0) {
|
||||
dci_ind->SFN = proc->frame_rx;
|
||||
dci_ind->slot = proc->nr_slot_rx;
|
||||
dci_ind->dci_list[dci_ind->number_of_dcis].rnti = n_rnti;
|
||||
dci_ind->dci_list[dci_ind->number_of_dcis].n_CCE = CCEind;
|
||||
dci_ind->dci_list[dci_ind->number_of_dcis].N_CCE = L;
|
||||
dci_ind->dci_list[dci_ind->number_of_dcis].dci_format = rel15->dci_format_options[k];
|
||||
dci_ind->dci_list[dci_ind->number_of_dcis].ss_type = rel15->dci_type_options[k];
|
||||
dci_ind->dci_list[dci_ind->number_of_dcis].coreset_type = rel15->coreset.CoreSetType;
|
||||
int n_rb, rb_offset;
|
||||
get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &rb_offset);
|
||||
dci_ind->dci_list[dci_ind->number_of_dcis].cset_start = rel15->BWPStart + rb_offset;
|
||||
dci_ind->dci_list[dci_ind->number_of_dcis].payloadSize = dci_length;
|
||||
memcpy((void*)dci_ind->dci_list[dci_ind->number_of_dcis].payloadBits,(void*)dci_estimation,8);
|
||||
dci_ind->number_of_dcis++;
|
||||
}
|
||||
else {
|
||||
sci_ind->sfn = proc->frame_rx;
|
||||
sci_ind->slot = proc->nr_slot_rx;
|
||||
sci_ind->sensing_result = 0;
|
||||
sci_ind->pssch_rsrp = 0; // measuring from pscch below; setting this flag to zero
|
||||
sci_ind->sci_pdu[sci_ind->number_of_SCIs].sci_format_type = SL_SCI_FORMAT_1A_ON_PSCCH;
|
||||
sci_ind->sci_pdu[sci_ind->number_of_SCIs].subch_index = 0;
|
||||
sci_ind->sci_pdu[sci_ind->number_of_SCIs].pscch_rsrp = *rsrp_dBm;
|
||||
sci_ind->sci_pdu[sci_ind->number_of_SCIs].sci_payloadlen = dci_length;
|
||||
sci_ind->sci_pdu[sci_ind->number_of_SCIs].Nid = Nid;
|
||||
|
||||
memcpy(sci_ind->sci_pdu[sci_ind->number_of_SCIs].sci_payloadBits,&dci_estimation,8);
|
||||
sci_ind->number_of_SCIs++;
|
||||
ue->SL_UE_PHY_PARAMS.pscch.rx_ok++;
|
||||
}
|
||||
break; // If DCI is found, no need to check for remaining DCI lengths
|
||||
}
|
||||
} else {
|
||||
@@ -944,7 +995,7 @@ uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
e_rx_cand_idx += 9*L*6*2; //e_rx index for next candidate (L CCEs, 6 REGs per CCE and 9 REs per REG and 2 uint16_t per RE)
|
||||
}
|
||||
return(dci_ind->number_of_dcis);
|
||||
return(dci_ind ? dci_ind->number_of_dcis : sci_ind->number_of_SCIs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -151,8 +151,8 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_time[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size];
|
||||
|
||||
for(int i=pbch_initial_symbol; i<pbch_initial_symbol+3;i++)
|
||||
nr_pbch_channel_estimation(ue,estimateSz, dl_ch_estimates, dl_ch_estimates_time,
|
||||
proc,i,i-pbch_initial_symbol,temp_ptr->i_ssb,temp_ptr->n_hf,rxdataF);
|
||||
nr_pbch_channel_estimation(ue,&ue->frame_parms, estimateSz, dl_ch_estimates, dl_ch_estimates_time,
|
||||
proc,i,i-pbch_initial_symbol,temp_ptr->i_ssb,temp_ptr->n_hf,rxdataF,false, frame_parms->Nid_cell);
|
||||
|
||||
stop_meas(&ue->dlsch_channel_estimation_stats);
|
||||
fapiPbch_t result = {0};
|
||||
@@ -330,7 +330,7 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc,
|
||||
|
||||
// compute the scramblingID_pdcch and the gold pdcch
|
||||
ue->scramblingID_pdcch = fp->Nid_cell;
|
||||
nr_gold_pdcch(ue,fp->Nid_cell);
|
||||
nr_gold_pdcch(&ue->frame_parms,ue->nr_gold_pdcch[0],fp->Nid_cell);
|
||||
|
||||
// compute the scrambling IDs for PDSCH DMRS
|
||||
for (int i=0; i<NR_NB_NSCID; i++) {
|
||||
|
||||
601
openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c
Normal file
601
openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c
Normal file
@@ -0,0 +1,601 @@
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/TOOLS/tools_defs.h"
|
||||
#include "PHY/NR_REFSIG/sss_nr.h"
|
||||
#include "PHY/NR_UE_ESTIMATION/nr_estimation.h"
|
||||
#include "PHY/MODULATION/modulation_UE.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "SCHED_NR_UE/defs.h"
|
||||
#include "common/utils/colors.h"
|
||||
|
||||
//#define SL_DEBUG
|
||||
|
||||
static const int16_t sl_phase_re_nr[PHASE_HYPOTHESIS_NUMBER]
|
||||
// -pi/3 ---- pi/3
|
||||
= {16384, 20173, 23571, 26509, 28932, 30791, 32051, 32687, 32687, 32051, 30791, 28932, 26509, 23571, 20173, 16384};
|
||||
|
||||
static const int16_t sl_phase_im_nr[PHASE_HYPOTHESIS_NUMBER] // -pi/3 ---- pi/3
|
||||
= {-28377, -25821, -22762, -19260, -15383, -11207, -6813, -2286, 2286, 6813, 11207, 15383, 19260, 22762, 25821, 28377};
|
||||
|
||||
|
||||
static int sl_nr_pss_correlation(PHY_VARS_NR_UE *UE, int frame_index)
|
||||
{
|
||||
|
||||
sl_nr_ue_phy_params_t *sl_ue = &UE->SL_UE_PHY_PARAMS;
|
||||
SL_NR_SYNC_PARAMS_t *sync_params = &sl_ue->sync_params;
|
||||
NR_DL_FRAME_PARMS *sl_fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
int16_t **pss_for_correlation = (int16_t **)sl_ue->init_params.sl_pss_for_correlation;
|
||||
|
||||
int maxval=0;
|
||||
int32_t **rxdata = NULL;
|
||||
unsigned int n, ar, peak_position = 0, pss_source = 0;
|
||||
int64_t peak_value = 0;
|
||||
double ffo_est=0;
|
||||
|
||||
int64_t avg[SL_NR_NUM_IDs_IN_PSS];
|
||||
uint32_t length = (frame_index == 0) ? sl_fp->samples_per_frame + (2 * sl_fp->ofdm_symbol_size) : sl_fp->samples_per_frame;
|
||||
int64_t psss_corr_value = 0;
|
||||
|
||||
rxdata = (int32_t **)UE->common_vars.rxdata;
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
char fname[50], sname[25];
|
||||
sprintf(fname,"rxdata_frame_%d.m",frame_index);
|
||||
sprintf(sname,"rxd_frame%d",frame_index);
|
||||
LOG_M(fname,sname, &rxdata[0][frame_index * sl_fp->samples_per_frame],sl_fp->samples_per_frame,1,1);
|
||||
LOG_M("pss_for_correlation0.m","pss_id0", pss_for_correlation[0],2048,1,1);
|
||||
LOG_M("pss_for_correlation1.m","pss_id1", pss_for_correlation[1],2048,1,1);
|
||||
|
||||
int64_t *pss_corr_debug_values[SL_NR_NUM_IDs_IN_PSS];
|
||||
#endif
|
||||
|
||||
for (int i=0;i<2*(sl_fp->ofdm_symbol_size);i++) {
|
||||
maxval = max(maxval,pss_for_correlation[0][i]);
|
||||
maxval = max(maxval,-pss_for_correlation[0][i]);
|
||||
maxval = max(maxval,pss_for_correlation[1][i]);
|
||||
maxval = max(maxval,-pss_for_correlation[1][i]);
|
||||
}
|
||||
|
||||
int shift = log2_approx(maxval);//*(sl_fp->ofdm_symbol_size + sl_fp->nb_prefix_samples)*2);
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
LOG_I(NR_PHY,"SIDELINK SLSS SEARCH: Function:%s\n", __func__);
|
||||
LOG_I(NR_PHY,"maxval:%d, shift:%d\n", maxval, shift);
|
||||
#endif
|
||||
|
||||
for (int pss_index = 0; pss_index < SL_NR_NUM_IDs_IN_PSS; pss_index++) {
|
||||
avg[pss_index]=0;
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
pss_corr_debug_values[pss_index] = malloc16_clear(length*sizeof(int64_t));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (n=0; n < length - sl_fp->ofdm_symbol_size; n+=4) { //
|
||||
|
||||
for (int pss_index = 0; pss_index < SL_NR_NUM_IDs_IN_PSS; pss_index++) {
|
||||
psss_corr_value = 0;
|
||||
|
||||
|
||||
// calculate dot product of primary_synchro_time_nr and rxdata[ar][n] (ar=0..nb_ant_rx) and store the sum in temp[n];
|
||||
for (ar=0; ar<sl_fp->nb_antennas_rx; ar++) {
|
||||
|
||||
/* perform correlation of rx data and pss sequence ie it is a dot product */
|
||||
const c32_t result = dot_product((c16_t *)pss_for_correlation[pss_index],
|
||||
(c16_t *)&(rxdata[ar][n + frame_index * sl_fp->samples_per_frame]),
|
||||
sl_fp->ofdm_symbol_size,
|
||||
shift);
|
||||
|
||||
const c64_t r64 = {.r = result.r, .i = result.i};
|
||||
psss_corr_value += squaredMod(r64);
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
pss_corr_debug_values[pss_index][n] = psss_corr_value;
|
||||
#endif
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("frame:%d n:%d, pss_index:%d, pss_for_correlation[pss_index][0]:%x, rxdata[n]:%x\n",
|
||||
frame_index, n, pss_index, pss_for_correlation[pss_index][0], rxdata[ar][n + frame_index * sl_fp->samples_per_frame]);
|
||||
printf("result %lld, pss_corr_values[%d][%d]:%ld\n",result, pss_index, n, pss_corr_debug_values[pss_index][n]);
|
||||
printf("pss_index %d: n %6u peak_value %15llu\n", pss_index, n, (unsigned long long)pss_corr_debug_values[pss_index][n]);
|
||||
printf("peak_value:%ld, peak_position:%d, pss_source:%d\n", peak_value, peak_position, pss_source);
|
||||
#endif
|
||||
}
|
||||
|
||||
// calculate the absolute value of sync_corr[n]
|
||||
avg[pss_index] += psss_corr_value;
|
||||
if (psss_corr_value > peak_value) {
|
||||
peak_value = psss_corr_value;
|
||||
peak_position = n;
|
||||
pss_source = pss_index;
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("pss_index %d: n %6u peak_value %15llu\n", pss_index, n, (unsigned long long)psss_corr_value);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
LOG_M("pss_corr_debug_values_0.m","pss_corr0", &pss_corr_debug_values[0][0],length,1,6);
|
||||
LOG_M("pss_corr_debug_values_1.m","pss_corr1", &pss_corr_debug_values[1][0],length,1,6);
|
||||
|
||||
for (int pss_index = 0; pss_index < SL_NR_NUM_IDs_IN_PSS; pss_index++) {
|
||||
free(pss_corr_debug_values[pss_index]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (UE->UE_fo_compensation) { // Not tested
|
||||
|
||||
// fractional frequency offset computation according to Cross-correlation Synchronization Algorithm Using PSS
|
||||
// Shoujun Huang, Yongtao Su, Ying He and Shan Tang, "Joint time and frequency offset estimation in LTE downlink," 7th International Conference on Communications and Networking in China, 2012.
|
||||
|
||||
// Computing cross-correlation at peak on half the symbol size for first half of data
|
||||
c32_t r1 = dot_product((c16_t *)pss_for_correlation[pss_source],
|
||||
(c16_t *)&(rxdata[0][peak_position + frame_index * sl_fp->samples_per_frame]),
|
||||
sl_fp->ofdm_symbol_size>>1,
|
||||
shift);
|
||||
// Computing cross-correlation at peak on half the symbol size for data shifted by half symbol size
|
||||
// as it is real and complex it is necessary to shift by a value equal to symbol size to obtain such shift
|
||||
c32_t r2 = dot_product((c16_t *)pss_for_correlation[pss_source] + (sl_fp->ofdm_symbol_size >> 1),
|
||||
(c16_t *)&(rxdata[0][peak_position + frame_index * sl_fp->samples_per_frame]) + (sl_fp->ofdm_symbol_size >> 1),
|
||||
sl_fp->ofdm_symbol_size >> 1,
|
||||
shift);
|
||||
cd_t r1d = {r1.r, r1.i}, r2d = {r2.r, r2.i};
|
||||
// estimation of fractional frequency offset: angle[(result1)'*(result2)]/pi
|
||||
ffo_est = atan2(r1d.r * r2d.i - r2d.r * r1d.i, r1d.r * r2d.r + r1d.i * r2d.i) / M_PI;
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("ffo %lf\n",ffo_est);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// computing absolute value of frequency offset
|
||||
sync_params->freq_offset = ffo_est*sl_fp->subcarrier_spacing;
|
||||
UE->common_vars.freq_offset = sync_params->freq_offset;
|
||||
for (int pss_index = 0; pss_index < SL_NR_NUM_IDs_IN_PSS; pss_index++) avg[pss_index]/=(length/4);
|
||||
|
||||
sync_params->N_sl_id2 = pss_source;
|
||||
|
||||
LOG_I(NR_PHY,"%sPSS Source = %d, Peak found at pos %d, val = %llu (%d dB) avg %d dB, ffo %lf, freq offset:%d Hz\n",
|
||||
KRED,pss_source, peak_position, (unsigned long long)peak_value, dB_fixed64(peak_value),dB_fixed64(avg[pss_source]),ffo_est, sync_params->freq_offset);
|
||||
|
||||
if (peak_value < 5*avg[pss_source])
|
||||
return(-1);
|
||||
|
||||
return peak_position;
|
||||
}
|
||||
|
||||
#define SL_NR_MAX_RX_ANTENNA 1
|
||||
#define SL_NR_FIRST_PSS_SYMBOL 1
|
||||
#define SL_NR_FIRST_SSS_SYMBOL 3
|
||||
#define SL_NR_NUM_PSS_SSS_SYMBOLS 4
|
||||
|
||||
static void sl_nr_extract_sss(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc,
|
||||
int32_t *tot_metric, uint8_t *phase_max,
|
||||
c16_t rxdataF[][ue->SL_UE_PHY_PARAMS.sl_frame_params.samples_per_slot_wCP])
|
||||
{
|
||||
|
||||
c16_t pss_ext[SL_NR_MAX_RX_ANTENNA][SL_NR_NUM_PSS_SYMBOLS][SL_NR_PSS_SEQUENCE_LENGTH];
|
||||
c16_t sss_ext[SL_NR_MAX_RX_ANTENNA][SL_NR_NUM_SSS_SYMBOLS][SL_NR_PSS_SEQUENCE_LENGTH];
|
||||
uint8_t Nid2 = ue->SL_UE_PHY_PARAMS.sync_params.N_sl_id2;
|
||||
NR_DL_FRAME_PARMS *sl_fp=&ue->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
int32_t metric, metric_re;
|
||||
int16_t *d;
|
||||
uint16_t Nid1 = 0;
|
||||
uint8_t phase;
|
||||
int16_t *sss;
|
||||
c16_t *rxF_ext;
|
||||
|
||||
for (int aarx=0; aarx < sl_fp->nb_antennas_rx; aarx++) {
|
||||
|
||||
unsigned int ofdm_symbol_size = sl_fp->ofdm_symbol_size;
|
||||
|
||||
// pss, sss extraction
|
||||
for (int sym = SL_NR_FIRST_PSS_SYMBOL; sym < SL_NR_FIRST_PSS_SYMBOL + SL_NR_NUM_PSS_SSS_SYMBOLS;sym ++) {
|
||||
|
||||
if (sym < SL_NR_FIRST_PSS_SYMBOL + SL_NR_NUM_PSS_SYMBOLS) {
|
||||
rxF_ext = &pss_ext[aarx][sym-SL_NR_FIRST_PSS_SYMBOL][0];
|
||||
} else {
|
||||
rxF_ext = &sss_ext[aarx][sym-SL_NR_FIRST_SSS_SYMBOL][0];
|
||||
}
|
||||
|
||||
unsigned int k = sl_fp->first_carrier_offset + sl_fp->ssb_start_subcarrier + 2;
|
||||
if (k >= ofdm_symbol_size) k -= ofdm_symbol_size;
|
||||
|
||||
LOG_D(PHY, "firstcarrieroffset:%d, ssb_sc:%d, k:%d, symbol:%d\n",sl_fp->first_carrier_offset, sl_fp->ssb_start_subcarrier, k, sym);
|
||||
|
||||
for (int i=0; i < SL_NR_PSS_SEQUENCE_LENGTH; i++) {
|
||||
rxF_ext[i] = rxdataF[aarx][sym*ofdm_symbol_size + k];
|
||||
k++;
|
||||
if (k == ofdm_symbol_size) k=0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LOG_D(PHY, "SIDELINK SLSS SEARCH: EXTRACTION OF PSS, SSS done\n");
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
LOG_M("pss_ext_sym1.m","pss_ext1",&pss_ext[aarx][0][0],SL_NR_PSS_SEQUENCE_LENGTH,1,1);
|
||||
LOG_M("pss_ext_sym2.m","pss_ext2",&pss_ext[aarx][1][0],SL_NR_PSS_SEQUENCE_LENGTH,1,1);
|
||||
LOG_M("sss_ext_sym3.m","sss_ext3",&sss_ext[aarx][0][0],SL_NR_PSS_SEQUENCE_LENGTH,1,1);
|
||||
LOG_M("sss_ext_sym4.m","sss_ext4",&sss_ext[aarx][1][0],SL_NR_PSS_SEQUENCE_LENGTH,1,1);
|
||||
#endif
|
||||
|
||||
|
||||
// get conjugated channel estimate from PSS, H* = R* \cdot PSS
|
||||
// and do channel estimation and compensation based on PSS
|
||||
int16_t *pss = ue->SL_UE_PHY_PARAMS.init_params.sl_pss_for_sync[Nid2];
|
||||
int16_t *pss_ext2,*sss_ext2;
|
||||
int16_t tmp_re,tmp_im,tmp_re2,tmp_im2;
|
||||
int32_t amp, shift;
|
||||
|
||||
for (int j=0; j<2;j++) {
|
||||
|
||||
int16_t *sss_ext3 = (int16_t*)&sss_ext[aarx][j][0];
|
||||
sss_ext2 = (int16_t*)&sss_ext[aarx][j][0];
|
||||
pss_ext2 = (int16_t*)&pss_ext[aarx][j][0];
|
||||
|
||||
for (int i = 0; i < SL_NR_PSS_SEQUENCE_LENGTH; i++) {
|
||||
|
||||
// This is H*(PSS) = R* \cdot PSS
|
||||
tmp_re = pss_ext2[i*2] * pss[i];
|
||||
tmp_im = -pss_ext2[i*2+1] * pss[i];
|
||||
|
||||
amp = (((int32_t)tmp_re)*tmp_re) + ((int32_t)tmp_im)*tmp_im;
|
||||
shift = log2_approx(amp)/2;
|
||||
|
||||
// This is R(SSS) \cdot H*(PSS)
|
||||
tmp_re2 = (int16_t)(((tmp_re * (int32_t)sss_ext2[i*2])>>shift) - ((tmp_im * (int32_t)sss_ext2[i*2+1]>>shift)));
|
||||
tmp_im2 = (int16_t)(((tmp_re * (int32_t)sss_ext2[i*2+1])>>shift) + ((tmp_im * (int32_t)sss_ext2[i*2]>>shift)));
|
||||
|
||||
// MRC on RX antennas
|
||||
// sss_ext now contains the compensated SSS
|
||||
if (aarx==0) {
|
||||
sss_ext3[i<<1] = tmp_re2;
|
||||
sss_ext3[1+(i<<1)] = tmp_im2;
|
||||
} else {
|
||||
AssertFatal(1==0,"SIDELINK MORE THAN 1 RX ANTENNA NOT YET SUPPORTED\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG_D(PHY, "SIDELINK SLSS SEARCH: Ch. estimation SSS done\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
|
||||
write_output("rxsig0.m","rxs0",&ue->common_vars.rxdata[0][0],ue->frame_parms.samples_per_subframe,1,1);
|
||||
write_output("rxdataF0_pss.m","rxF0_pss",&ue->common_vars.rxdataF[0][0],frame_parms->ofdm_symbol_size,1,1);
|
||||
write_output("rxdataF0_sss.m","rxF0_sss",&ue->common_vars.rxdataF[0][(SSS_SYMBOL_NB-PSS_SYMBOL_NB)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size,1,1);
|
||||
write_output("pss_ext.m","pss_ext",pss_ext,LENGTH_PSS_NR,1,1);
|
||||
|
||||
#endif
|
||||
*/
|
||||
#if 0
|
||||
printf("H*(%d,%d) : (%d,%d)\n",aarx,i,tmp_re,tmp_im);
|
||||
printf("pss(%d,%d) : (%d,%d)\n",aarx,i,pss[2*i],pss[2*i+1]);
|
||||
printf("pss_ext(%d,%d) : (%d,%d)\n",aarx,i,pss_ext2[2*i],pss_ext2[2*i+1]);
|
||||
if (aarx==0) {
|
||||
chest[i<<1]=tmp_re;
|
||||
chest[1+(i<<1)]=tmp_im;
|
||||
}
|
||||
#endif
|
||||
// printf("SSSi(%d,%d) : (%d,%d)\n",aarx,i,sss_ext2[i<<1],sss_ext2[1+(i<<1)]);
|
||||
// printf("SSSo(%d,%d) : (%d,%d)\n",aarx,i,tmp_re2,tmp_im2);
|
||||
// MRC on RX antennas
|
||||
#if 0
|
||||
LOG_M("pssrx.m","pssrx",pss,LENGTH_PSS_NR,1,1);
|
||||
LOG_M("pss_ext.m","pssext",pss_ext2,LENGTH_PSS_NR,1,1);
|
||||
LOG_M("psschest.m","pssch",chest,LENGTH_PSS_NR,1,1);
|
||||
#endif
|
||||
#if 0
|
||||
|
||||
for (int i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
printf(" sss ext 2 [%d] %d %d at address %p\n", i, sss_ext2[2*i], sss_ext2[2*i+1]);
|
||||
printf(" sss ref [%d] %d %d at address %p\n", i, d_sss[0][0][i], d_sss[0][0][i]);
|
||||
printf(" sss ext 3 [%d] %d %d at address %p\n", i, sss_ext3[2*i], sss_ext3[2*i+1]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
/* simulate of a phase shift on the signal */
|
||||
|
||||
int phase_shift_index = 0;
|
||||
|
||||
phase_shift_samples(sss, LENGTH_SSS_NR, phase_re_nr[phase_shift_index], phase_im_nr[phase_shift_index]);
|
||||
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
int16_t *ps = (int16_t *)pss_ext;
|
||||
|
||||
for (int i = 0; i < LENGTH_SSS_NR; i++) {
|
||||
printf("sss ref [%i] : %d \n", i, d_sss[0][0][i]);
|
||||
printf("sss ext [%i] : %d %d \n", i, sss[2*i], sss[2*i+1]);
|
||||
|
||||
printf("pss ref [%i] : %d %d \n", i, primary_synchro_nr2[0][2*i], primary_synchro_nr2[0][2*i+1]);
|
||||
printf("pss ext [%i] : %d %d \n", i, ps[2*i], ps[2*i+1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* for phase evaluation, one uses an array of possible phase shifts */
|
||||
/* then a correlation is done between received signal with a shift pĥase and the reference signal */
|
||||
/* Computation of signal with shift phase is based on below formula */
|
||||
/* cosinus cos(x + y) = cos(x)cos(y) - sin(x)sin(y) */
|
||||
/* sinus sin(x + y) = sin(x)cos(y) + cos(x)sin(y) */
|
||||
|
||||
// now do the SSS detection based on the pre computed SSS sequences
|
||||
*tot_metric = INT_MIN;
|
||||
sss = (int16_t*)&sss_ext[0][0][0];
|
||||
|
||||
for (uint16_t id1 = 0 ; id1 < SL_NR_NUM_IDs_IN_SSS; id1++) { // all possible SSS Nid1 values
|
||||
for (phase=0; phase < PHASE_HYPOTHESIS_NUMBER; phase++) { // phase offset between PSS and SSS
|
||||
|
||||
metric = 0;
|
||||
metric_re = 0;
|
||||
|
||||
d = (int16_t *)&ue->SL_UE_PHY_PARAMS.init_params.sl_sss_for_sync[Nid2 * SL_NR_NUM_IDs_IN_SSS + id1];
|
||||
|
||||
// This is the inner product using one particular value of each unknown parameter
|
||||
for (int i=0; i < SL_NR_SSS_SEQUENCE_LENGTH; i++) {
|
||||
|
||||
metric_re += d[i]*(((sl_phase_re_nr[phase]*sss[2*i])>>15) - ((sl_phase_im_nr[phase]*sss[2*i+1])>>15));
|
||||
|
||||
#if 0
|
||||
printf("i %d, phase %d/%d: metric %d, phase (%d,%d) sss (%d,%d) d %d\n",i,phase,PHASE_HYPOTHESIS_NUMBER,metric_re,phase_re_nr[phase],phase_im_nr[phase],sss[2*i],sss[1+(2*i)],d[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
metric = metric_re;
|
||||
|
||||
// if the current metric is better than the last save it
|
||||
if (metric > *tot_metric) {
|
||||
*tot_metric = metric;
|
||||
Nid1 = id1;
|
||||
*phase_max = phase;
|
||||
|
||||
LOG_D(PHY, "(phase,Nid1) (%d,%d), metric_phase %d tot_metric %d, phase_max %d \n",phase, Nid1, metric, *tot_metric, *phase_max);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ue->SL_UE_PHY_PARAMS.sync_params.N_sl_id1 = Nid1;
|
||||
ue->SL_UE_PHY_PARAMS.sync_params.N_sl_id = ue->SL_UE_PHY_PARAMS.sync_params.N_sl_id1 + 336 * ue->SL_UE_PHY_PARAMS.sync_params.N_sl_id2;
|
||||
LOG_I(NR_PHY, "%sUE[%d]NR-SL SLSS SEARCH: SSS Processing over. id2 from SSS:%d, id1 from PSS:%d, SLSS id:%d\n",KRED,
|
||||
ue->Mod_id, ue->SL_UE_PHY_PARAMS.sync_params.N_sl_id1, ue->SL_UE_PHY_PARAMS.sync_params.N_sl_id2,
|
||||
ue->SL_UE_PHY_PARAMS.sync_params.N_sl_id);
|
||||
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
#define SSS_METRIC_FLOOR_NR (30000)
|
||||
if (*tot_metric > SSS_METRIC_FLOOR_NR) {
|
||||
Nid2 = ue->SL_UE_PHY_PARAMS.sync_params.N_sl_id2;
|
||||
Nid1 = ue->SL_UE_PHY_PARAMS.sync_params.N_sl_id1;
|
||||
printf("Nid2 %d Nid1 %d tot_metric %d, phase_max %d \n", Nid2, Nid1, *tot_metric, *phase_max);
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Right now 2 frames worth of samples get processed for PSS in OAI.
|
||||
// For PSS in Sidelink, worst case 1 SSB in 16 frames can be present
|
||||
// Hence 16 frames worth of samples needs to be correlated to find the PSS.
|
||||
int sl_nr_slss_search(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc, int num_frames) {
|
||||
|
||||
sl_nr_ue_phy_params_t *sl_ue = &UE->SL_UE_PHY_PARAMS;
|
||||
SL_NR_SYNC_PARAMS_t *sync_params = &sl_ue->sync_params;
|
||||
NR_DL_FRAME_PARMS *sl_fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
int32_t sync_pos = -1;// sync_pos_frame = -1;
|
||||
int32_t metric_tdd_ncp=0;
|
||||
uint8_t phase_tdd_ncp = 0;
|
||||
double im, re;
|
||||
int ret=-1;
|
||||
uint16_t rx_slss_id = 65535;
|
||||
|
||||
#ifdef SL_DEBUG_SEARCH_SLSS
|
||||
LOG_D(PHY, "SIDELINK SEARCH SLSS: Function:%s\n", __func__);
|
||||
#endif
|
||||
|
||||
/* Initial synchronisation
|
||||
*
|
||||
* 1 radio frame = 10 ms
|
||||
* <--------------------------------------------------------------------------->
|
||||
* | Received UE data buffer |
|
||||
* ----------------------------------------------------------------------------
|
||||
* <-------------->|psbch|pss|pss|sss|sss|psbch sym5-sym 12|sym13 - guard|
|
||||
* sync_pos SS/PSBCH block
|
||||
*/
|
||||
|
||||
// initial sync performed on 16 successive frames. Worst case - one PSBCH can be sent in 16 frames.
|
||||
//If psbch passes on first frame, no need to process second frame
|
||||
// Problem with the frame approach is that
|
||||
// --------- SSB can be on the boundary between frames. In this case if only 1 SSB is sent we will miss it.
|
||||
// rxdata will hold 16 frames + slot worth of samples. This needs to be processed to find the best SSB
|
||||
for(int frame_index = 0; frame_index < num_frames; frame_index++) {
|
||||
|
||||
/* process pss search on received buffer */
|
||||
sync_pos = sl_nr_pss_correlation(UE, frame_index);
|
||||
|
||||
if (sync_pos == -1) {
|
||||
LOG_I(NR_PHY,"SIDELINK SEARCH SLSS: No PSSS found in this frame\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
sync_pos += frame_index * sl_fp->samples_per_frame; // position in the num_frames frame samples
|
||||
|
||||
for (int pss_sym = 1; pss_sym < 3;pss_sym++) {
|
||||
// Now Sync pos can point to PSS 1st symbol or 2nd symbol.
|
||||
// Right now implemented the strategy to try both locations for FFT
|
||||
// Think about a better correlation strategy
|
||||
if (pss_sym == 1) { // Check if sync pos points to SYMBOL1 - first symbol of PSS location
|
||||
if (sync_pos > sl_fp->nb_prefix_samples0 + sl_fp->ofdm_symbol_size + sl_fp->nb_prefix_samples)
|
||||
sync_params->ssb_offset = sync_pos - (sl_fp->nb_prefix_samples0 + sl_fp->ofdm_symbol_size + sl_fp->nb_prefix_samples);
|
||||
else
|
||||
sync_params->ssb_offset = sync_pos + sl_fp->samples_per_frame - (sl_fp->nb_prefix_samples0 + sl_fp->ofdm_symbol_size + sl_fp->nb_prefix_samples);
|
||||
} else { // Check if sync pos points to SYMBOL2 - second symbol of PSS location
|
||||
if (sync_pos >= sl_fp->nb_prefix_samples0 + 2*(sl_fp->ofdm_symbol_size + sl_fp->nb_prefix_samples))
|
||||
sync_params->ssb_offset = sync_pos - (sl_fp->nb_prefix_samples0 + 2*(sl_fp->ofdm_symbol_size + sl_fp->nb_prefix_samples));
|
||||
else
|
||||
sync_params->ssb_offset = sync_pos + sl_fp->samples_per_frame - (sl_fp->nb_prefix_samples0 + 2*(sl_fp->ofdm_symbol_size + sl_fp->nb_prefix_samples));
|
||||
}
|
||||
|
||||
#define SL_NR_NUM_SYMBOLS_FOR_PSBCH_NORMAL_CP 14
|
||||
|
||||
LOG_I(NR_PHY,"%sUE[%d]SIDELINK SEARCH SLSS: PSS Peak at %d, PSS sym:%d, Estimated PSS position %d\n",KRED,
|
||||
UE->Mod_id,sync_pos,pss_sym,sync_params->ssb_offset);
|
||||
|
||||
int slss_block_samples = (SL_NR_NUM_SYMBOLS_FOR_PSBCH_NORMAL_CP * sl_fp->ofdm_symbol_size) +
|
||||
(SL_NR_NUM_SYMBOLS_FOR_PSBCH_NORMAL_CP -1) * sl_fp->nb_prefix_samples + sl_fp->nb_prefix_samples0;
|
||||
|
||||
int ssb_end_position = sync_params->ssb_offset + slss_block_samples;
|
||||
|
||||
LOG_D(PHY, "ssb_end:%d ssb block samples:%d total samples: %d\n", ssb_end_position, slss_block_samples, num_frames * sl_fp->samples_per_frame);
|
||||
|
||||
|
||||
/* check that SSS/PBCH block is continuous inside the received buffer */
|
||||
if (ssb_end_position < num_frames * sl_fp->samples_per_frame) {
|
||||
|
||||
// digital compensation of FFO for SSB symbols
|
||||
if (UE->UE_fo_compensation){ // This code to be checked. Why do we do this before PSS detection is successful?
|
||||
double s_time = 1/(1.0e3 * sl_fp->samples_per_subframe); // sampling time
|
||||
double off_angle = -2 * M_PI * s_time * (sync_params->freq_offset); // offset rotation angle compensation per sample
|
||||
|
||||
int start = sync_params->ssb_offset; // start for offset correction is at ssb_offset (pss time position)
|
||||
// Adapt this for other numerologies number of symbols with larger cp increases TBD
|
||||
int end = ssb_end_position; // loop over samples in all symbols (ssb size), including prefix
|
||||
|
||||
|
||||
LOG_I(NR_PHY,"%sSLSS SEARCH: FREQ comp of SLSS samples. Freq_OFSET:%d, startpos:%d, end_pos:%d\n",KRED,
|
||||
sync_params->freq_offset, start, end);
|
||||
for(int n=start; n<end; n++) {
|
||||
for (int ar=0; ar<sl_fp->nb_antennas_rx; ar++) {
|
||||
re = ((double)(((short *)UE->common_vars.rxdata[ar]))[2*n]);
|
||||
im = ((double)(((short *)UE->common_vars.rxdata[ar]))[2*n+1]);
|
||||
((short *)UE->common_vars.rxdata[ar])[2*n] = (short)(round(re*cos(n*off_angle) - im*sin(n*off_angle)));
|
||||
((short *)UE->common_vars.rxdata[ar])[2*n+1] = (short)(round(re*sin(n*off_angle) + im*cos(n*off_angle)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NR_DL_FRAME_PARMS *frame_parms = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
const uint32_t rxdataF_sz = frame_parms->samples_per_slot_wCP;
|
||||
__attribute__ ((aligned(32))) c16_t rxdataF[frame_parms->nb_antennas_rx][rxdataF_sz];
|
||||
|
||||
/* In order to achieve correct processing for NR prefix samples is forced to 0 and then restored after function call */
|
||||
for(int symbol=0; symbol<SL_NR_NUM_SYMBOLS_FOR_PSBCH_NORMAL_CP;symbol++) {
|
||||
sl_nr_slot_fep(UE,
|
||||
NULL,
|
||||
symbol,
|
||||
0,
|
||||
sync_params->ssb_offset,
|
||||
rxdataF);
|
||||
}
|
||||
|
||||
sl_nr_extract_sss(UE, NULL, &metric_tdd_ncp, &phase_tdd_ncp, rxdataF);
|
||||
|
||||
// save detected cell id to psbch
|
||||
rx_slss_id = UE->SL_UE_PHY_PARAMS.sync_params.N_sl_id;
|
||||
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates[frame_parms->nb_antennas_rx][rxdataF_sz];
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_time[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size];
|
||||
|
||||
uint8_t decoded_output[4];
|
||||
|
||||
for (int symbol = 0; symbol < SL_NR_NUM_SYMBOLS_FOR_PSBCH_NORMAL_CP-1;) {
|
||||
nr_pbch_channel_estimation(UE,
|
||||
frame_parms,
|
||||
rxdataF_sz,
|
||||
dl_ch_estimates,
|
||||
dl_ch_estimates_time,
|
||||
proc,
|
||||
symbol,
|
||||
symbol,
|
||||
0,
|
||||
0,
|
||||
rxdataF,
|
||||
1,
|
||||
rx_slss_id);
|
||||
|
||||
symbol = (symbol == 0) ? 5 : symbol+1;
|
||||
}
|
||||
|
||||
ret = nr_rx_psbch(UE,proc,
|
||||
rxdataF_sz,
|
||||
dl_ch_estimates,
|
||||
frame_parms,
|
||||
decoded_output,
|
||||
rxdataF,
|
||||
rx_slss_id);
|
||||
|
||||
if (ret == 0) { // Check this later TBD
|
||||
// sync at symbol ue->symbol_offset
|
||||
// computing the offset wrt the beginning of the frame
|
||||
// SSB located at symbol 0
|
||||
sync_params->remaining_frames = (num_frames * sl_fp->samples_per_frame - sync_params->ssb_offset)/sl_fp->samples_per_frame;
|
||||
//ssb_offset points to start of sl-ssb
|
||||
//rx_offset points to remaining samples needed to fill a frame
|
||||
sync_params->rx_offset = sync_params->ssb_offset % sl_fp->samples_per_frame;
|
||||
|
||||
LOG_I(NR_PHY,"%sUE[%d]SIDELINK SLSS SEARCH: PSBCH RX OK. Remainingframes:%d, rx_offset:%d\n",KRED,
|
||||
UE->Mod_id,sync_params->remaining_frames, sync_params->rx_offset);
|
||||
|
||||
uint32_t psbch_payload = (*(uint32_t *)decoded_output);
|
||||
//retrieve DFN and slot number from SL-MIB
|
||||
sync_params->DFN = (((psbch_payload & 0x0700) >> 1) | ((psbch_payload & 0xFE0000) >> 17));
|
||||
sync_params->slot_offset = (((psbch_payload & 0x010000) >> 10) | ((psbch_payload & 0xFC000000) >> 26));
|
||||
|
||||
LOG_I(NR_PHY, "%sUE[%d]SIDELINK SLSS SEARCH: SL-MIB: DFN:%d, slot:%d.\n",KRED,
|
||||
UE->Mod_id, sync_params->DFN, sync_params->slot_offset);
|
||||
|
||||
nr_sl_psbch_rsrp_measurements(sl_ue,frame_parms,rxdataF, false);
|
||||
|
||||
UE->init_sync_frame = sync_params->remaining_frames;
|
||||
UE->rx_offset = sync_params->rx_offset;
|
||||
|
||||
nr_sidelink_indication_t sl_indication;
|
||||
sl_nr_rx_indication_t rx_ind = {0};
|
||||
uint16_t number_pdus = 1;
|
||||
nr_fill_sl_indication(&sl_indication, &rx_ind, NULL, proc, UE, NULL);
|
||||
nr_fill_sl_rx_indication(&rx_ind, SL_NR_RX_PDU_TYPE_SSB, UE, number_pdus, proc, (void *)decoded_output, rx_slss_id);
|
||||
|
||||
|
||||
LOG_D(PHY,"Sidelink SLSS SEARCH PSBCH RX OK. Send SL-SSB TO MAC\n");
|
||||
|
||||
if (UE->if_inst && UE->if_inst->sl_indication)
|
||||
UE->if_inst->sl_indication(&sl_indication);
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_I(NR_PHY,"SIDELINK SLSS SEARCH: SLSS ID: %d metric %d, phase %d, psbch CRC %s\n",
|
||||
sl_ue->sync_params.N_sl_id,metric_tdd_ncp,phase_tdd_ncp,(ret == 0) ? "OK" : "NOT OK");
|
||||
|
||||
} else {
|
||||
LOG_W(PHY,"SIDELINK SLSS SEARCH: Error: Not enough samples to process PSBCH. sync_pos %d\n", sync_pos);
|
||||
}
|
||||
}
|
||||
if (ret == 0) break;
|
||||
}
|
||||
|
||||
if (ret!=0) { // PSBCH not found so indicate sync to higher layers and configure frame parameters
|
||||
LOG_E(PHY,"SIDELINK SLSS SEARCH: PSBCH not received. Estimated PSS position:%d\n", sync_pos);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -244,7 +244,7 @@ int nr_pbch_channel_level(struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER
|
||||
return(avg2);
|
||||
}
|
||||
|
||||
static void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL],
|
||||
void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL],
|
||||
struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL],
|
||||
int nb_re,
|
||||
struct complex16 rxdataF_comp[][PBCH_MAX_RE_PER_SYMBOL],
|
||||
@@ -254,7 +254,6 @@ static void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][PBCH_MAX
|
||||
vect128 *dl_ch128 = (vect128 *)dl_ch_estimates_ext[aarx];
|
||||
vect128 *rxdataF128 = (vect128 *)rxdataF_ext[aarx];
|
||||
vect128 *rxdataF_comp128 = (vect128 *)rxdataF_comp[aarx];
|
||||
|
||||
for (int re=0; re<nb_re; re+=12) {
|
||||
*rxdataF_comp128++ = mulByConjugate128(rxdataF128++, dl_ch128++, output_shift);
|
||||
*rxdataF_comp128++ = mulByConjugate128(rxdataF128++, dl_ch128++, output_shift);
|
||||
@@ -300,7 +299,7 @@ void nr_pbch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms,
|
||||
#endif
|
||||
}
|
||||
|
||||
static void nr_pbch_unscrambling(int16_t *demod_pbch_e,
|
||||
void nr_pbch_unscrambling(int16_t *demod_pbch_e,
|
||||
uint16_t Nid,
|
||||
uint8_t nushift,
|
||||
uint16_t M,
|
||||
@@ -362,7 +361,7 @@ static void nr_pbch_unscrambling(int16_t *demod_pbch_e,
|
||||
}
|
||||
}
|
||||
|
||||
static void nr_pbch_quantize(int16_t *pbch_llr8,
|
||||
void nr_pbch_quantize(int16_t *pbch_llr8,
|
||||
int16_t *pbch_llr,
|
||||
uint16_t len) {
|
||||
for (int i=0; i<len; i++) {
|
||||
@@ -505,7 +504,7 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
|
||||
0, 0, pbch_a_prime, &pbch_a_interleaved);
|
||||
//polar decoding de-rate matching
|
||||
uint64_t tmp=0;
|
||||
decoderState = polar_decoder_int16(pbch_e_rx,(uint64_t *)&tmp,0,
|
||||
decoderState = polar_decoder_int16(pbch_e_rx,(uint64_t *)&tmp,NULL,0,
|
||||
NR_POLAR_PBCH_MESSAGE_TYPE, NR_POLAR_PBCH_PAYLOAD_BITS, NR_POLAR_PBCH_AGGREGATION_LEVEL);
|
||||
pbch_a_prime = tmp;
|
||||
|
||||
|
||||
269
openair1/PHY/NR_UE_TRANSPORT/nr_psbch_rx.c
Normal file
269
openair1/PHY/NR_UE_TRANSPORT/nr_psbch_rx.c
Normal file
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* 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.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h"
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "PHY/TOOLS/phy_scope_interface.h"
|
||||
|
||||
|
||||
//#define DEBUG_PSBCH
|
||||
|
||||
//Reuse already existing PBCH functions
|
||||
extern int nr_pbch_channel_level(struct complex16 dl_ch_estimates_ext[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
int nb_re);
|
||||
extern void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
|
||||
struct complex16 dl_ch_estimates_ext[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
|
||||
int nb_re,
|
||||
struct complex16 rxdataF_comp[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t output_shift);
|
||||
extern void nr_pbch_unscrambling(int16_t *demod_pbch_e,
|
||||
uint16_t Nid,
|
||||
uint8_t nushift,
|
||||
uint16_t M,
|
||||
uint16_t length,
|
||||
uint8_t bitwise,
|
||||
uint32_t unscrambling_mask,
|
||||
uint32_t pbch_a_prime,
|
||||
uint32_t *pbch_a_interleaved);
|
||||
extern void nr_pbch_quantize(int16_t *pbch_llr8,
|
||||
int16_t *pbch_llr,
|
||||
uint16_t len);
|
||||
|
||||
|
||||
static void nr_psbch_extract(uint32_t rxdataF_sz,
|
||||
c16_t rxdataF[][rxdataF_sz],
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
struct complex16 rxdataF_ext[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
|
||||
struct complex16 dl_ch_estimates_ext[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
|
||||
uint32_t symbol,
|
||||
NR_DL_FRAME_PARMS *frame_params)
|
||||
{
|
||||
uint16_t rb;
|
||||
uint8_t i,j,aarx;
|
||||
struct complex16 *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext;
|
||||
|
||||
const uint8_t nb_rb = SL_NR_NUM_PSBCH_RBS_IN_ONE_SYMBOL;
|
||||
|
||||
AssertFatal((symbol == 0 || symbol >= 5), "SIDELINK: PSBCH DMRS not contained in symbol %d \n", symbol);
|
||||
|
||||
for (aarx=0; aarx<frame_params->nb_antennas_rx; aarx++) {
|
||||
unsigned int rx_offset = frame_params->first_carrier_offset + frame_params->ssb_start_subcarrier;
|
||||
rx_offset = rx_offset % frame_params->ofdm_symbol_size;
|
||||
|
||||
rxF = &rxdataF[aarx][symbol*frame_params->ofdm_symbol_size];
|
||||
rxF_ext = &rxdataF_ext[aarx][0];
|
||||
|
||||
dl_ch0 = &dl_ch_estimates[aarx][symbol*frame_params->ofdm_symbol_size];
|
||||
dl_ch0_ext = &dl_ch_estimates_ext[aarx][0];
|
||||
|
||||
#ifdef DEBUG_PSBCH
|
||||
LOG_I(PHY, "extract_rbs: rx_offset=%d, symbol %u\n", (rx_offset + (symbol*frame_params->ofdm_symbol_size)),symbol);
|
||||
#endif
|
||||
|
||||
for (rb=0; rb<nb_rb; rb++) {
|
||||
j=0;
|
||||
|
||||
for (i=0; i<NR_NB_SC_PER_RB; i++) {
|
||||
|
||||
if (i%4 != 0) {
|
||||
|
||||
rxF_ext[j]=rxF[rx_offset];
|
||||
dl_ch0_ext[j]=dl_ch0[i];
|
||||
|
||||
#ifdef DEBUG_PSBCH
|
||||
|
||||
LOG_I(PHY,"rxF ext[%d] = (%d,%d) rxF [%u]= (%d,%d)\n",(9*rb) + j,
|
||||
((int16_t *)&rxF_ext[j])[0],
|
||||
((int16_t *)&rxF_ext[j])[1],
|
||||
rx_offset,
|
||||
((int16_t *)&rxF[rx_offset])[0],
|
||||
((int16_t *)&rxF[rx_offset])[1]);
|
||||
|
||||
LOG_I(PHY,"dl ch0 ext[%d] = (%d,%d) dl_ch0 [%d]= (%d,%d)\n", (9*rb) + j,
|
||||
((int16_t *)&dl_ch0_ext[j])[0],
|
||||
((int16_t *)&dl_ch0_ext[j])[1],
|
||||
i,
|
||||
((int16_t *)&dl_ch0[i])[0],
|
||||
((int16_t *)&dl_ch0[i])[1]);
|
||||
#endif
|
||||
j++;
|
||||
}
|
||||
rx_offset=(rx_offset+1)%(frame_params->ofdm_symbol_size);
|
||||
}
|
||||
|
||||
rxF_ext += SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_RB;
|
||||
dl_ch0_ext += SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_RB;
|
||||
dl_ch0 += NR_NB_SC_PER_RB;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PSBCH
|
||||
char filename[40], varname[25];
|
||||
sprintf(filename,"psbch_dlch_sym_%d.m", symbol);
|
||||
sprintf(varname,"psbch_dlch%d.m", symbol);
|
||||
LOG_M(filename, varname, (void*)dl_ch0, frame_params->ofdm_symbol_size, 1, 1);
|
||||
sprintf(filename,"psbch_dlchext_sym_%d.m", symbol);
|
||||
sprintf(varname,"psbch_dlchext%d.m", symbol);
|
||||
LOG_M(filename, varname, (void*)&dl_ch_estimates_ext[0][0], SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL , 1, 1);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
int nr_rx_psbch(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t *decoded_output,
|
||||
c16_t rxdataF[][frame_parms->samples_per_slot_wCP],
|
||||
uint16_t slss_id)
|
||||
{
|
||||
|
||||
uint32_t decoderState=0;
|
||||
int psbch_e_rx_idx = 0;
|
||||
int16_t psbch_e_rx[SL_NR_POLAR_PSBCH_E_NORMAL_CP]= {0};
|
||||
int16_t psbch_unClipped[SL_NR_POLAR_PSBCH_E_NORMAL_CP]= {0};
|
||||
|
||||
#ifdef DEBUG_PSBCH
|
||||
write_output("psbch_rxdataF.m","psbchrxF",
|
||||
&rxdataF[0][0],frame_parms->ofdm_symbol_size*SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP,1,1);
|
||||
#endif
|
||||
// symbol refers to symbol within SSB. symbol_offset is the offset of the SSB wrt start of slot
|
||||
double log2_maxh = 0;
|
||||
|
||||
// 0 for Normal Cyclic Prefix and 1 for EXT CyclicPrefix
|
||||
const int numsym = (frame_parms->Ncp) ? SL_NR_NUM_SYMBOLS_SSB_EXT_CP
|
||||
: SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP;
|
||||
|
||||
for (int symbol=0; symbol<numsym;) {
|
||||
const uint16_t nb_re = SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL;
|
||||
uint16_t nb_re2 = (nb_re/12)*12 + ((nb_re % 12)>0 ? 12 : 0);
|
||||
__attribute__ ((aligned(32))) struct complex16 rxdataF_ext[frame_parms->nb_antennas_rx][nb_re2];
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_ext[frame_parms->nb_antennas_rx][nb_re2];
|
||||
//memset(dl_ch_estimates_ext,0, sizeof dl_ch_estimates_ext);
|
||||
nr_psbch_extract(frame_parms->samples_per_slot_wCP,
|
||||
rxdataF,
|
||||
estimateSz,
|
||||
dl_ch_estimates,
|
||||
rxdataF_ext,
|
||||
dl_ch_estimates_ext,
|
||||
symbol,
|
||||
frame_parms);
|
||||
#ifdef DEBUG_PSBCH
|
||||
LOG_I(PHY,"PSBCH RX Symbol %d ofdm size %d\n",symbol, frame_parms->ofdm_symbol_size );
|
||||
#endif
|
||||
|
||||
int max_h=0;
|
||||
if (symbol == 0) {
|
||||
max_h = nr_pbch_channel_level(dl_ch_estimates_ext,
|
||||
frame_parms,
|
||||
nb_re);
|
||||
//log2_maxh = 3+(log2_approx(max_h)/2);
|
||||
log2_maxh = 5 +(log2_approx(max_h)/2);// LLR32 crc error. LLR 16 CRC works
|
||||
|
||||
}
|
||||
#ifdef DEBUG_PSBCH
|
||||
LOG_I(PHY,"PSBCH RX log2_maxh = %f (%d)\n", log2_maxh, max_h);
|
||||
#endif
|
||||
|
||||
__attribute__ ((aligned(32))) struct complex16 rxdataF_comp[frame_parms->nb_antennas_rx][nb_re2];
|
||||
nr_pbch_channel_compensation(rxdataF_ext,
|
||||
dl_ch_estimates_ext,
|
||||
nb_re,
|
||||
rxdataF_comp,
|
||||
frame_parms,
|
||||
log2_maxh); // log2_maxh+I0_shift
|
||||
|
||||
nr_pbch_quantize(psbch_e_rx + psbch_e_rx_idx,
|
||||
(short *)rxdataF_comp[0],
|
||||
SL_NR_NUM_PSBCH_DATA_BITS_IN_ONE_SYMBOL);
|
||||
|
||||
//Unnecessary copy. Used only for SCOPE ... TBD... to remove this.
|
||||
memcpy(psbch_unClipped + psbch_e_rx_idx, rxdataF_comp[0], SL_NR_NUM_PSBCH_DATA_BITS_IN_ONE_SYMBOL*sizeof(int16_t));
|
||||
psbch_e_rx_idx += SL_NR_NUM_PSBCH_DATA_BITS_IN_ONE_SYMBOL;
|
||||
|
||||
//SKIP 2 SL-PSS AND 2 SL-SSS symbols
|
||||
//Symbols carrying PSBCH 0, 5-12
|
||||
symbol = (symbol == 0) ? 5 : symbol + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
UEscopeCopy(ue, psbchRxdataF_comp, psbch_unClipped, sizeof(struct complex16), frame_parms->nb_antennas_rx, psbch_e_rx_idx/2,0);
|
||||
UEscopeCopy(ue, psbchLlr, psbch_e_rx, sizeof(int16_t), frame_parms->nb_antennas_rx, psbch_e_rx_idx,0);
|
||||
|
||||
#ifdef DEBUG_PSBCH
|
||||
write_output("psbch_rxdataFcomp.m","psbch_rxFcomp",psbch_unClipped,SL_NR_NUM_PSBCH_DATA_RE_IN_ALL_SYMBOLS,1,1);
|
||||
#endif
|
||||
|
||||
//un-scrambling
|
||||
LOG_D(PHY, "PSBCH RX POLAR DECODING: total PSBCH bits:%d, rx_slss_id:%d\n", psbch_e_rx_idx, slss_id);
|
||||
|
||||
nr_pbch_unscrambling(psbch_e_rx, slss_id, 0, 0, psbch_e_rx_idx,
|
||||
0, 0, 0, NULL);
|
||||
//polar decoding de-rate matching
|
||||
uint64_t tmp=0;
|
||||
decoderState = polar_decoder_int16(psbch_e_rx,(uint64_t *)&tmp,NULL,0,
|
||||
SL_NR_POLAR_PSBCH_MESSAGE_TYPE, SL_NR_POLAR_PSBCH_PAYLOAD_BITS, SL_NR_POLAR_PSBCH_AGGREGATION_LEVEL);
|
||||
|
||||
|
||||
uint32_t psbch_payload = tmp;
|
||||
|
||||
if(decoderState) {
|
||||
LOG_E(PHY,"%d:%d PSBCH RX: NOK \n",proc->frame_rx, proc->nr_slot_rx);
|
||||
return(decoderState);
|
||||
}
|
||||
|
||||
// Decoder reversal
|
||||
uint32_t a_reversed=0;
|
||||
|
||||
for (int i=0; i<SL_NR_POLAR_PSBCH_PAYLOAD_BITS; i++)
|
||||
a_reversed |= (((uint64_t)psbch_payload>>i)&1)<<(31-i);
|
||||
|
||||
psbch_payload = a_reversed;
|
||||
|
||||
*((uint32_t *)decoded_output) = psbch_payload;
|
||||
|
||||
#ifdef DEBUG_PSBCH
|
||||
for (int i=0; i<4; i++) {
|
||||
LOG_I(PHY, "decoded_output[%d]:%x\n", i, decoded_output[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
ue->symbol_offset = 0;
|
||||
|
||||
//retrieve DFN and slot number from SL-MIB
|
||||
uint32_t DFN = 0, slot_offset = 0;
|
||||
DFN = (((psbch_payload & 0x0700) >> 1) | ((psbch_payload & 0xFE0000) >> 17));
|
||||
slot_offset = (((psbch_payload & 0x010000) >> 10) | ((psbch_payload & 0xFC000000) >> 26));
|
||||
|
||||
LOG_D(PHY, "PSBCH RX SL-MIB:%x, decoded DFN:slot %d:%d, %x\n",psbch_payload, DFN, slot_offset, *(uint32_t *)decoded_output);
|
||||
|
||||
return 0;
|
||||
}
|
||||
381
openair1/PHY/NR_UE_TRANSPORT/nr_psbch_tx.c
Normal file
381
openair1/PHY/NR_UE_TRANSPORT/nr_psbch_tx.c
Normal file
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/LTE_REFSIG/lte_refsig.h"
|
||||
#include "PHY/NR_REFSIG/nr_mod_table.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h"
|
||||
|
||||
/*
|
||||
This function performs PSBCH SCrambling as described in 38.211.
|
||||
Input parameter "output" is scrambled and the scrambled output is stored in this parameter.
|
||||
id - SLSS ID used for C_INIT
|
||||
length is the length of the buffer.
|
||||
*/
|
||||
|
||||
//#define SL_DEBUG
|
||||
|
||||
void sl_psbch_scrambling(uint32_t *output, uint32_t id, uint16_t length)
|
||||
{
|
||||
uint32_t x1, x2, s=0;
|
||||
// x1 is set in lte_gold_generic
|
||||
x2 = id; // C_INIT
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("SIDELINK: Function %s\n", __func__);
|
||||
printf("Scrambling params: length %d id %d \n", length, id);
|
||||
#endif
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
for (int i=0; i<56;i++) {
|
||||
printf("\nBEFORE SCRAMBLING output[%d]:0x%x\n",i,output[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
// get initial 32 scrambing bits
|
||||
s = lte_gold_generic(&x1, &x2, 1);
|
||||
#ifdef SL_DEBUG
|
||||
printf("s: %04x\t", s);
|
||||
#endif
|
||||
|
||||
// scramble in 32bit chunks
|
||||
int i = 0;
|
||||
while(i+32 <= length) {
|
||||
|
||||
output[i>>5] ^= s;
|
||||
|
||||
i += 32;
|
||||
s = lte_gold_generic(&x1, &x2, 0);
|
||||
#ifdef SL_DEBUG
|
||||
printf("s: %04x\t", s);
|
||||
#endif
|
||||
}
|
||||
|
||||
// scramble remaining bits
|
||||
for (; i < length; ++i) {
|
||||
output[i>>5] ^= ((s>>(i&0x1f)&1)<<(i&0x1f));
|
||||
}
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
for (int i=0; i<56;i++) {
|
||||
printf("\nAFTER SCRAMBLING output[%d]:0x%x\n",i,output[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This function RE MAPS PSS, SSS sequences as described in 38.211.
|
||||
txF is the data in frequency domain, sync_seq = PSS or SSS seq
|
||||
startsym = 1 for PSS, 3 for SSS
|
||||
re_offset = sample which points to first RE + SSB start RE
|
||||
scaling factor = scaling factor used for PSS, SSS (determined according to PSBCH pwr)
|
||||
symbol size = OFDM symbol size used for RE Mapping
|
||||
*/
|
||||
void sl_map_pss_or_sss(struct complex16 *txF, int16_t *sync_seq, uint16_t startsym,
|
||||
uint16_t re_offset, uint16_t scaling_factor, uint16_t symbol_size)
|
||||
{
|
||||
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("%s. DEBUG PSBCH TX: RE MAPPING of PSS/SSS \n", __func__);
|
||||
printf("Input Params - StartSYM:%d, NUMSYM:%d, RE_OFFSET:%d, num_REs:%d, scaling_factor:%d, symbol_size:%d\n",
|
||||
startsym, SL_NR_NUM_PSS_OR_SSS_SYMBOLS,re_offset, SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL, scaling_factor, symbol_size);
|
||||
#endif
|
||||
|
||||
// RE Mapping of SL-PSS, SL-SSS
|
||||
for (int l = startsym;l < (startsym + SL_NR_NUM_PSS_OR_SSS_SYMBOLS);l++) {
|
||||
|
||||
int k = re_offset % symbol_size;
|
||||
int index = 0, offset = 0;
|
||||
|
||||
for (int m = 0;m < SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL;m++) {
|
||||
|
||||
offset = l*symbol_size + k;
|
||||
if ((m < 2) || (m >= (SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL - 3))) {
|
||||
txF[offset].r = 0; //Set REs 0,1,129,130,131 = 0
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("sym:%d, RE:%d, txF[%d]:%d.%d \n", l, m, offset, txF[offset].r,txF[offset].i);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
txF[offset].r = (sync_seq[index] * scaling_factor) >> 15;
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("sym:%d, RE:%d, txF[%d]:%d.%d, syncseq[%d]:%d \n", l, m, offset, txF[offset].r,txF[offset].i, index, sync_seq[index]);
|
||||
#endif
|
||||
|
||||
index++;
|
||||
}
|
||||
txF[offset].i = 0;
|
||||
k = (k + 1) % symbol_size;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This function Generates the PSBCH DATA Modulation symbols and RE MAPS PSBCH Modulated symbols
|
||||
and PSBCH DMRS sequences as described in 38.211.
|
||||
txF is the data in frequency domain
|
||||
payload is the PSBCH payload (SL-MIB given by higher layers)
|
||||
id - SLSS ID used for knowing which DMRS sequence to be used.
|
||||
Cp - NORMAL of extended Cyclic prefix
|
||||
startsym = 0 and then PSBCH is mapped from symbols 5-13 if normal , 5-11 if extended
|
||||
re_offset = sample which points to first RE + SSB start RE
|
||||
scaling factor = scaling factor used for PSS, SSS (determined according to PSBCH pwr)
|
||||
symbol size = OFDM symbol size used for RE Mapping
|
||||
*/
|
||||
|
||||
void sl_generate_and_map_psbch(struct complex16 *txF, uint32_t *payload, uint16_t id,
|
||||
uint16_t cp, uint16_t re_offset, uint16_t scaling_factor, uint16_t symbol_size,
|
||||
struct complex16 *psbch_dmrs)
|
||||
{
|
||||
|
||||
uint64_t psbch_a_reversed = 0;
|
||||
uint16_t num_psbch_modsym = 0, numsym = 0;
|
||||
uint8_t idx = 0;
|
||||
uint32_t encoder_output[SL_NR_POLAR_PSBCH_E_DWORD];
|
||||
struct complex16 psbch_modsym[SL_NR_NUM_PSBCH_MODULATED_SYMBOLS];
|
||||
|
||||
LOG_D(PHY, "PSBCH TX: Generation accg to 38.212, 38.211. SLSS id:%d\n", id);
|
||||
|
||||
// Encoder reversal
|
||||
for (int i=0; i<SL_NR_POLAR_PSBCH_PAYLOAD_BITS; i++)
|
||||
psbch_a_reversed |= (((uint64_t)*payload>>i)&1)<<(31-i);
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("DEBUG PSBCH TX: 38.212 PSBCH CRC + Channel coding (POLAR) + Rate Matching:\n");
|
||||
printf("PSBCH payload:%x, Reversed Payload:%016lx\n",*payload, psbch_a_reversed);
|
||||
#endif
|
||||
|
||||
/// CRC, coding and rate matching
|
||||
polar_encoder_fast(&psbch_a_reversed, (void*)encoder_output, NULL, 0, 0,
|
||||
SL_NR_POLAR_PSBCH_MESSAGE_TYPE,
|
||||
SL_NR_POLAR_PSBCH_PAYLOAD_BITS,
|
||||
SL_NR_POLAR_PSBCH_AGGREGATION_LEVEL);
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
for (int i=0; i<SL_NR_POLAR_PSBCH_E_DWORD; i++)
|
||||
printf("encoderoutput[%d]: 0x%08x\t", i, encoder_output[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
/// 38.211 Scrambling
|
||||
if (cp) { // EXT Cyclic prefix
|
||||
sl_psbch_scrambling(encoder_output, id, SL_NR_POLAR_PSBCH_E_EXT_CP); //for Extended Cyclic prefix
|
||||
num_psbch_modsym = SL_NR_POLAR_PSBCH_E_EXT_CP/2;
|
||||
numsym = SL_NR_NUM_SYMBOLS_SSB_EXT_CP;
|
||||
AssertFatal(1==0, "EXT CP is not yet supported\n");
|
||||
}
|
||||
else { // Normal CP
|
||||
sl_psbch_scrambling(encoder_output, id, SL_NR_POLAR_PSBCH_E_NORMAL_CP); //for Cyclic prefix
|
||||
num_psbch_modsym = SL_NR_POLAR_PSBCH_E_NORMAL_CP/2;
|
||||
numsym = SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP;
|
||||
}
|
||||
|
||||
LOG_D(PHY,"PSBCH TX: 38.211 Scrambling done. Number of bits:%d \n",
|
||||
SL_NR_POLAR_PSBCH_E_NORMAL_CP);
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("38211 STEP: PSBCH Scrambling \n");
|
||||
for (int i=0; i<SL_NR_POLAR_PSBCH_E_NORMAL_CP/32; i++)
|
||||
printf("Scrambleroutput[%d]: 0x%08x\t", i, encoder_output[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("SIDELINK PSBCH TX: 38211 STEP: QPSK Modulation of PSBCH symbols:%d, symbols in PSBCH:%d\n", num_psbch_modsym, numsym);
|
||||
#endif
|
||||
|
||||
/// 38.211 QPSK modulation
|
||||
for (int j=0; j<num_psbch_modsym; j++) {
|
||||
idx = ((encoder_output[(j<<1)>>5]>>((j<<1)&0x1f))&3);
|
||||
psbch_modsym[j].r = nr_qpsk_mod_table[2*idx];
|
||||
psbch_modsym[j].i = nr_qpsk_mod_table[(2*idx)+1];
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("idx %d, psbch_modsym[%d]-r:%d, i:%d\n", idx, j, psbch_modsym[j].r, psbch_modsym[j].i);
|
||||
#endif
|
||||
}
|
||||
|
||||
// RE MApping of PSBCH and PSBCH DMRS
|
||||
int index = 0, dmrs_index = 0;
|
||||
const int numre=SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL;
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
LOG_M("sl_psbch_data_symbols.m", "psbch_sym", (void*)psbch_modsym, num_psbch_modsym, 1, 1);
|
||||
LOG_M("sl_psbch_dmrs_symbols.m", "psbch_dmrs", (void*)psbch_dmrs, SL_NR_NUM_PSBCH_DMRS_RE, 1, 1);
|
||||
#endif
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("\nMapping Sidelink PSBCH DMRS, PSBCH modulation symbols to 132 REs\n");
|
||||
#endif
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("%s. DEBUG PSBCH TX: RE MAPPING of PSBCH DATA AND DMRS \n", __func__);
|
||||
printf("Input Params - StartSYM:%d, NUMSYM:%d, RE_OFFSET:%d, num_REs:%d, scaling_factor:%d, symbol_size:%d\n",
|
||||
0, numsym,re_offset, numre, scaling_factor, symbol_size);
|
||||
#endif
|
||||
|
||||
for (int l=0;l < numsym;) {
|
||||
|
||||
int k = re_offset % symbol_size;
|
||||
int symbol_offset = l*symbol_size;
|
||||
int offset = 0;
|
||||
|
||||
for (int m=0; m < numre;m++) {
|
||||
|
||||
// Maps PSBCH DMRS in every 4th RE ex:0,4,....128
|
||||
// Maps PSBCH in all other REs ex: 1,2,3,5,6,...127,129,130,131
|
||||
|
||||
offset = symbol_offset + k;
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("symbol:%d, symbol_offset:%d, k:%d, re:%d, sampleoffset:%d ", l, symbol_offset, k, m, offset);
|
||||
#endif
|
||||
|
||||
if (m % 4 == 0) {
|
||||
txF[offset].r = (psbch_dmrs[dmrs_index].r * scaling_factor) >> 15;
|
||||
txF[offset].i = (psbch_dmrs[dmrs_index].i * scaling_factor) >> 15;
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("txF[%d]:%d,%d, psbch_dmrs[%d]:%d,%d ", offset, txF[offset].r,
|
||||
txF[offset].i, dmrs_index, psbch_dmrs[dmrs_index].r, psbch_dmrs[dmrs_index].i);
|
||||
#endif
|
||||
|
||||
dmrs_index++;
|
||||
|
||||
} else {
|
||||
txF[offset].r = (psbch_modsym[index].r * scaling_factor) >> 15;
|
||||
txF[offset].i = (psbch_modsym[index].i * scaling_factor) >> 15;
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("txF[%d]:%d,%d, psbch_modsym[%d]:%d,%d\n", offset, txF[offset].r,
|
||||
txF[offset].i, index ,psbch_modsym[index].r, psbch_modsym[index].i);
|
||||
#endif
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
k = (k + 1) % symbol_size;
|
||||
}
|
||||
|
||||
LOG_D(PHY, "PSBCH TX: 38211 STEP: RE MAPPING OF PSBCH, PSBCH DMRS DONE. symbol:%d, first RE offset:%d, Last RE offset:%d, Num PSBCH DATA REs:%d, Num PSBCH DMRS REs:%d\n",
|
||||
l, symbol_offset+re_offset, offset, index, dmrs_index);
|
||||
|
||||
l = (l == 0) ? 5: l+1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This function prepares the PSBCH block and RE MAPS PSS, SSS, PSBCH DATA, PSBCH DMRS into buffer txF.
|
||||
Called by the L1 Scheduler when MAC triggers PHY to send PSBCH
|
||||
UE is the UE context.
|
||||
frame, slot points to the TTI in which PSBCH TX will be transmitted
|
||||
*/
|
||||
void nr_tx_psbch(PHY_VARS_NR_UE *UE, uint32_t frame_tx,
|
||||
uint32_t slot_tx,
|
||||
sl_nr_tx_config_psbch_pdu_t *psbch_vars,
|
||||
c16_t **txdataF)
|
||||
{
|
||||
|
||||
sl_nr_ue_phy_params_t *sl_ue_phy_params = &UE->SL_UE_PHY_PARAMS;
|
||||
uint16_t slss_id = psbch_vars->tx_slss_id;
|
||||
NR_DL_FRAME_PARMS *sl_fp = &sl_ue_phy_params->sl_frame_params;
|
||||
uint32_t psbch_payload = *((uint32_t *)psbch_vars->psbch_payload);
|
||||
|
||||
LOG_D(PHY,"PSBCH TX: slss-id %d, psbch payload %x \n", slss_id, psbch_payload);
|
||||
|
||||
// Insert FN and Slot number into SL-MIB
|
||||
uint32_t mask = ~(0x700 | 0xFE0000 | 0x10000 | 0xFC000000);
|
||||
psbch_payload &= mask;
|
||||
psbch_payload |= ((frame_tx%1024)<<1) & 0x700;
|
||||
psbch_payload |= ((frame_tx%1024)<<17) & 0xFE0000;
|
||||
psbch_payload |= (slot_tx<<10) & 0x10000;
|
||||
psbch_payload |= (slot_tx<<26) & 0xFC000000;
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("DEBUG PSBCH TX: DFN, SLOT included. psbch_a :0x%08x, frame:%d, slot:%d\n",
|
||||
psbch_payload, frame_tx, slot_tx);
|
||||
#endif
|
||||
|
||||
LOG_D(PHY,"PSBCH TX: Frame.Slot %d.%d. Payload::0x%08x, slssid:%d\n",
|
||||
frame_tx, slot_tx, psbch_payload, slss_id);
|
||||
|
||||
// GENERATE Sidelink PSS,SSS Sequences, PSBCH DMRS Symbols, PSBCH Symbols
|
||||
int16_t *sl_pss = &sl_ue_phy_params->init_params.sl_pss[slss_id/336][0];
|
||||
int16_t *sl_sss = &sl_ue_phy_params->init_params.sl_sss[slss_id][0];
|
||||
|
||||
uint16_t re_offset = sl_fp->first_carrier_offset + sl_fp->ssb_start_subcarrier;
|
||||
uint16_t symbol_size = sl_fp->ofdm_symbol_size;
|
||||
// TBD: Need to be replaced by function which calculates scaling factor based on psbch tx power
|
||||
uint16_t scaling_factor = AMP;
|
||||
|
||||
struct complex16 *txF = &txdataF[0][0];
|
||||
uint16_t startsym = SL_NR_PSS_START_SYMBOL;
|
||||
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("DEBUG PSBCH TX: MAP PSS. startsym:%d, PSS RE START:%d, scaling factor:%d\n",
|
||||
startsym, re_offset, scaling_factor);
|
||||
#endif
|
||||
sl_map_pss_or_sss(txF, sl_pss, startsym, re_offset, scaling_factor, symbol_size); // PSS
|
||||
|
||||
|
||||
startsym += SL_NR_NUM_PSS_SYMBOLS;
|
||||
#ifdef SL_DEBUG
|
||||
printf("DEBUG PSBCH TX: MAP SSS. startsym:%d, SSS RE START:%d, scaling factor:%d\n",
|
||||
startsym, re_offset, scaling_factor);
|
||||
#endif
|
||||
sl_map_pss_or_sss(txF, sl_sss, startsym, re_offset, scaling_factor, symbol_size); // SSS
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("DEBUG PSBCH TX: MAP PSBCH DATA AND DMRS. cyclicPrefix:%d, PSS RE START:%d, scaling factor:%d\n",
|
||||
sl_fp->Ncp, re_offset, scaling_factor);
|
||||
#endif
|
||||
|
||||
struct complex16 *psbch_dmrs = &sl_ue_phy_params->init_params.psbch_dmrs_modsym[slss_id][0];
|
||||
|
||||
sl_generate_and_map_psbch(txF, &psbch_payload, slss_id,
|
||||
sl_fp->Ncp, re_offset, scaling_factor, symbol_size,
|
||||
psbch_dmrs);
|
||||
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("DEBUG PSBCH TX: txdataF Prepared\n");
|
||||
#endif
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
LOG_M("sl_psbch_block.m", "sl_txF", (void*)txdataF[0], symbol_size*14, 1, 1);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
75
openair1/PHY/NR_UE_TRANSPORT/nr_pscch_tx.c
Normal file
75
openair1/PHY/NR_UE_TRANSPORT/nr_pscch_tx.c
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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 PHY/NR_UE_TRANSPORT/nr_pscch_tx.c
|
||||
* \brief Top-level routines for generating and decoding the PSCCH physical channel
|
||||
* \author R. Knopp
|
||||
* \date 2023
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email:
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
//#include "PHY/defs.h"
|
||||
#include "PHY/impl_defs_nr.h"
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
//#include "PHY/extern.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/pucch_nr.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
#include <openair1/PHY/CODING/nrSmallBlock/nr_small_block_defs.h>
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
|
||||
#include "T.h"
|
||||
|
||||
uint32_t nr_generate_dci(void *gNB, PHY_VARS_NR_UE *ue,
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
|
||||
int32_t *txdataF,
|
||||
int16_t amp,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
int slot);
|
||||
|
||||
uint32_t nr_generate_sci1(const PHY_VARS_NR_UE *ue,
|
||||
c16_t *txdataF,
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
const int16_t amp,
|
||||
const int nr_slot_tx,
|
||||
const sl_nr_tx_config_pscch_pssch_pdu_t *pscch_pssch_pdu)
|
||||
{
|
||||
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t pdcch_pdu_rel15={0};
|
||||
// for SCI we put the startRB and number of RBs for PSCCH in the first 2 FAPI FreqDomainResource fields
|
||||
pdcch_pdu_rel15.FreqDomainResource[0] = pscch_pssch_pdu->startrb;
|
||||
pdcch_pdu_rel15.FreqDomainResource[1] = pscch_pssch_pdu->pscch_numrbs;
|
||||
pdcch_pdu_rel15.StartSymbolIndex = 1;
|
||||
pdcch_pdu_rel15.DurationSymbols = pscch_pssch_pdu->pscch_numsym;
|
||||
pdcch_pdu_rel15.numDlDci = 1;
|
||||
pdcch_pdu_rel15.dci_pdu[0].ScramblingId = pscch_pssch_pdu->pscch_dmrs_scrambling_id;
|
||||
pdcch_pdu_rel15.dci_pdu[0].PayloadSizeBits = pscch_pssch_pdu->pscch_sci_payload_len;
|
||||
// for SCI we put the number of PRBs in the FAPI AggregationLevel field
|
||||
pdcch_pdu_rel15.dci_pdu[0].AggregationLevel = pscch_pssch_pdu->pscch_numrbs*pscch_pssch_pdu->pscch_numsym;
|
||||
pdcch_pdu_rel15.dci_pdu[0].ScramblingRNTI = 1010;
|
||||
*(uint64_t*)pdcch_pdu_rel15.dci_pdu[0].Payload = *(uint64_t *)pscch_pssch_pdu->pscch_sci_payload;
|
||||
return(nr_generate_dci(NULL,(PHY_VARS_NR_UE *)ue,&pdcch_pdu_rel15,(int32_t *)txdataF,amp,(NR_DL_FRAME_PARMS*)frame_parms,nr_slot_tx));
|
||||
}
|
||||
70
openair1/PHY/NR_UE_TRANSPORT/nr_psfch_tx.c
Normal file
70
openair1/PHY/NR_UE_TRANSPORT/nr_psfch_tx.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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 PHY/NR_UE_TRANSPORT/pucch_nr.c
|
||||
* \brief Top-level routines for generating and decoding the PSFCH physical channel
|
||||
* \author R. Knopp
|
||||
* \date 2023
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email:
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
//#include "PHY/defs.h"
|
||||
#include "PHY/impl_defs_nr.h"
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
//#include "PHY/extern.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/pucch_nr.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
#include <openair1/PHY/CODING/nrSmallBlock/nr_small_block_defs.h>
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
|
||||
#include "T.h"
|
||||
|
||||
|
||||
void nr_generate_psfch0(const PHY_VARS_NR_UE *ue,
|
||||
c16_t **txdataF,
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
const int16_t amp,
|
||||
const int nr_slot_tx,
|
||||
const sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu)
|
||||
{
|
||||
|
||||
fapi_nr_ul_config_pucch_pdu pucch_pdu;
|
||||
|
||||
pucch_pdu.start_symbol_index = psfch_pdu->start_symbol_index;
|
||||
pucch_pdu.hopping_id = psfch_pdu->hopping_id;
|
||||
pucch_pdu.prb_start = psfch_pdu->prb;
|
||||
pucch_pdu.initial_cyclic_shift = psfch_pdu->initial_cyclic_shift;
|
||||
pucch_pdu.mcs = psfch_pdu->mcs;
|
||||
pucch_pdu.nr_of_symbols = psfch_pdu->nr_of_symbols;
|
||||
pucch_pdu.n_bit = psfch_pdu->bit_len_harq;
|
||||
pucch_pdu.bwp_start = psfch_pdu->sl_bwp_start;
|
||||
pucch_pdu.freq_hop_flag = psfch_pdu->freq_hop_flag;
|
||||
pucch_pdu.group_hop_flag = psfch_pdu->group_hop_flag;
|
||||
pucch_pdu.second_hop_prb = psfch_pdu->second_hop_prb;
|
||||
pucch_pdu.sequence_hop_flag = psfch_pdu->sequence_hop_flag;
|
||||
nr_generate_pucch0(ue, txdataF, frame_parms, amp, nr_slot_tx, &pucch_pdu);
|
||||
}
|
||||
@@ -41,6 +41,9 @@
|
||||
#define NR_PUSCH_x 2 // UCI placeholder bit TS 38.212 V15.4.0 subclause 5.3.3.1
|
||||
#define NR_PUSCH_y 3 // UCI placeholder bit
|
||||
|
||||
// Additional memory allocation, because of applying the filter and the memory offset to ensure memory alignment
|
||||
#define FILTER_MARGIN 32
|
||||
|
||||
// Functions below implement 36-211 and 36-212
|
||||
|
||||
/** @addtogroup _PHY_TRANSPORT_
|
||||
@@ -211,6 +214,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
|
||||
int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
||||
NR_UE_ULSCH_t *ulsch,
|
||||
sl_nr_tx_config_pscch_pssch_pdu_t *pscch_pssch_pdu,
|
||||
NR_DL_FRAME_PARMS* frame_parms,
|
||||
uint8_t harq_pid,
|
||||
unsigned int G);
|
||||
@@ -252,7 +256,7 @@ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE,
|
||||
const uint8_t slot,
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
const uint8_t n_antenna_ports,
|
||||
c16_t **txdataF);
|
||||
c16_t **txdataF, uint32_t linktype);
|
||||
|
||||
int8_t clean_UE_ulsch(PHY_VARS_NR_UE *UE, uint8_t gNB_id);
|
||||
|
||||
@@ -264,6 +268,7 @@ void nr_dlsch_unscrambling(int16_t* llr,
|
||||
|
||||
int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int pscch_flag,
|
||||
int32_t pdcch_est_size,
|
||||
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
|
||||
int16_t *pdcch_e_rx,
|
||||
@@ -362,13 +367,15 @@ void nr_pdcch_unscrambling(int16_t *z,
|
||||
uint16_t scrambling_RNTI,
|
||||
uint32_t length,
|
||||
uint16_t pdcch_DMRS_scrambling_id,
|
||||
int16_t *z2);
|
||||
int16_t *z2,int sci_flag);
|
||||
|
||||
uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int pscch_flag,
|
||||
int16_t *pdcch_e_rx,
|
||||
fapi_nr_dci_indication_t *dci_ind,
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15);
|
||||
void *ind,
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15,
|
||||
int16_t *rsrp_dBm);
|
||||
|
||||
|
||||
/** \brief This function is the top-level entry point to PDSCH demodulation, after frequency-domain transformation and channel estimation. It performs
|
||||
@@ -410,6 +417,57 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t
|
||||
|
||||
void dump_nrdlsch(PHY_VARS_NR_UE *ue,uint8_t gNB_id,uint8_t nr_slot_rx,unsigned int *coded_bits_per_codeword,int round, unsigned char harq_pid);
|
||||
void nr_a_sum_b(c16_t *input_x, c16_t *input_y, unsigned short nb_rb);
|
||||
|
||||
int nr_rx_psbch(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t *decoded_output,
|
||||
c16_t rxdataF[][frame_parms->samples_per_slot_wCP],
|
||||
uint16_t slss_id);
|
||||
|
||||
void nr_tx_psbch(PHY_VARS_NR_UE *UE, uint32_t frame_tx, uint32_t slot_tx,
|
||||
sl_nr_tx_config_psbch_pdu_t *psbch_vars,
|
||||
c16_t **txdataF);
|
||||
|
||||
int sl_nr_slss_search(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc, int num_frames);
|
||||
|
||||
uint32_t nr_generate_sci1(const PHY_VARS_NR_UE *ue,
|
||||
c16_t *txdataF,
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
const int16_t amp,
|
||||
const int nr_slot_tx,
|
||||
const sl_nr_tx_config_pscch_pssch_pdu_t *pscch_pssch_pdu);
|
||||
|
||||
void nr_generate_psfch0(const PHY_VARS_NR_UE *ue,
|
||||
c16_t **txdataF,
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
const int16_t amp,
|
||||
const int nr_slot_tx,
|
||||
const sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu);
|
||||
|
||||
int8_t nr_ue_decode_pucch0(PHY_VARS_NR_UE *ue,
|
||||
int frame,
|
||||
int slot,
|
||||
c16_t rxdataF[][ue->SL_UE_PHY_PARAMS.sl_frame_params.samples_per_slot_wCP],
|
||||
nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu,
|
||||
nfapi_nr_pucch_pdu_t *pucch_pdu);
|
||||
|
||||
int8_t nr_ue_decode_psfch0(PHY_VARS_NR_UE *ue,
|
||||
int frame,
|
||||
int slot,
|
||||
c16_t rxdataF[][ue->SL_UE_PHY_PARAMS.sl_frame_params.samples_per_slot_wCP],
|
||||
const sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu);
|
||||
|
||||
int nr_csi_rs_sinr_estimation(const PHY_VARS_NR_UE *ue,
|
||||
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
|
||||
const uint8_t N_ports,
|
||||
uint8_t mem_offset,
|
||||
const int32_t csi_rs_estimated_channel_freq[][N_ports][ue->frame_parms.ofdm_symbol_size + FILTER_MARGIN],
|
||||
const uint32_t interference_plus_noise_power,
|
||||
const int16_t log2_re,
|
||||
int32_t *precoded_sinr_dB);
|
||||
/**@}*/
|
||||
#endif
|
||||
|
||||
|
||||
337
openair1/PHY/NR_UE_TRANSPORT/nr_ue_pucch_rx.c
Normal file
337
openair1/PHY/NR_UE_TRANSPORT/nr_ue_pucch_rx.c
Normal file
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
* 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 PHY/NR_TRANSPORT/pucch_rx.c
|
||||
* \brief Top-level routines for decoding the PUCCH physical channel
|
||||
* \author A. Mico Pereperez, Padarthi Naga Prasanth, Francesco Mani, Raymond Knopp
|
||||
* \date 2020
|
||||
* \version 0.2
|
||||
* \company Eurecom
|
||||
* \email:
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
#include<stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "PHY/impl_defs_nr.h"
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/sse_intrin.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/pucch_nr.h"
|
||||
#include <openair1/PHY/CODING/nrSmallBlock/nr_small_block_defs.h>
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/NR_REFSIG/nr_refsig.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
#include "T.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
|
||||
//#define DEBUG_NR_PUCCH_RX 1
|
||||
|
||||
int get_pucch0_cs_lut_index(PHY_VARS_NR_UE *ue, nfapi_nr_pucch_pdu_t* pucch_pdu) {
|
||||
|
||||
int i = 0;
|
||||
|
||||
#ifdef DEBUG_NR_PUCCH_RX
|
||||
LOG_I(NR_PHY, "getting index for LUT with %d entries, Nid %d\n", ue->pucch0_lut.nb_id, pucch_pdu->hopping_id);
|
||||
#endif
|
||||
|
||||
for (i=0; i<ue->pucch0_lut.nb_id; i++) {
|
||||
if (ue->pucch0_lut.Nid[i] == pucch_pdu->hopping_id) break;
|
||||
}
|
||||
#ifdef DEBUG_NR_PUCCH_RX
|
||||
LOG_I(NR_PHY, "found index %d\n", i);
|
||||
#endif
|
||||
if (i < ue->pucch0_lut.nb_id) return(i);
|
||||
|
||||
#ifdef DEBUG_NR_PUCCH_RX
|
||||
LOG_I(NR_PHY, "Initializing PUCCH0 LUT index %i with Nid %d\n", i, pucch_pdu->hopping_id);
|
||||
#endif
|
||||
// initialize
|
||||
ue->pucch0_lut.Nid[ue->pucch0_lut.nb_id] = pucch_pdu->hopping_id;
|
||||
for (int slot=0; slot<10<<pucch_pdu->subcarrier_spacing; slot++)
|
||||
for (int symbol=0; symbol<14; symbol++)
|
||||
ue->pucch0_lut.lut[ue->pucch0_lut.nb_id][slot][symbol] = (int)floor(nr_cyclic_shift_hopping(pucch_pdu->hopping_id, 0, 0, 0, symbol, slot) / 0.5235987756);
|
||||
ue->pucch0_lut.nb_id++;
|
||||
return(ue->pucch0_lut.nb_id-1);
|
||||
}
|
||||
|
||||
int8_t nr_ue_decode_psfch0(PHY_VARS_NR_UE *ue,
|
||||
int frame,
|
||||
int slot,
|
||||
c16_t rxdataF[][ue->SL_UE_PHY_PARAMS.sl_frame_params.samples_per_slot_wCP],
|
||||
const sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu) {
|
||||
int8_t ack_nack_rcvd = -1;
|
||||
nfapi_nr_pucch_pdu_t pucch_pdu;
|
||||
pucch_pdu.freq_hop_flag = psfch_pdu->freq_hop_flag;
|
||||
pucch_pdu.group_hop_flag = psfch_pdu->group_hop_flag;
|
||||
pucch_pdu.sequence_hop_flag = psfch_pdu->sequence_hop_flag;
|
||||
pucch_pdu.second_hop_prb = psfch_pdu->second_hop_prb;
|
||||
pucch_pdu.nr_of_symbols = psfch_pdu->nr_of_symbols;
|
||||
pucch_pdu.start_symbol_index = psfch_pdu->start_symbol_index;
|
||||
pucch_pdu.hopping_id = psfch_pdu->hopping_id;
|
||||
pucch_pdu.prb_start = psfch_pdu->prb;
|
||||
pucch_pdu.prb_size = 1;
|
||||
pucch_pdu.bwp_start = psfch_pdu->sl_bwp_start;
|
||||
pucch_pdu.initial_cyclic_shift = psfch_pdu->initial_cyclic_shift;
|
||||
pucch_pdu.bit_len_harq = psfch_pdu->bit_len_harq;
|
||||
pucch_pdu.sr_flag = 0;
|
||||
pucch_pdu.subcarrier_spacing = 1;
|
||||
ack_nack_rcvd = nr_ue_decode_pucch0(ue,
|
||||
frame,
|
||||
slot,
|
||||
rxdataF,
|
||||
NULL,
|
||||
&pucch_pdu);
|
||||
return ack_nack_rcvd;
|
||||
}
|
||||
|
||||
int8_t nr_ue_decode_pucch0(PHY_VARS_NR_UE *ue,
|
||||
int frame,
|
||||
int slot,
|
||||
c16_t rxdataF[][ue->SL_UE_PHY_PARAMS.sl_frame_params.samples_per_slot_wCP],
|
||||
nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu,
|
||||
nfapi_nr_pucch_pdu_t *pucch_pdu)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *frame_parms = get_softmodem_params()->sl_mode ? &ue->SL_UE_PHY_PARAMS.sl_frame_params : &ue->frame_parms;
|
||||
|
||||
int soffset = 0;
|
||||
int nr_sequences;
|
||||
const uint8_t *mcs;
|
||||
AssertFatal(pucch_pdu->sr_flag == 0, "SR flag MUST be 0 in SL\n");
|
||||
AssertFatal(pucch_pdu->bit_len_harq == 0 || pucch_pdu->bit_len_harq == 1, "Invalid value for bit_len_harq %d\n", pucch_pdu->bit_len_harq);
|
||||
if(pucch_pdu->bit_len_harq == 0){
|
||||
mcs = table1_mcs;
|
||||
nr_sequences = 1;
|
||||
}
|
||||
else if(pucch_pdu->bit_len_harq == 1){
|
||||
mcs = table1_mcs;
|
||||
nr_sequences = 4 >> 1;
|
||||
}
|
||||
|
||||
AssertFatal(nr_sequences == 1 || nr_sequences == 2, "nr_sequences must be either 1 or 2, nr_sequences %d\n", nr_sequences);
|
||||
|
||||
LOG_D(PHY, "%s pucch0: nr_symbols %d, start_symbol %d, prb_start %d, second_hop_prb %d, group_hop_flag %d, sequence_hop_flag %d, O_ACK %d, O_SR %d, mcs %d, initial_cyclic_shift %d, subcarrier_spacing %d\n",
|
||||
__FUNCTION__,
|
||||
pucch_pdu->nr_of_symbols,
|
||||
pucch_pdu->start_symbol_index,
|
||||
pucch_pdu->prb_start,
|
||||
pucch_pdu->second_hop_prb,
|
||||
pucch_pdu->group_hop_flag,
|
||||
pucch_pdu->sequence_hop_flag,
|
||||
pucch_pdu->bit_len_harq,
|
||||
pucch_pdu->sr_flag,
|
||||
mcs[0],
|
||||
pucch_pdu->initial_cyclic_shift,
|
||||
pucch_pdu->subcarrier_spacing);
|
||||
|
||||
int cs_ind = get_pucch0_cs_lut_index(ue, pucch_pdu);
|
||||
/*
|
||||
* Implement TS 38.211 Subclause 6.3.2.3.1 Sequence generation
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2
|
||||
*/
|
||||
/*
|
||||
* in TS 38.213 Subclause 9.2.1 it is said that:
|
||||
* for PUCCH format 0 or PUCCH format 1, the index of the cyclic shift
|
||||
* is indicated by higher layer parameter PUCCH-F0-F1-initial-cyclic-shift
|
||||
*/
|
||||
|
||||
/*
|
||||
* Implementing TS 38.211 Subclause 6.3.2.3.1, the sequence x(n) shall be generated according to:
|
||||
* x(l*12+n) = r_u_v_alpha_delta(n)
|
||||
*/
|
||||
// the value of u,v (delta always 0 for PUCCH) has to be calculated according to TS 38.211 Subclause 6.3.2.2.1
|
||||
uint8_t u[2] = {0}, v[2] = {0};
|
||||
|
||||
// // x_n contains the sequence r_u_v_alpha_delta(n)
|
||||
int n, i;
|
||||
int prb_offset[2] = {pucch_pdu->bwp_start + pucch_pdu->prb_start, pucch_pdu->bwp_start + pucch_pdu->prb_start};
|
||||
|
||||
pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag << 1);
|
||||
nr_group_sequence_hopping(pucch_GroupHopping,
|
||||
pucch_pdu->hopping_id,
|
||||
0,
|
||||
slot,
|
||||
&u[0],
|
||||
&v[0]); // calculating u and v value first hop
|
||||
LOG_D(PHY, "pucch0: u %d, v %d\n", u[0], v[0]);
|
||||
|
||||
if (pucch_pdu->freq_hop_flag == 1) {
|
||||
nr_group_sequence_hopping(pucch_GroupHopping,
|
||||
pucch_pdu->hopping_id,
|
||||
1,
|
||||
slot,
|
||||
&u[1],
|
||||
&v[1]); // calculating u and v value second hop
|
||||
LOG_D(PHY, "pucch0 second hop: u %d, v %d\n", u[1], v[1]);
|
||||
prb_offset[1] = pucch_pdu->bwp_start + pucch_pdu->second_hop_prb;
|
||||
}
|
||||
|
||||
AssertFatal(pucch_pdu->nr_of_symbols < 3, "nr_of_symbols %d not allowed\n", pucch_pdu->nr_of_symbols);
|
||||
uint32_t re_offset[2] = {0};
|
||||
|
||||
const int16_t *x_re[2], *x_im[2];
|
||||
x_re[0] = table_5_2_2_2_2_Re[u[0]];
|
||||
x_im[0] = table_5_2_2_2_2_Im[u[0]];
|
||||
x_re[1] = table_5_2_2_2_2_Re[u[1]];
|
||||
x_im[1] = table_5_2_2_2_2_Im[u[1]];
|
||||
|
||||
c64_t xr[frame_parms->nb_antennas_rx][pucch_pdu->nr_of_symbols][12] __attribute__((aligned(32)));
|
||||
int64_t xrtmag = 0, xrtmag_next = 0;
|
||||
uint8_t maxpos = 0;
|
||||
uint8_t index = 0;
|
||||
LOG_D(NR_PHY, "prb_size %d\n", pucch_pdu->prb_size);
|
||||
int nb_re_pucch = 12*pucch_pdu->prb_size; // prb size is 1
|
||||
int32_t rp[frame_parms->nb_antennas_rx][pucch_pdu->nr_of_symbols][nb_re_pucch];
|
||||
memset(rp, 0, sizeof(rp));
|
||||
int32_t *tmp_rp = NULL;
|
||||
|
||||
for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
|
||||
uint8_t l2 = l + pucch_pdu->start_symbol_index;
|
||||
|
||||
re_offset[l] = (12 * prb_offset[l]) + frame_parms->first_carrier_offset;
|
||||
if (re_offset[l] >= frame_parms->ofdm_symbol_size)
|
||||
re_offset[l] -= frame_parms->ofdm_symbol_size;
|
||||
|
||||
for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) {
|
||||
LOG_D(NR_PHY, "soffset %i, soffset + l2*frame_parms->ofdm_symbol_size %i %i re_offset[%d] %i\n",
|
||||
soffset, soffset + l2*frame_parms->ofdm_symbol_size,
|
||||
(soffset + l2*frame_parms->ofdm_symbol_size + nb_re_pucch), l, re_offset[l]);
|
||||
for (int z = soffset + l2*frame_parms->ofdm_symbol_size + re_offset[l]; z < (soffset + l2*frame_parms->ofdm_symbol_size + re_offset[l] + nb_re_pucch); z++)
|
||||
LOG_D(NR_PHY, "%4d.%2d z %d rxdataF (%d,%d)\n", frame, slot, z, rxdataF[aa][z].r, rxdataF[aa][z].i);
|
||||
tmp_rp = (int32_t *)&rxdataF[aa][soffset + l2 * frame_parms->ofdm_symbol_size];
|
||||
if(re_offset[l] + nb_re_pucch > frame_parms->ofdm_symbol_size) {
|
||||
int neg_length = frame_parms->ofdm_symbol_size - re_offset[l];
|
||||
int pos_length = nb_re_pucch - neg_length;
|
||||
memcpy1((void*)rp[aa][l], (void*)&tmp_rp[re_offset[l]], neg_length*sizeof(int32_t));
|
||||
memcpy1((void*)&rp[aa][l][neg_length], (void*)tmp_rp, pos_length*sizeof(int32_t));
|
||||
}
|
||||
else
|
||||
memcpy1((void*)rp[aa][l], (void*)&tmp_rp[re_offset[l]], nb_re_pucch*sizeof(int32_t));
|
||||
|
||||
c16_t *r = (c16_t*)&rp[aa][l];
|
||||
|
||||
for (n=0; n<nb_re_pucch; n++) {
|
||||
xr[aa][l][n].r = (int32_t)x_re[l][n] * r[n].r + (int32_t)x_im[l][n] * r[n].i;
|
||||
xr[aa][l][n].i = (int32_t)x_re[l][n] * r[n].i - (int32_t)x_im[l][n] * r[n].r;
|
||||
#ifdef DEBUG_NR_PUCCH_RX
|
||||
LOG_I(NR_PHY, "x (%d,%d), r%d.%d (%d,%d), xr (%lld,%lld)\n",
|
||||
x_re[l][n], x_im[l][n], l2, re_offset[l], r[n].r, r[n].i, xr[aa][l][n].r, xr[aa][l][n].i);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int seq_index = 0;
|
||||
int64_t temp;
|
||||
|
||||
for(i=0; i<nr_sequences; i++) {
|
||||
c64_t corr[frame_parms->nb_antennas_rx][2];
|
||||
for (int aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
||||
for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
|
||||
seq_index = (pucch_pdu->initial_cyclic_shift+
|
||||
mcs[i]+
|
||||
ue->pucch0_lut.lut[cs_ind][slot][l+pucch_pdu->start_symbol_index])%12;
|
||||
#ifdef DEBUG_NR_PUCCH_RX
|
||||
LOG_I(NR_PHY, "PUCCH symbol %d seq %d, seq_index %d, mcs %d , slot %d, cs_ind %d\n",
|
||||
l, i, seq_index, mcs[i], slot, cs_ind);
|
||||
#endif
|
||||
corr[aa][l] = (c64_t){0};
|
||||
for (n = 0; n < 12; n++) {
|
||||
corr[aa][l].r += xr[aa][l][n].r * idft12_re[seq_index][n] + xr[aa][l][n].i * idft12_im[seq_index][n];
|
||||
corr[aa][l].i += xr[aa][l][n].r * idft12_im[seq_index][n] - xr[aa][l][n].i * idft12_re[seq_index][n];
|
||||
}
|
||||
corr[aa][l].r >>= 31;
|
||||
corr[aa][l].i >>= 31;
|
||||
}
|
||||
}
|
||||
LOG_D(PHY,"PUCCH IDFT[%d/%d] = (%ld,%ld)=>%f\n",
|
||||
mcs[i], seq_index, corr[0][0].r, corr[0][0].i,
|
||||
10*log10((double)squaredMod(corr[0][0])));
|
||||
if (pucch_pdu->nr_of_symbols == 2)
|
||||
LOG_D(PHY,"PUCCH 2nd symbol IDFT[%d/%d] = (%ld,%ld)=>%f\n",
|
||||
mcs[i], seq_index, corr[0][1].r, corr[0][1].i,
|
||||
10*log10((double)squaredMod(corr[0][1])));
|
||||
if (pucch_pdu->freq_hop_flag == 0) {
|
||||
if (pucch_pdu->nr_of_symbols == 1) {// non-coherent correlation
|
||||
temp = 0;
|
||||
for (int aa=0; aa<frame_parms->nb_antennas_rx; aa++)
|
||||
temp += squaredMod(corr[aa][0]);
|
||||
} else {
|
||||
temp = 0;
|
||||
for (int aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
||||
c64_t corr2;
|
||||
csum(corr2, corr[aa][0], corr[aa][1]);
|
||||
// coherent combining of 2 symbols and then complex modulus for single-frequency case
|
||||
temp += corr2.r*corr2.r + corr2.i*corr2.i;
|
||||
}
|
||||
}
|
||||
} else if (pucch_pdu->freq_hop_flag == 1) {
|
||||
// full non-coherent combining of 2 symbols for frequency-hopping case
|
||||
temp = 0;
|
||||
for (int aa=0; aa<frame_parms->nb_antennas_rx; aa++)
|
||||
temp += squaredMod(corr[aa][0]) + squaredMod(corr[aa][1]);
|
||||
}
|
||||
else AssertFatal(1==0,"shouldn't happen\n");
|
||||
LOG_D(PHY, "Sequence %d temp %ld vs. xrtmag %ld xrtmag_next %ld, slot %d rx atnennas %u\n",
|
||||
i, temp, xrtmag, xrtmag_next, slot, frame_parms->nb_antennas_rx);
|
||||
if (temp > xrtmag) {
|
||||
xrtmag_next = xrtmag;
|
||||
xrtmag = temp;
|
||||
LOG_D(PHY,"Sequence %d xrtmag %ld xrtmag_next %ld, slot %d\n", i, xrtmag, xrtmag_next, slot);
|
||||
maxpos = i;
|
||||
int64_t temp2 = 0,temp3 = 0;;
|
||||
for (int aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
||||
temp2 += squaredMod(corr[aa][0]);
|
||||
if (pucch_pdu->nr_of_symbols == 2)
|
||||
temp3 += squaredMod(corr[aa][1]);
|
||||
}
|
||||
}
|
||||
else if (temp > xrtmag_next)
|
||||
xrtmag_next = temp;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_NR_PUCCH_RX
|
||||
LOG_D(NR_PHY, "PUCCH 0 : maxpos %d\n", maxpos);
|
||||
#endif
|
||||
index = maxpos;
|
||||
uint8_t ack_nack = !(index&0x01);
|
||||
LOG_D(PHY,
|
||||
"[PSFCH RX] %d.%d HARQ %s\n",
|
||||
frame,
|
||||
slot,
|
||||
ack_nack == 0 ? "ACK" : "NACK");
|
||||
return ack_nack;
|
||||
}
|
||||
@@ -47,15 +47,7 @@ void nr_get_carrier_frequencies(PHY_VARS_NR_UE *ue, uint64_t *dl_carrier, uint64
|
||||
}
|
||||
|
||||
|
||||
void nr_get_carrier_frequencies_sl(PHY_VARS_NR_UE *ue, uint64_t *sl_carrier) {
|
||||
|
||||
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
if (ue->if_freq!=0) {
|
||||
*sl_carrier = ue->if_freq;
|
||||
} else {
|
||||
*sl_carrier = fp->sl_CarrierFreq;
|
||||
}
|
||||
}
|
||||
|
||||
void nr_rf_card_config_gain(openair0_config_t *openair0_cfg,
|
||||
double rx_gain_off){
|
||||
|
||||
@@ -38,11 +38,13 @@
|
||||
#include "PHY/CODING/nrLDPC_extern.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
|
||||
//#define DEBUG_ULSCH_CODING
|
||||
|
||||
int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
||||
NR_UE_ULSCH_t *ulsch,
|
||||
sl_nr_tx_config_pscch_pssch_pdu_t *pscch_pssch_pdu,
|
||||
NR_DL_FRAME_PARMS* frame_parms,
|
||||
uint8_t harq_pid,
|
||||
unsigned int G) {
|
||||
@@ -53,44 +55,43 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
||||
///////////
|
||||
|
||||
unsigned int crc = 1;
|
||||
NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid];
|
||||
uint16_t nb_rb = ulsch->pusch_pdu.rb_size;
|
||||
uint32_t A = ulsch->pusch_pdu.pusch_data.tb_size<<3;
|
||||
NR_UL_UE_HARQ_t *harq_process = get_softmodem_params()->sl_mode ? &ue->sl_harq_processes[harq_pid] : &ue->ul_harq_processes[harq_pid];
|
||||
uint16_t nb_rb = pscch_pssch_pdu == NULL ? ulsch->pusch_pdu.rb_size : pscch_pssch_pdu->l_subch * pscch_pssch_pdu->subchannel_size;
|
||||
uint32_t A = (pscch_pssch_pdu == NULL ? ulsch->pusch_pdu.pusch_data.tb_size : pscch_pssch_pdu->tb_size)<<3;
|
||||
uint32_t *pz = &harq_process->Z;
|
||||
uint8_t mod_order = ulsch->pusch_pdu.qam_mod_order;
|
||||
uint8_t mod_order = pscch_pssch_pdu == NULL ? ulsch->pusch_pdu.qam_mod_order : pscch_pssch_pdu->mod_order;
|
||||
int ndi = pscch_pssch_pdu==NULL ? ulsch->pusch_pdu.pusch_data.new_data_indicator:pscch_pssch_pdu->ndi;
|
||||
int num_layers = pscch_pssch_pdu == NULL ? ulsch->pusch_pdu.nrOfLayers:pscch_pssch_pdu->num_layers;
|
||||
int rv_index = pscch_pssch_pdu == NULL ? ulsch->pusch_pdu.pusch_data.rv_index:pscch_pssch_pdu->rv_index;
|
||||
int tbslbrm = pscch_pssch_pdu==NULL?ulsch->pusch_pdu.tbslbrm:pscch_pssch_pdu->tbslbrm;
|
||||
|
||||
uint16_t Kr=0;
|
||||
uint32_t r_offset=0;
|
||||
uint32_t F=0;
|
||||
// target_code_rate is in 0.1 units
|
||||
float Coderate = (float) ulsch->pusch_pdu.target_code_rate / 10240.0f;
|
||||
float Coderate = (float) (pscch_pssch_pdu == NULL ? ulsch->pusch_pdu.target_code_rate : pscch_pssch_pdu->target_coderate) / 10240.0f;
|
||||
|
||||
if (pscch_pssch_pdu) memcpy(harq_process->a,pscch_pssch_pdu->slsch_payload,A>>3);
|
||||
///////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_IN);
|
||||
|
||||
LOG_D(NR_PHY, "ulsch coding nb_rb %d, Nl = %d\n", nb_rb, ulsch->pusch_pdu.nrOfLayers);
|
||||
LOG_D(NR_PHY, "ulsch coding A %d G %d mod_order %d Coderate %f\n", A, G, mod_order, Coderate);
|
||||
LOG_D(NR_PHY, "%s coding nb_rb %d, Nl = %d\n", pscch_pssch_pdu == NULL ? "ULSCH":"SLSCH",nb_rb, num_layers);
|
||||
LOG_D(NR_PHY, "%s coding A %d G %d mod_order %d Coderate %f\n", pscch_pssch_pdu == NULL ? "ULSCH" : "SLSCH",A, G, mod_order, Coderate);
|
||||
LOG_D(NR_PHY, "harq_pid %d harq_process->ndi %d, pusch_data.new_data_indicator %d\n",
|
||||
harq_pid,harq_process->ndi,ulsch->pusch_pdu.pusch_data.new_data_indicator);
|
||||
harq_pid,harq_process->ndi,ndi);
|
||||
|
||||
if (harq_process->first_tx == 1 ||
|
||||
harq_process->ndi != ulsch->pusch_pdu.pusch_data.new_data_indicator) { // this is a new packet
|
||||
harq_process->ndi != ndi) { // this is a new packet
|
||||
#ifdef DEBUG_ULSCH_CODING
|
||||
printf("encoding thinks this is a new packet \n");
|
||||
#endif
|
||||
harq_process->first_tx = 0;
|
||||
///////////////////////// a---->| add CRC |---->b /////////////////////////
|
||||
///////////
|
||||
/*
|
||||
int i;
|
||||
printf("ulsch (tx): \n");
|
||||
for (i=0;i<(A>>3);i++)
|
||||
printf("%02x.",harq_process->a[i]);
|
||||
printf("\n");
|
||||
*/
|
||||
|
||||
int max_payload_bytes = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*ulsch->pusch_pdu.nrOfLayers*1056;
|
||||
|
||||
int max_payload_bytes = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*num_layers*1056;
|
||||
|
||||
if (A > 3824) {
|
||||
// Add 24-bit crc (polynomial A) to payload
|
||||
@@ -145,7 +146,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
||||
&harq_process->F,
|
||||
harq_process->BG);
|
||||
|
||||
if (harq_process->C>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*ulsch->pusch_pdu.nrOfLayers) {
|
||||
if (harq_process->C>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*num_layers) {
|
||||
LOG_E(PHY,"nr_segmentation.c: too many segments %d, B %d\n",harq_process->C,harq_process->B);
|
||||
return(-1);
|
||||
}
|
||||
@@ -217,8 +218,8 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
||||
|
||||
///////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
LOG_D(PHY,"setting ndi to %d from pusch_data\n", ulsch->pusch_pdu.pusch_data.new_data_indicator);
|
||||
harq_process->ndi = ulsch->pusch_pdu.pusch_data.new_data_indicator;
|
||||
LOG_D(PHY,"setting ndi to %d from pusch_data\n", ndi);
|
||||
harq_process->ndi = ndi;
|
||||
}
|
||||
F = harq_process->F;
|
||||
Kr = harq_process->K;
|
||||
@@ -236,19 +237,19 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
||||
LOG_D(PHY,"Rate Matching, Code segment %d (coded bits (G) %u, unpunctured/repeated bits per code segment %d, mod_order %d, nb_rb %d, rvidx %d)...\n",
|
||||
r,
|
||||
G,
|
||||
Kr*3,
|
||||
Kr>>3,
|
||||
mod_order,nb_rb,
|
||||
ulsch->pusch_pdu.pusch_data.rv_index);
|
||||
rv_index);
|
||||
|
||||
//start_meas(rm_stats);
|
||||
///////////////////////// d---->| Rate matching bit selection |---->e /////////////////////////
|
||||
///////////
|
||||
|
||||
uint32_t E = nr_get_E(G, harq_process->C, mod_order, ulsch->pusch_pdu.nrOfLayers, r);
|
||||
uint32_t E = nr_get_E(G, harq_process->C, mod_order, num_layers, r);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RATE_MATCHING_LDPC, VCD_FUNCTION_IN);
|
||||
start_meas(&ue->ulsch_rate_matching_stats);
|
||||
if (nr_rate_matching_ldpc(ulsch->pusch_pdu.tbslbrm,
|
||||
if (nr_rate_matching_ldpc(tbslbrm,
|
||||
harq_process->BG,
|
||||
*pz,
|
||||
harq_process->d[r],
|
||||
@@ -256,7 +257,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
||||
harq_process->C,
|
||||
F,
|
||||
Kr-F-2*(*pz),
|
||||
ulsch->pusch_pdu.pusch_data.rv_index,
|
||||
rv_index,
|
||||
E) == -1)
|
||||
return -1;
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_sch_dmrs.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_dci.h"
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "PHY/TOOLS/tools_defs.h"
|
||||
#include "executables/nr-softmodem.h"
|
||||
@@ -93,6 +94,55 @@ void nr_pusch_codeword_scrambling_uci(uint8_t *in,
|
||||
}
|
||||
}
|
||||
|
||||
void nr_pusch_codeword_scrambling_sci(uint32_t *in,
|
||||
uint32_t size,
|
||||
uint32_t Nid,
|
||||
uint32_t* out)
|
||||
{
|
||||
uint8_t reset, b_idx;
|
||||
uint32_t x1 = 0, x2 = 0, s = 0;
|
||||
|
||||
reset = 1;
|
||||
x2 = (Nid<<15) + 1010;
|
||||
|
||||
for (int i=0; i<size; i++) {
|
||||
b_idx = i&0x1f;
|
||||
if (b_idx==0) {
|
||||
s = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
if (i)
|
||||
out++;
|
||||
}
|
||||
*out ^= (((in[i])&1) ^ ((s>>b_idx)&1))<<b_idx;
|
||||
//printf("i %d b_idx %d in %d s 0x%08x out 0x%08x\n", i, b_idx, in[i], s, *out);
|
||||
}
|
||||
}
|
||||
void nr_pusch_codeword_scrambling_sci_2layer(uint32_t *in,
|
||||
uint32_t size,
|
||||
uint32_t Nid,
|
||||
uint32_t* out)
|
||||
{
|
||||
uint8_t reset, b_idx;
|
||||
uint32_t x1 = 0, x2 = 0, s = 0;
|
||||
|
||||
reset = 1;
|
||||
x2 = (Nid<<15) + 1010;
|
||||
|
||||
for (int i=0; i<size; i+=4) {
|
||||
b_idx = i&0x1f;
|
||||
if (b_idx==0) {
|
||||
s = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
if (i)
|
||||
out++;
|
||||
}
|
||||
*out ^= (((in[i])&1) ^ ((s>>b_idx)&1))<<b_idx;
|
||||
*out ^= (((in[i+1])&1) ^ ((s>>(b_idx+1))&1))<<(b_idx+1);
|
||||
*out ^= (((in[i])&1) ^ ((s>>b_idx)&1))<<(b_idx+2);
|
||||
*out ^= (((in[i+1])&1) ^ ((s>>(b_idx+1))&1))<<(b_idx+3);
|
||||
//printf("i %d b_idx %d in %d s 0x%08x out 0x%08x\n", i, b_idx, in[i], s, *out);
|
||||
}
|
||||
}
|
||||
void nr_pusch_codeword_scrambling(uint8_t *in,
|
||||
uint32_t size,
|
||||
uint32_t Nid,
|
||||
@@ -106,6 +156,8 @@ void nr_pusch_codeword_scrambling(uint8_t *in,
|
||||
nr_codeword_scrambling(in, size, 0, Nid, n_RNTI, out);
|
||||
}
|
||||
|
||||
int dmrs_pscch_mask[2] = {7,15} ;
|
||||
|
||||
void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
const unsigned char harq_pid,
|
||||
const uint32_t frame,
|
||||
@@ -122,60 +174,116 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
int i;
|
||||
int sample_offsetF, N_RE_prime;
|
||||
|
||||
NR_DL_FRAME_PARMS *frame_parms = &UE->frame_parms;
|
||||
|
||||
bool is_csi_rs_slot = false;
|
||||
if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS)
|
||||
is_csi_rs_slot = true;
|
||||
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params = is_csi_rs_slot ? (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)&phy_data->nr_sl_pssch_pscch_pdu.nr_sl_csi_rs_pdu : NULL;
|
||||
if (csi_params)
|
||||
LOG_D(NR_PHY, "Tx start_rb %i, cdm_type %i, csi_type %i, freq_density %i, nr_of_rbs %i, row %i symb_l0 %i is_csi_rs_slot %i\n",
|
||||
csi_params->start_rb, csi_params->cdm_type, csi_params->csi_type, csi_params->freq_density, csi_params->nr_of_rbs, csi_params->row, csi_params->symb_l0, is_csi_rs_slot);
|
||||
int N_PRB_oh = 0; // higher layer (RRC) parameter xOverhead in PUSCH-ServingCellConfig
|
||||
uint16_t number_dmrs_symbols = 0;
|
||||
|
||||
NR_UE_ULSCH_t *ulsch_ue = &phy_data->ulsch;
|
||||
NR_UL_UE_HARQ_t *harq_process_ul_ue = &UE->ul_harq_processes[harq_pid];
|
||||
sl_nr_tx_config_pscch_pssch_pdu_t *pscch_pssch_pdu = &phy_data->nr_sl_pssch_pscch_pdu;
|
||||
NR_UL_UE_HARQ_t *harq_process_ul_ue = get_softmodem_params()->sl_mode ? &UE->sl_harq_processes[harq_pid] : &UE->ul_harq_processes[harq_pid];
|
||||
const nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &ulsch_ue->pusch_pdu;
|
||||
|
||||
int start_symbol = pusch_pdu->start_symbol_index;
|
||||
uint16_t ul_dmrs_symb_pos = pusch_pdu->ul_dmrs_symb_pos;
|
||||
uint8_t number_of_symbols = pusch_pdu->nr_of_symbols;
|
||||
uint8_t dmrs_type = pusch_pdu->dmrs_config_type;
|
||||
uint16_t start_rb = pusch_pdu->rb_start;
|
||||
uint16_t nb_rb = pusch_pdu->rb_size;
|
||||
uint8_t Nl = pusch_pdu->nrOfLayers;
|
||||
uint8_t mod_order = pusch_pdu->qam_mod_order;
|
||||
uint16_t rnti = pusch_pdu->rnti;
|
||||
uint8_t cdm_grps_no_data = pusch_pdu->num_dmrs_cdm_grps_no_data;
|
||||
uint16_t start_sc = frame_parms->first_carrier_offset + (start_rb+pusch_pdu->bwp_start)*NR_NB_SC_PER_RB;
|
||||
|
||||
NR_DL_FRAME_PARMS *frame_parms = pscch_pssch_pdu == NULL ? &UE->frame_parms : &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
int start_symbol = pscch_pssch_pdu == NULL ? pusch_pdu->start_symbol_index : (1+pscch_pssch_pdu->pssch_startsym);
|
||||
uint16_t ul_dmrs_symb_pos = pscch_pssch_pdu == NULL ? pusch_pdu->ul_dmrs_symb_pos : pscch_pssch_pdu->dmrs_symbol_position;
|
||||
uint8_t number_of_symbols = pscch_pssch_pdu == NULL ? pusch_pdu->nr_of_symbols : pscch_pssch_pdu->pssch_numsym;
|
||||
uint8_t dmrs_type = pscch_pssch_pdu == NULL ? pusch_pdu->dmrs_config_type : pusch_dmrs_type1;
|
||||
uint16_t start_rb = pscch_pssch_pdu == NULL ? pusch_pdu->rb_start : pscch_pssch_pdu->startrb;
|
||||
uint16_t nb_rb = pscch_pssch_pdu == NULL ? pusch_pdu->rb_size : pscch_pssch_pdu->l_subch * pscch_pssch_pdu->subchannel_size;
|
||||
uint8_t Nl = pscch_pssch_pdu == NULL ? pusch_pdu->nrOfLayers : pscch_pssch_pdu->num_layers;
|
||||
uint8_t mod_order = pscch_pssch_pdu == NULL ? pusch_pdu->qam_mod_order : pscch_pssch_pdu->mod_order;
|
||||
uint16_t rnti = pscch_pssch_pdu == NULL ? pusch_pdu->rnti : 0;
|
||||
uint8_t cdm_grps_no_data = pscch_pssch_pdu == NULL ? pusch_pdu->num_dmrs_cdm_grps_no_data : 1;
|
||||
uint16_t start_sc = frame_parms->first_carrier_offset + (start_rb+(pscch_pssch_pdu == NULL ? pusch_pdu->bwp_start:0))*NR_NB_SC_PER_RB;
|
||||
uint16_t Tpmi = pscch_pssch_pdu == NULL ? pusch_pdu->Tpmi : 0;
|
||||
|
||||
if (start_sc >= frame_parms->ofdm_symbol_size)
|
||||
start_sc -= frame_parms->ofdm_symbol_size;
|
||||
|
||||
ulsch_ue->Nid_cell = frame_parms->Nid_cell;
|
||||
|
||||
uint8_t first_dmrs_symbol = 0;
|
||||
bool is_first_dmrs_symbol = true;
|
||||
for (int i = start_symbol; i < start_symbol + number_of_symbols; i++) {
|
||||
if((ul_dmrs_symb_pos >> i) & 0x01)
|
||||
if((ul_dmrs_symb_pos >> i) & 0x01) {
|
||||
number_dmrs_symbols += 1;
|
||||
if (is_first_dmrs_symbol) {
|
||||
first_dmrs_symbol = i;
|
||||
is_first_dmrs_symbol = false;
|
||||
}
|
||||
if (csi_params && csi_params->symb_l0 != 0)
|
||||
AssertFatal(i != csi_params->symb_l0, "CSI-RS (symb_l0 %d) MUST not be sent in DMRS symbol (%d)\n", csi_params->symb_l0, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (csi_params && csi_params->symb_l0 != 0)
|
||||
AssertFatal(csi_params->symb_l0 > pscch_pssch_pdu->pscch_numsym, "CSI-RS (symb_l0 %d) MUST not be sent in PSCCH symbol (%d)\n", csi_params->symb_l0, pscch_pssch_pdu->pscch_numsym);
|
||||
nb_dmrs_re_per_rb = ((dmrs_type == pusch_dmrs_type1) ? 6:4)*cdm_grps_no_data;
|
||||
|
||||
LOG_D(PHY,"ulsch TX %x : start_rb %d nb_rb %d mod_order %d Nl %d Tpmi %d bwp_start %d start_sc %d start_symbol %d num_symbols %d cdmgrpsnodata %d num_dmrs %d dmrs_re_per_rb %d\n",
|
||||
rnti,start_rb,nb_rb,mod_order,Nl,pusch_pdu->Tpmi,pusch_pdu->bwp_start,start_sc,start_symbol,number_of_symbols,cdm_grps_no_data,number_dmrs_symbols,nb_dmrs_re_per_rb);
|
||||
//LOG_I(NR_PHY,"%s TX %x : start_rb %d nb_rb %d mod_order %d Nl %d Tpmi %d bwp_start %d start_sc %d start_symbol %d num_symbols %d cdmgrpsnodata %d num_dmrs %d dmrs_re_per_rb %d\n",pscch_pssch_pdu==NULL?"PUSCH":"PSSCH",
|
||||
// rnti,start_rb,nb_rb,mod_order,Nl,Tpmi,pscch_pssch_pdu==NULL?pusch_pdu->bwp_start:0,start_sc,start_symbol,number_of_symbols,cdm_grps_no_data,number_dmrs_symbols,nb_dmrs_re_per_rb);
|
||||
// TbD num_of_mod_symbols is set but never used
|
||||
N_RE_prime = NR_NB_SC_PER_RB*number_of_symbols - nb_dmrs_re_per_rb*number_dmrs_symbols - N_PRB_oh;
|
||||
uint16_t num_CSI_REs = is_csi_rs_slot ? get_nRECSI_RS(csi_params->freq_density, csi_params->nr_of_rbs) : 0;
|
||||
int num_CSI_REs_per_RB = is_csi_rs_slot ? (num_CSI_REs/csi_params->nr_of_rbs) : 0;
|
||||
N_RE_prime = NR_NB_SC_PER_RB * number_of_symbols - nb_dmrs_re_per_rb * number_dmrs_symbols - N_PRB_oh - num_CSI_REs_per_RB;
|
||||
harq_process_ul_ue->num_of_mod_symbols = N_RE_prime*nb_rb;
|
||||
|
||||
/////////////////////////ULSCH coding/////////////////////////
|
||||
///////////
|
||||
int sci2_re = pscch_pssch_pdu ? get_NREsci2(pscch_pssch_pdu->sci2_alpha_times_100,
|
||||
pscch_pssch_pdu->sci2_payload_len,
|
||||
pscch_pssch_pdu->sci2_beta_offset,
|
||||
pscch_pssch_pdu->pssch_numsym,
|
||||
pscch_pssch_pdu->pscch_numsym,
|
||||
pscch_pssch_pdu->pscch_numrbs,
|
||||
pscch_pssch_pdu->l_subch,
|
||||
pscch_pssch_pdu->subchannel_size,
|
||||
get_softmodem_params()->sl_mode ? 1 : pscch_pssch_pdu->mcs,
|
||||
pscch_pssch_pdu->mcs_table): 0 ;
|
||||
//if (pscch_pssch_pdu) LOG_I(NR_PHY,"dmrs_symbol_position %x, pscch_numsym %d\n",pscch_pssch_pdu->dmrs_symbol_position,pscch_pssch_pdu->pscch_numsym);
|
||||
AssertFatal(pscch_pssch_pdu->pscch_numsym==2 || pscch_pssch_pdu->pscch_numsym==3,"illegal pscch_numsym %d\n",pscch_pssch_pdu->pscch_numsym);
|
||||
int sci1_dmrs_overlap = pscch_pssch_pdu ? pscch_pssch_pdu->dmrs_symbol_position & dmrs_pscch_mask[pscch_pssch_pdu->pscch_numsym-2] : 0;
|
||||
uint16_t sci1_re = pscch_pssch_pdu->pscch_numsym * pscch_pssch_pdu->pscch_numrbs * NR_NB_SC_PER_RB;
|
||||
unsigned int G = (pscch_pssch_pdu==NULL) ? nr_get_G(nb_rb, number_of_symbols,
|
||||
nb_dmrs_re_per_rb, number_dmrs_symbols, mod_order, Nl):
|
||||
nr_get_G_SL(nb_rb, number_of_symbols, 6, number_dmrs_symbols, sci1_dmrs_overlap, sci1_re,
|
||||
pscch_pssch_pdu->pscch_numrbs, sci2_re, num_CSI_REs, mod_order, Nl);
|
||||
|
||||
unsigned int G = nr_get_G(nb_rb, number_of_symbols,
|
||||
nb_dmrs_re_per_rb, number_dmrs_symbols, mod_order, Nl);
|
||||
|
||||
// Following code checks, after PSCCH symbols and DMRS symbols, whether PSSCH symbols are used by SCI2 or not,
|
||||
// If true, then CSI-RS MUST not be sent in those PSSCH symbols containing SCI2.
|
||||
if (csi_params && csi_params->symb_l0 != 0) {
|
||||
int32_t next_symbs_sci2_re = 0;
|
||||
int32_t sci1_re = 12 * pscch_pssch_pdu->pscch_numrbs;
|
||||
int32_t non_sci1_re = 12 * nb_rb - sci1_re;
|
||||
next_symbs_sci2_re = first_dmrs_symbol <= pscch_pssch_pdu->pscch_numsym ? sci2_re - (non_sci1_re / 2 - (non_sci1_re * (pscch_pssch_pdu->pscch_numsym - 1)) - (12 * nb_rb) / 2) : sci2_re - (12 * nb_rb) / 2;
|
||||
int8_t remaining_sci2_symb = next_symbs_sci2_re > 0 ? ceil(next_symbs_sci2_re / (12 * nb_rb)) : 0;
|
||||
int8_t non_csi_rs_symbs = pscch_pssch_pdu->pscch_numsym + 1 + remaining_sci2_symb; // 1 is for first dmrs symbol
|
||||
AssertFatal(csi_params->symb_l0 > non_csi_rs_symbs, "CSI-RS MUST not be sent in PSSCH symbol containing SCI2");
|
||||
}
|
||||
|
||||
uint32_t Gsci2 = sci2_re*2*Nl;
|
||||
trace_NRpdu(DIRECTION_UPLINK,
|
||||
harq_process_ul_ue->a,
|
||||
pusch_pdu->pusch_data.tb_size,
|
||||
pscch_pssch_pdu==NULL?pusch_pdu->pusch_data.tb_size:pscch_pssch_pdu->tb_size,
|
||||
WS_C_RNTI, rnti, frame, slot, 0, 0);
|
||||
|
||||
if (nr_ulsch_encoding(UE, ulsch_ue, frame_parms, harq_pid, G) == -1)
|
||||
if (nr_ulsch_encoding(UE, ulsch_ue, pscch_pssch_pdu,frame_parms, harq_pid, G) == -1)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
uint32_t sci2_encoded_output[sci2_re*2];
|
||||
|
||||
if (pscch_pssch_pdu) {
|
||||
LOG_D(NR_PHY,"Generating SCI2/PSSCH with %d RE, payload %llx\n",sci2_re,*(unsigned long long*)pscch_pssch_pdu->sci2_payload);
|
||||
// do SCI2 encoding
|
||||
polar_encoder_fast((uint64_t*)pscch_pssch_pdu->sci2_payload, (void*)sci2_encoded_output, NULL,0, 1,
|
||||
NR_POLAR_SCI2_MESSAGE_TYPE,
|
||||
pscch_pssch_pdu->sci2_payload_len, sci2_re);
|
||||
}
|
||||
|
||||
///////////
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@@ -185,15 +293,29 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
|
||||
uint32_t available_bits = G;
|
||||
uint32_t scrambled_output[(available_bits>>5)+1];
|
||||
uint32_t scrambled_output_sci[(Gsci2>>5)+1];
|
||||
memset(scrambled_output, 0, ((available_bits>>5)+1)*sizeof(uint32_t));
|
||||
memset(scrambled_output_sci, 0, ((Gsci2>>5)+1)*sizeof(uint32_t));
|
||||
|
||||
// for (int i=0;i<(Gsci2>>5)+1;i++) LOG_I(NR_PHY,"sci2_encoded[%d] %x\n",i,sci2_encoded_output[i]);
|
||||
// for (int g=0;g<G;g++) LOG_I(NR_PHY,"coded_output_f[%d] %d\n",g,harq_process_ul_ue->f[g]);
|
||||
// LOG_I(NR_PHY,"Scrambling with Nid %x\n",phy_data->pscch_Nid);
|
||||
nr_pusch_codeword_scrambling(harq_process_ul_ue->f,
|
||||
available_bits,
|
||||
ulsch_ue->Nid_cell,
|
||||
rnti,
|
||||
G,
|
||||
pscch_pssch_pdu==NULL ? ulsch_ue->Nid_cell : phy_data->pscch_Nid,
|
||||
pscch_pssch_pdu==NULL ? rnti : 1010,
|
||||
false,
|
||||
scrambled_output);
|
||||
|
||||
if (pscch_pssch_pdu && Nl==1)
|
||||
nr_pdcch_scrambling(sci2_encoded_output,
|
||||
Gsci2,
|
||||
phy_data->pscch_Nid,1010,
|
||||
scrambled_output_sci,1);
|
||||
else if (pscch_pssch_pdu)
|
||||
nr_pusch_codeword_scrambling_sci_2layer(sci2_encoded_output,
|
||||
Gsci2,
|
||||
phy_data->pscch_Nid,
|
||||
scrambled_output_sci);
|
||||
/////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -203,25 +325,39 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
int max_num_re = Nl*number_of_symbols*nb_rb*NR_NB_SC_PER_RB;
|
||||
int32_t d_mod[max_num_re] __attribute__ ((aligned(16)));
|
||||
|
||||
nr_modulation(scrambled_output, // assume one codeword for the moment
|
||||
available_bits,
|
||||
mod_order,
|
||||
(int16_t *)d_mod);
|
||||
|
||||
|
||||
if (Gsci2 > 0) {
|
||||
nr_modulation(scrambled_output_sci, // assume one codeword for the moment
|
||||
Gsci2,
|
||||
2,
|
||||
(int16_t *)d_mod);
|
||||
//for (int i=0;i<Gsci2;i+=2) LOG_I(NR_PHY,"SCI2 RE %d/%d: (%d,%d)\n",i/2,Gsci2/2,((int16_t*)d_mod)[i],((int16_t*)d_mod)[i+1]);
|
||||
int32_t d_mod2[max_num_re] __attribute__ ((aligned(16)));
|
||||
nr_modulation(scrambled_output, // assume one codeword for the moment
|
||||
available_bits,
|
||||
mod_order,
|
||||
(int16_t *)d_mod2);
|
||||
LOG_D(NR_PHY,"SCI bits %d (sci2_re %d), PSSCH bits %d (PSCCH RE %d), max_re %d\n",Gsci2,sci2_re,available_bits,available_bits/mod_order,max_num_re);
|
||||
memcpy(d_mod+sci2_re,d_mod2,available_bits*sizeof(int32_t)/mod_order);
|
||||
}
|
||||
else
|
||||
nr_modulation(scrambled_output, // assume one codeword for the moment
|
||||
available_bits,
|
||||
mod_order,
|
||||
(int16_t *)d_mod);
|
||||
|
||||
///////////
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////DMRS Modulation/////////////////////////
|
||||
///////////
|
||||
|
||||
if(pusch_pdu->ul_dmrs_scrambling_id != UE->scramblingID_ulsch[pusch_pdu->scid]) {
|
||||
if(!pscch_pssch_pdu && pusch_pdu->ul_dmrs_scrambling_id != UE->scramblingID_ulsch[pusch_pdu->scid]) {
|
||||
UE->scramblingID_ulsch[pusch_pdu->scid] = pusch_pdu->ul_dmrs_scrambling_id;
|
||||
nr_init_pusch_dmrs(UE, pusch_pdu->scid, pusch_pdu->ul_dmrs_scrambling_id);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ***pusch_dmrs = UE->nr_gold_pusch_dmrs[slot];
|
||||
uint16_t n_dmrs = (pusch_pdu->bwp_start + start_rb + nb_rb)*((dmrs_type == pusch_dmrs_type1) ? 6:4);
|
||||
uint16_t n_dmrs = ((pscch_pssch_pdu==NULL ? pusch_pdu->bwp_start : 0) + start_rb + nb_rb)*((dmrs_type == pusch_dmrs_type1) ? 6:4);
|
||||
int16_t mod_dmrs[n_dmrs<<1] __attribute((aligned(16)));
|
||||
|
||||
///////////
|
||||
@@ -235,7 +371,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
uint8_t L_ptrs, K_ptrs = 0;
|
||||
uint16_t beta_ptrs = 1; // temp value until power control is implemented
|
||||
|
||||
if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
|
||||
if (!pscch_pssch_pdu && (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS)) {
|
||||
|
||||
K_ptrs = pusch_pdu->pusch_ptrs.ptrs_freq_density;
|
||||
L_ptrs = 1<<pusch_pdu->pusch_ptrs.ptrs_time_density;
|
||||
@@ -259,11 +395,10 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
|
||||
int16_t **tx_layers = (int16_t **)malloc16_clear(Nl*sizeof(int16_t *));
|
||||
for (int nl=0; nl<Nl; nl++)
|
||||
tx_layers[nl] = (int16_t *)malloc16_clear((available_bits<<1)/mod_order*sizeof(int16_t));
|
||||
|
||||
tx_layers[nl] = (int16_t *)malloc16_clear((((available_bits<<1)/mod_order)+(sci2_re<<1))*sizeof(int32_t));
|
||||
nr_ue_layer_mapping((int16_t *)d_mod,
|
||||
Nl,
|
||||
available_bits/mod_order,
|
||||
(available_bits/mod_order)+sci2_re,
|
||||
tx_layers);
|
||||
|
||||
///////////
|
||||
@@ -282,7 +417,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
/// Transform-coded "y"-sequences (for definition see 38-211 V15.3.0 2018-09, subsection 6.3.1.4)
|
||||
int32_t y[max_num_re] __attribute__ ((aligned(16)));
|
||||
|
||||
if (pusch_pdu->transform_precoding == transformPrecoder_enabled) {
|
||||
if (!pscch_pssch_pdu && (pusch_pdu->transform_precoding == transformPrecoder_enabled)) {
|
||||
|
||||
uint32_t nb_re_pusch=nb_rb * NR_NB_SC_PER_RB;
|
||||
uint32_t y_offset = 0;
|
||||
@@ -312,7 +447,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
LOG_D(PHY,"Transform precoding being done on data- symbol: %d, nb_re_pusch: %d, y_offset: %d\n", l, nb_re_pusch, y_offset);
|
||||
|
||||
#ifdef DEBUG_PUSCH_MAPPING
|
||||
printf("NR_ULSCH_UE: y_offset %u\t nb_re_pusch %u \t Symbol %d \t nb_rb %d \n",
|
||||
LOG_I(NR_PHY,"NR_ULSCH_UE: y_offset %u\t nb_re_pusch %u \t Symbol %d \t nb_rb %d \n",
|
||||
y_offset, nb_re_pusch, l, nb_rb);
|
||||
#endif
|
||||
}
|
||||
@@ -357,10 +492,11 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
uint16_t m = 0;
|
||||
|
||||
#ifdef DEBUG_PUSCH_MAPPING
|
||||
printf("NR_ULSCH_UE: Value of CELL ID %d /t, u %d \n", frame_parms->Nid_cell, u);
|
||||
LOG_I(NR_PHY,"NR_ULSCH_UE: Value of CELL ID %d /t, u %d \n", frame_parms->Nid_cell, u);
|
||||
#endif
|
||||
|
||||
int dmrs_port = get_dmrs_port(nl,pusch_pdu->dmrs_ports);
|
||||
int dmrs_port = get_dmrs_port(nl,pscch_pssch_pdu ? nl : pusch_pdu->dmrs_ports);
|
||||
if (dmrs_port < 0) return;
|
||||
// DMRS params for this dmrs port
|
||||
get_Wt(Wt, dmrs_port, dmrs_type);
|
||||
get_Wf(Wf, dmrs_port, dmrs_type);
|
||||
@@ -371,23 +507,40 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
uint16_t k = start_sc;
|
||||
uint16_t n = 0;
|
||||
uint8_t is_dmrs_sym = 0;
|
||||
uint8_t is_csi_rs_sym = 0;
|
||||
uint8_t is_ptrs_sym = 0;
|
||||
uint16_t dmrs_idx = 0, ptrs_idx = 0;
|
||||
int16_t csi_rs_rb = 0;
|
||||
int is_pscch_sym = 0;
|
||||
if (pscch_pssch_pdu && l<(start_symbol + pscch_pssch_pdu->pscch_numsym)) {
|
||||
is_pscch_sym = 1;
|
||||
}
|
||||
|
||||
if (is_csi_rs_slot && l == csi_params->symb_l0) {
|
||||
is_csi_rs_sym = 1;
|
||||
csi_rs_rb = csi_params->start_rb;
|
||||
}
|
||||
|
||||
if ((ul_dmrs_symb_pos >> l) & 0x01) {
|
||||
is_dmrs_sym = 1;
|
||||
|
||||
if (pusch_pdu->transform_precoding == transformPrecoder_disabled){
|
||||
if (pscch_pssch_pdu || (pusch_pdu->transform_precoding == transformPrecoder_disabled)){
|
||||
|
||||
if (dmrs_type == pusch_dmrs_type1)
|
||||
dmrs_idx = (pusch_pdu->bwp_start + start_rb)*6;
|
||||
dmrs_idx = ((pscch_pssch_pdu==NULL ? pusch_pdu->bwp_start : 0) + start_rb)*6;
|
||||
else
|
||||
dmrs_idx = (pusch_pdu->bwp_start + start_rb)*4;
|
||||
dmrs_idx = ((pscch_pssch_pdu==NULL ? pusch_pdu->bwp_start : 0) + start_rb)*4;
|
||||
|
||||
// TODO: performance improvement, we can skip the modulation of DMRS symbols outside the bandwidth part
|
||||
// Perform this on gold sequence, not required when SC FDMA operation is done,
|
||||
LOG_D(PHY,"DMRS in symbol %d\n",l);
|
||||
nr_modulation(pusch_dmrs[l][pusch_pdu->scid], n_dmrs*2, DMRS_MOD_ORDER, mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated
|
||||
if (pscch_pssch_pdu == NULL)
|
||||
nr_modulation(pusch_dmrs[l][pusch_pdu->scid], n_dmrs*2, DMRS_MOD_ORDER, mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated
|
||||
else {
|
||||
uint32_t pssch_dmrs[((frame_parms->N_RB_UL * 12) >> 5) + 1];
|
||||
nr_init_pssch_dmrs_oneshot(frame_parms,phy_data->pscch_Nid,pssch_dmrs,slot,l);
|
||||
nr_modulation(pssch_dmrs, n_dmrs*2, DMRS_MOD_ORDER, mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated
|
||||
}
|
||||
} else {
|
||||
dmrs_idx = 0;
|
||||
}
|
||||
@@ -404,7 +557,18 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
for (i=0; i< nb_rb*NR_NB_SC_PER_RB; i++) {
|
||||
uint8_t is_dmrs = 0;
|
||||
uint8_t is_ptrs = 0;
|
||||
uint8_t is_csi_rs = 0;
|
||||
|
||||
if (is_pscch_sym && i==(pscch_pssch_pdu->startrb)) {
|
||||
i+=(pscch_pssch_pdu->pscch_numrbs*NR_NB_SC_PER_RB);
|
||||
k+=(pscch_pssch_pdu->pscch_numrbs*NR_NB_SC_PER_RB);
|
||||
if (is_dmrs_sym) {
|
||||
dmrs_idx+=(6*pscch_pssch_pdu->pscch_numrbs);
|
||||
n+=(3*pscch_pssch_pdu->pscch_numrbs);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_D(NR_PHY, "symbol %d re %d/%d k %d\n", l, i, nb_rb*NR_NB_SC_PER_RB, k);
|
||||
sample_offsetF = l*frame_parms->ofdm_symbol_size + k;
|
||||
|
||||
if (is_dmrs_sym) {
|
||||
@@ -422,9 +586,26 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
frame_parms->ofdm_symbol_size);
|
||||
}
|
||||
|
||||
if (is_csi_rs_sym) {
|
||||
if ((k >= csi_params->start_rb * NR_NB_SC_PER_RB) && (i % NR_NB_SC_PER_RB == 0) && (csi_rs_rb < csi_params->nr_of_rbs)) {
|
||||
csi_rs_params_t table_params;
|
||||
get_csi_rs_params_from_table(csi_params, &table_params);
|
||||
port_freq_indices_t *port_freq_indices = (port_freq_indices_t *)malloc(table_params.ports*sizeof(port_freq_indices));
|
||||
get_csi_rs_freq_ind_sl(frame_parms, csi_rs_rb, csi_params, &table_params, port_freq_indices);
|
||||
if (k == port_freq_indices[nl].k) {
|
||||
is_csi_rs = 1;
|
||||
csi_rs_rb++;
|
||||
LOG_D(NR_PHY, "Tx port_freq_indices.p %i, port_freq_indices.k %d, is_csi_rs %d, k = %i, RE %i, csi_rs_rb %i\n",
|
||||
port_freq_indices[nl].p, port_freq_indices[nl].k, is_csi_rs, k, i, csi_rs_rb);
|
||||
}
|
||||
free(port_freq_indices);
|
||||
port_freq_indices = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_dmrs == 1) {
|
||||
// if transform precoding is enabled
|
||||
if (pusch_pdu->transform_precoding == transformPrecoder_enabled) {
|
||||
if (!pscch_pssch_pdu && pusch_pdu->transform_precoding == transformPrecoder_enabled) {
|
||||
((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*dmrs_seq[2*dmrs_idx]) >> 15;
|
||||
((int16_t*)tx_precoding[nl])[((sample_offsetF)<<1) + 1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*dmrs_seq[(2*dmrs_idx) + 1]) >> 15;
|
||||
} else {
|
||||
@@ -433,7 +614,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PUSCH_MAPPING
|
||||
printf("DMRS: Layer: %d\t, dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t dmrs: %d %d\n",
|
||||
LOG_I(NR_PHY,"DMRS: Layer: %d\t, dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t dmrs: %d %d\n",
|
||||
nl, dmrs_idx, l, k, k_prime, n, ((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1],
|
||||
((int16_t*)tx_precoding[nl])[((sample_offsetF)<<1) + 1]);
|
||||
#endif
|
||||
@@ -448,9 +629,14 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
((int16_t*)tx_precoding[nl])[((sample_offsetF)<<1) + 1] = (beta_ptrs*AMP*mod_ptrs[(ptrs_idx<<1) + 1]) >> 15;
|
||||
ptrs_idx++;
|
||||
} else if (!is_dmrs_sym || allowed_xlsch_re_in_dmrs_symbol(k, start_sc, frame_parms->ofdm_symbol_size, cdm_grps_no_data, dmrs_type)) {
|
||||
if (pusch_pdu->transform_precoding == transformPrecoder_disabled) {
|
||||
((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1] = ((int16_t *)tx_layers[nl])[m<<1];
|
||||
((int16_t*)tx_precoding[nl])[((sample_offsetF)<<1) + 1] = ((int16_t *)tx_layers[nl])[(m<<1) + 1];
|
||||
if (pscch_pssch_pdu || pusch_pdu->transform_precoding == transformPrecoder_disabled) {
|
||||
if (!is_csi_rs) {
|
||||
((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1] = ((int16_t *)tx_layers[nl])[m<<1];
|
||||
((int16_t*)tx_precoding[nl])[((sample_offsetF)<<1) + 1] = ((int16_t *)tx_layers[nl])[(m<<1) + 1];
|
||||
} else {
|
||||
((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1] = 0;
|
||||
((int16_t*)tx_precoding[nl])[((sample_offsetF)<<1) + 1] = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1] = ((int16_t *) y)[m<<1];
|
||||
@@ -458,12 +644,13 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PUSCH_MAPPING
|
||||
printf("DATA: layer %d\t m %d\t l %d \t k %d \t tx_precoding: %d %d\n",
|
||||
LOG_I(NR_PHY,"DATA: layer %d\t m %d\t l %d \t k %d \t tx_precoding: %d %d\n",
|
||||
nl, m, l, k, ((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1],
|
||||
((int16_t*)tx_precoding[nl])[((sample_offsetF)<<1) + 1]);
|
||||
#endif
|
||||
|
||||
m++;
|
||||
if (!is_csi_rs)
|
||||
m++;
|
||||
|
||||
} else {
|
||||
((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1] = 0;
|
||||
@@ -489,14 +676,23 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
for (int ap=0; ap<frame_parms->nb_antennas_tx; ap++) {
|
||||
for (int l=start_symbol; l<start_symbol+number_of_symbols; l++) {
|
||||
uint16_t k = start_sc;
|
||||
int is_pscch_sym = 0;
|
||||
if (pscch_pssch_pdu && l<(start_symbol + pscch_pssch_pdu->pscch_numsym)) {
|
||||
is_pscch_sym = 1;
|
||||
}
|
||||
|
||||
for (int rb=0; rb<nb_rb; rb++) {
|
||||
if (is_pscch_sym && rb==(pscch_pssch_pdu->startrb)) {
|
||||
k+=(pscch_pssch_pdu->pscch_numrbs*NR_NB_SC_PER_RB);
|
||||
if (k>=frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size;
|
||||
rb=pscch_pssch_pdu->startrb+pscch_pssch_pdu->pscch_numrbs;
|
||||
}
|
||||
//get pmi info
|
||||
uint8_t pmi=pusch_pdu->Tpmi;
|
||||
uint8_t pmi=Tpmi;
|
||||
|
||||
if (pmi == 0) {//unitary Precoding
|
||||
if (k + NR_NB_SC_PER_RB <= frame_parms->ofdm_symbol_size) { // RB does not cross DC
|
||||
if (ap<pusch_pdu->nrOfLayers)
|
||||
if (ap<Nl)
|
||||
memcpy(&txdataF[ap][l*frame_parms->ofdm_symbol_size + k],
|
||||
&tx_precoding[ap][2*(l*frame_parms->ofdm_symbol_size + k)],
|
||||
NR_NB_SC_PER_RB*sizeof(int32_t));
|
||||
@@ -507,7 +703,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
} else { // RB does cross DC
|
||||
int neg_length = frame_parms->ofdm_symbol_size - k;
|
||||
int pos_length = NR_NB_SC_PER_RB - neg_length;
|
||||
if (ap<pusch_pdu->nrOfLayers) {
|
||||
if (ap<Nl) {
|
||||
memcpy(&txdataF[ap][l*frame_parms->ofdm_symbol_size + k],
|
||||
&tx_precoding[ap][2*(l*frame_parms->ofdm_symbol_size + k)],
|
||||
neg_length*sizeof(int32_t));
|
||||
@@ -536,17 +732,17 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
W_prec = nr_W_1l_2p[pmi][ap];
|
||||
break;
|
||||
case 2://2 antenna ports
|
||||
if (pusch_pdu->nrOfLayers == 1)//1 layer
|
||||
if (Nl == 1)//1 layer
|
||||
W_prec = nr_W_1l_2p[pmi][ap];
|
||||
else//2 layers
|
||||
W_prec = nr_W_2l_2p[pmi][ap];
|
||||
break;
|
||||
case 4://4 antenna ports
|
||||
if (pusch_pdu->nrOfLayers == 1)//1 layer
|
||||
if (Nl == 1)//1 layer
|
||||
W_prec = nr_W_1l_4p[pmi][ap];
|
||||
else if (pusch_pdu->nrOfLayers == 2)//2 layers
|
||||
else if (Nl == 2)//2 layers
|
||||
W_prec = nr_W_2l_4p[pmi][ap];
|
||||
else if (pusch_pdu->nrOfLayers == 3)//3 layers
|
||||
else if (Nl == 3)//3 layers
|
||||
W_prec = nr_W_3l_4p[pmi][ap];
|
||||
else//4 layers
|
||||
W_prec = nr_W_4l_4p[pmi][ap];
|
||||
@@ -559,7 +755,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
|
||||
for (int i=0; i<NR_NB_SC_PER_RB; i++) {
|
||||
int32_t re_offset = l*frame_parms->ofdm_symbol_size + k;
|
||||
int32_t precodatatx_F = nr_layer_precoder(tx_precoding, W_prec, pusch_pdu->nrOfLayers, re_offset);
|
||||
int32_t precodatatx_F = nr_layer_precoder(tx_precoding, W_prec, Nl, re_offset);
|
||||
((int16_t*)txdataF[ap])[(re_offset<<1)] = ((int16_t *) &precodatatx_F)[0];
|
||||
((int16_t*)txdataF[ap])[(re_offset<<1) + 1] = ((int16_t *) &precodatatx_F)[1];
|
||||
|
||||
@@ -572,9 +768,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
} // symbol loop
|
||||
}// port loop
|
||||
|
||||
NR_UL_UE_HARQ_t *harq_process_ulsch=NULL;
|
||||
harq_process_ulsch = &UE->ul_harq_processes[harq_pid];
|
||||
harq_process_ulsch->status = SCH_IDLE;
|
||||
harq_process_ul_ue->status = SCH_IDLE;
|
||||
|
||||
for (int nl = 0; nl < Nl; nl++) {
|
||||
free_and_zero(tx_layers[nl]);
|
||||
@@ -591,15 +785,18 @@ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE,
|
||||
const uint8_t slot,
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
const uint8_t n_antenna_ports,
|
||||
c16_t **txdataF)
|
||||
c16_t **txdataF,
|
||||
uint32_t linktype)
|
||||
{
|
||||
const int tx_offset = frame_parms->get_samples_slot_timestamp(slot, frame_parms, 0);
|
||||
|
||||
c16_t **txdata = UE->common_vars.txData;
|
||||
|
||||
LOG_D(NR_PHY,"Applying TX rotation for slot %d linktype %d\n",slot,linktype);
|
||||
for(int ap = 0; ap < n_antenna_ports; ap++) {
|
||||
apply_nr_rotation_TX(frame_parms,
|
||||
txdataF[ap],
|
||||
frame_parms->symbol_rotation[1],
|
||||
frame_parms->symbol_rotation[linktype],
|
||||
slot,
|
||||
frame_parms->N_RB_UL,
|
||||
0,
|
||||
|
||||
@@ -59,14 +59,14 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
|
||||
const fapi_nr_ul_config_pucch_pdu *pucch_pdu)
|
||||
{
|
||||
#ifdef DEBUG_NR_PUCCH_TX
|
||||
printf("\t [nr_generate_pucch0] start function at slot(nr_slot_tx)=%d\n",nr_slot_tx);
|
||||
LOG_I(NR_PHY, "\t [nr_generate_pucch0] start function at slot(nr_slot_tx)=%d\n", nr_slot_tx);
|
||||
#endif
|
||||
/*
|
||||
* Implement TS 38.211 Subclause 6.3.2.3.1 Sequence generation
|
||||
*
|
||||
*/
|
||||
#ifdef DEBUG_NR_PUCCH_TX
|
||||
printf("\t [nr_generate_pucch0] sequence generation\n");
|
||||
LOG_I(NR_PHY, "\t [nr_generate_pucch0] sequence generation\n");
|
||||
#endif
|
||||
/*
|
||||
* Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2
|
||||
@@ -91,11 +91,19 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
|
||||
// the value of u,v (delta always 0 for PUCCH) has to be calculated according to TS 38.211 Subclause 6.3.2.2.1
|
||||
uint8_t u[2]={0,0},v[2]={0,0};
|
||||
|
||||
LOG_D(PHY,"pucch0: slot %d nr_symbols %d, start_symbol %d, prb_start %d, second_hop_prb %d, group_hop_flag %d, sequence_hop_flag %d, mcs %d\n",
|
||||
nr_slot_tx,pucch_pdu->nr_of_symbols,pucch_pdu->start_symbol_index,pucch_pdu->prb_start,pucch_pdu->second_hop_prb,pucch_pdu->group_hop_flag,pucch_pdu->sequence_hop_flag,pucch_pdu->mcs);
|
||||
LOG_D(PHY, "pucch0: slot %d nr_symbols %d, start_symbol %d, prb_start %d, second_hop_prb %d, group_hop_flag %d, sequence_hop_flag %d, mcs %d bwp_start %d hopping_id %d\n",
|
||||
nr_slot_tx, pucch_pdu->nr_of_symbols,
|
||||
pucch_pdu->start_symbol_index,
|
||||
pucch_pdu->prb_start,
|
||||
pucch_pdu->second_hop_prb,
|
||||
pucch_pdu->group_hop_flag,
|
||||
pucch_pdu->sequence_hop_flag,
|
||||
pucch_pdu->mcs,
|
||||
pucch_pdu->bwp_start,
|
||||
pucch_pdu->hopping_id);
|
||||
|
||||
#ifdef DEBUG_NR_PUCCH_TX
|
||||
printf("\t [nr_generate_pucch0] sequence generation: variable initialization for test\n");
|
||||
LOG_I(NR_PHY, "\t [nr_generate_pucch0] sequence generation: variable initialization for test\n");
|
||||
#endif
|
||||
// x_n contains the sequence r_u_v_alpha_delta(n)
|
||||
int16_t x_n_re[2][24],x_n_im[2][24];
|
||||
@@ -104,10 +112,10 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
|
||||
pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1);
|
||||
|
||||
// we proceed to calculate alpha according to TS 38.211 Subclause 6.3.2.2.2
|
||||
int prb_offset[2]={startingPRB,startingPRB};
|
||||
nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,0,nr_slot_tx,&u[0],&v[0]); // calculating u and v value
|
||||
int prb_offset[2] = {startingPRB, startingPRB};
|
||||
nr_group_sequence_hopping(pucch_GroupHopping, pucch_pdu->hopping_id, 0, nr_slot_tx, &u[0], &v[0]); // calculating u and v value
|
||||
if (pucch_pdu->freq_hop_flag == 1) {
|
||||
nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,1,nr_slot_tx,&u[1],&v[1]); // calculating u and v value
|
||||
nr_group_sequence_hopping(pucch_GroupHopping, pucch_pdu->hopping_id, 1, nr_slot_tx, &u[1], &v[1]); // calculating u and v value
|
||||
prb_offset[1] = pucch_pdu->second_hop_prb + pucch_pdu->bwp_start;
|
||||
}
|
||||
for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
|
||||
@@ -117,7 +125,7 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
|
||||
pucch_pdu->start_symbol_index,
|
||||
nr_slot_tx);
|
||||
#ifdef DEBUG_NR_PUCCH_TX
|
||||
printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \t(for symbol l=%d)\n",u[l],v[l],alpha,l);
|
||||
LOG_I(NR_PHY, "\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \t(for symbol l=%d)\n", u[l], v[l], alpha, l);
|
||||
#endif
|
||||
|
||||
for (int n=0; n<12; n++) {
|
||||
@@ -126,8 +134,8 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
|
||||
x_n_im[l][n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u[l]][n])>>15)
|
||||
+ (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u[l]][n])>>15))); // Im part of base sequence shifted by alpha
|
||||
#ifdef DEBUG_NR_PUCCH_TX
|
||||
printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \tx_n(l=%d,n=%d)=(%d,%d)\n",
|
||||
u[l],v[l],alpha,l,n,x_n_re[l][n],x_n_im[l][n]);
|
||||
LOG_I(NR_PHY, "\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \tx_n(l=%d,n=%d)=(%d, %d)\n",
|
||||
u[l], v[l], alpha, l, n, x_n_re[l][n], x_n_im[l][n]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -140,15 +148,15 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
|
||||
uint8_t l2;
|
||||
|
||||
for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
|
||||
l2=l+pucch_pdu->start_symbol_index;
|
||||
l2 = l + pucch_pdu->start_symbol_index;
|
||||
re_offset = (12*prb_offset[l]) + frame_parms->first_carrier_offset;
|
||||
if (re_offset>= frame_parms->ofdm_symbol_size)
|
||||
re_offset-=frame_parms->ofdm_symbol_size;
|
||||
if (re_offset >= frame_parms->ofdm_symbol_size)
|
||||
re_offset -= frame_parms->ofdm_symbol_size;
|
||||
|
||||
//txptr = &txdataF[0][re_offset];
|
||||
#ifdef DEBUG_NR_PUCCH_TX
|
||||
printf("\t [nr_generate_pucch0] symbol %d PRB %d (%u)\n",l,prb_offset[l],re_offset);
|
||||
#endif
|
||||
LOG_I(NR_PHY, "\t [nr_generate_pucch0] symbol %d PRB %d (%u)\n", l, prb_offset[l], re_offset);
|
||||
#endif
|
||||
for (int n=0; n<12; n++) {
|
||||
|
||||
txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset].r = (int16_t)(((int32_t)(amp) * x_n_re[l][n])>>15);
|
||||
@@ -157,14 +165,14 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
|
||||
//((int16_t *)txptr[0][re_offset])[1] = (int16_t)((int32_t)amp * x_n_im[(12*l)+n])>>15;
|
||||
//txptr[re_offset] = (x_n_re[(12*l)+n]<<16) + x_n_im[(12*l)+n];
|
||||
#ifdef DEBUG_NR_PUCCH_TX
|
||||
printf("\t [nr_generate_pucch0] mapping to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \ttxptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
|
||||
LOG_I(NR_PHY, "\t [nr_generate_pucch0] mapping to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \ttxptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
|
||||
amp, frame_parms->ofdm_symbol_size, frame_parms->N_RB_DL, frame_parms->first_carrier_offset, (l2 * frame_parms->ofdm_symbol_size) + re_offset,
|
||||
l2, n, txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset].r,
|
||||
txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset].i);
|
||||
#endif
|
||||
re_offset++;
|
||||
if (re_offset>= frame_parms->ofdm_symbol_size)
|
||||
re_offset-=frame_parms->ofdm_symbol_size;
|
||||
if (re_offset >= frame_parms->ofdm_symbol_size)
|
||||
re_offset -= frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -645,7 +653,7 @@ static void nr_uci_encoding(uint64_t payload,
|
||||
AssertFatal(nrofPRB<=16,"Number of PRB >16\n");
|
||||
} else if (A>=12) {
|
||||
AssertFatal(A<65,"Polar encoding not supported yet for UCI with more than 64 bits\n");
|
||||
polar_encoder_fast(&payload, b, 0,0,
|
||||
polar_encoder_fast(&payload, b, NULL,0,0,
|
||||
NR_POLAR_UCI_PUCCH_MESSAGE_TYPE,
|
||||
A,
|
||||
nrofPRB);
|
||||
|
||||
@@ -64,10 +64,11 @@ float Limits_KPI_gNB[4][2] = {
|
||||
@UE: These are the (default) lower and upper threshold values for BLER and Throughput at the UE side.
|
||||
These threshold values can be further updated in run-time through the option 'Configs' in the drop-down list
|
||||
*/
|
||||
float Limits_KPI_ue[2][2] = {
|
||||
float Limits_KPI_ue[3][2] = {
|
||||
// {lower Limit, Upper Limit}
|
||||
{0.0, 0.8}, // DL BLER
|
||||
{0.2, 10} // Throughput in Mbs
|
||||
{0.2, 10}, // Throughput in Mbs
|
||||
{0,60} //psbch RSRP db/RE
|
||||
};
|
||||
|
||||
/* This class creates the window when choosing the option 'Configs' to configure the threshold values. */
|
||||
@@ -176,6 +177,9 @@ KPIListSelectUE::KPIListSelectUE(QWidget *parent) : QComboBox(parent)
|
||||
this->addItem("Time Adv.", static_cast<int>(PlotTypeUE::timingAdvance));
|
||||
|
||||
this->addItem("Configs", static_cast<int>(PlotTypeUE::config));
|
||||
this->addItem("LLR PSBCH", static_cast<int>(PlotTypeUE::psbchLLR));
|
||||
this->addItem("I/Q PSBCH", static_cast<int>(PlotTypeUE::psbchIQ));
|
||||
this->addItem("PSBCH RSRP dB/RE", static_cast<int>(PlotTypeUE::psbchRSRP));
|
||||
}
|
||||
|
||||
WaterFall::WaterFall(complex16 *values, NR_DL_FRAME_PARMS *frame_parms, QWidget *parent) : QWidget(parent), values(values), frame_parms(frame_parms)
|
||||
@@ -891,6 +895,8 @@ float PainterWidgetUE::getValue()
|
||||
case PlotTypeUE::timingAdvance:
|
||||
return (float)this->ue->timing_advance;
|
||||
|
||||
case PlotTypeUE::psbchRSRP:
|
||||
return (float)this->ue->SL_UE_PHY_PARAMS.psbch.rsrp_dB_per_RE;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
@@ -901,15 +907,22 @@ scopeGraphData_t *PainterWidgetUE::getPlotValue()
|
||||
{
|
||||
scopeData_t *scope = (scopeData_t *)this->ue->scopeData;
|
||||
scopeGraphData_t **data = (scopeGraphData_t **)scope->liveData;
|
||||
bool is_sl = this->ue->sl_mode;
|
||||
|
||||
switch (this->plotType) {
|
||||
case PlotTypeUE::CIR:
|
||||
return data[pbchDlChEstimateTime];
|
||||
return (is_sl ? data[psbchDlChEstimateTime] : data[pbchDlChEstimateTime]);
|
||||
|
||||
case PlotTypeUE::pbchLLR:
|
||||
return data[pbchLlr];
|
||||
case PlotTypeUE::pbchIQ:
|
||||
return data[pbchRxdataF_comp];
|
||||
|
||||
case PlotTypeUE::psbchLLR:
|
||||
return data[psbchLlr];
|
||||
case PlotTypeUE::psbchIQ:
|
||||
return data[psbchRxdataF_comp];
|
||||
|
||||
case PlotTypeUE::pdcchLLR:
|
||||
return data[pdcchLlr];
|
||||
|
||||
@@ -980,13 +993,14 @@ void PainterWidgetUE::makeConnections(int type)
|
||||
break;
|
||||
}
|
||||
case PlotTypeUE::CIR: {
|
||||
if (!data[pbchDlChEstimateTime]) {
|
||||
enum scopeDataType typ = (this->ue->sl_mode) ? psbchDlChEstimateTime : pbchDlChEstimateTime;
|
||||
if (!data[typ]) {
|
||||
newChart = new QChart();
|
||||
this->plotType = PlotTypeUE::empty;
|
||||
this->comboBox->setCurrentIndex(static_cast<int>(PlotTypeUE::empty));
|
||||
break;
|
||||
}
|
||||
newChart = new CIRPlot((complex16 *)(data[pbchDlChEstimateTime] + 1), data[pbchDlChEstimateTime]->lineSz);
|
||||
newChart = new CIRPlot((complex16 *)(data[typ] + 1), data[typ]->lineSz);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1010,6 +1024,26 @@ void PainterWidgetUE::makeConnections(int type)
|
||||
newChart = new IQPlotUE((complex16 *)(data[pbchRxdataF_comp] + 1), data[pbchRxdataF_comp]->lineSz, this);
|
||||
break;
|
||||
}
|
||||
case PlotTypeUE::psbchLLR: {
|
||||
if (!data[psbchLlr]) {
|
||||
newChart = new QChart();
|
||||
this->plotType = PlotTypeUE::empty;
|
||||
this->comboBox->setCurrentIndex(static_cast<int>(PlotTypeUE::empty));
|
||||
break;
|
||||
}
|
||||
newChart = new LLRPlotUE((int16_t *)(data[psbchLlr] + 1), data[psbchLlr]->lineSz, this);
|
||||
break;
|
||||
}
|
||||
case PlotTypeUE::psbchIQ: {
|
||||
if (!data[psbchRxdataF_comp]) {
|
||||
newChart = new QChart();
|
||||
this->plotType = PlotTypeUE::empty;
|
||||
this->comboBox->setCurrentIndex(static_cast<int>(PlotTypeUE::empty));
|
||||
break;
|
||||
}
|
||||
newChart = new IQPlotUE((complex16 *)(data[psbchRxdataF_comp] + 1), data[psbchRxdataF_comp]->lineSz, this);
|
||||
break;
|
||||
}
|
||||
case PlotTypeUE::pdcchLLR: {
|
||||
if (!data[pdcchLlr]) {
|
||||
newChart = new QChart();
|
||||
@@ -1079,7 +1113,10 @@ void PainterWidgetUE::makeConnections(int type)
|
||||
newChart = new KPIPlot(this);
|
||||
break;
|
||||
}
|
||||
|
||||
case PlotTypeUE::psbchRSRP: {
|
||||
newChart = new KPIPlot(this,Limits_KPI_ue[2]);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1164,6 +1201,7 @@ void *nrgNBQtscopeThread(void *arg)
|
||||
void *nrUEQtscopeThread(void *arg)
|
||||
{
|
||||
PHY_VARS_NR_UE *ue = (PHY_VARS_NR_UE *)arg;
|
||||
bool is_sl = ue->sl_mode;
|
||||
|
||||
sleep(1);
|
||||
|
||||
@@ -1197,14 +1235,16 @@ void *nrUEQtscopeThread(void *arg)
|
||||
mainLayout.addWidget(&pwidgetueCombo2, 1, 1);
|
||||
|
||||
KPIListSelectUE combo3;
|
||||
combo3.setCurrentIndex(static_cast<int>(PlotTypeUE::pbchLLR));
|
||||
if (is_sl) combo3.setCurrentIndex(static_cast<int>(PlotTypeUE::psbchLLR));
|
||||
else combo3.setCurrentIndex(static_cast<int>(PlotTypeUE::psbchLLR));
|
||||
PainterWidgetUE pwidgetueCombo3(&config, &combo3, ue);
|
||||
|
||||
mainLayout.addWidget(&combo3, 2, 0);
|
||||
mainLayout.addWidget(&pwidgetueCombo3, 3, 0);
|
||||
|
||||
KPIListSelectUE combo4;
|
||||
combo4.setCurrentIndex(static_cast<int>(PlotTypeUE::pbchIQ));
|
||||
if (is_sl) combo4.setCurrentIndex(static_cast<int>(PlotTypeUE::psbchIQ));
|
||||
else combo4.setCurrentIndex(static_cast<int>(PlotTypeUE::psbchIQ));
|
||||
PainterWidgetUE pwidgetueCombo4(&config, &combo4, ue);
|
||||
|
||||
mainLayout.addWidget(&combo4, 2, 1);
|
||||
|
||||
@@ -81,7 +81,10 @@ enum class PlotTypeUE {
|
||||
pdschRBs,
|
||||
frequencyOffset,
|
||||
timingAdvance,
|
||||
config
|
||||
config,
|
||||
psbchLLR,
|
||||
psbchIQ,
|
||||
psbchRSRP,
|
||||
};
|
||||
|
||||
/// This abstract class defines an interface how the KPIPlot class can access values for the different KPI plot types
|
||||
|
||||
@@ -771,14 +771,17 @@ static void ueTimeResponse (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int
|
||||
*/
|
||||
|
||||
static void ueChannelResponse (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
|
||||
enum scopeDataType typ = (phy_vars_ue->sl_mode) ? psbchDlChEstimateTime : pbchDlChEstimateTime;
|
||||
|
||||
// Channel Impulse Response
|
||||
if (!data[pbchDlChEstimateTime])
|
||||
if (!data[typ])
|
||||
return;
|
||||
|
||||
const scopeSample_t *tmp=(scopeSample_t *)(data[pbchDlChEstimateTime]+1);
|
||||
genericPowerPerAntena(graph, data[pbchDlChEstimateTime]->colSz,
|
||||
const scopeSample_t *tmp=(scopeSample_t *)(data[typ]+1);
|
||||
genericPowerPerAntena(graph, data[typ]->colSz,
|
||||
&tmp,
|
||||
data[pbchDlChEstimateTime]->lineSz);
|
||||
data[typ]->lineSz);
|
||||
}
|
||||
|
||||
static void ueFreqWaterFall (scopeGraphData_t **data, OAIgraph_t *graph,PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id ) {
|
||||
@@ -832,14 +835,17 @@ static void uePbchFrequencyResp (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue
|
||||
}
|
||||
*/
|
||||
static void uePbchLLR (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
|
||||
enum scopeDataType typ = (phy_vars_ue->sl_mode) ? psbchLlr : pbchLlr;
|
||||
|
||||
// PBCH LLRs
|
||||
if ( !data[pbchLlr])
|
||||
if ( !data[typ])
|
||||
return;
|
||||
|
||||
const int sz=data[pbchLlr]->lineSz;
|
||||
//const int antennas=data[pbchLlr]->colSz;
|
||||
const int sz=data[typ]->lineSz;
|
||||
//const int antennas=data[typ]->colSz;
|
||||
// We take the first antenna only for now
|
||||
int16_t *llrs = (int16_t *) (data[pbchLlr]+1);
|
||||
int16_t *llrs = (int16_t *) (data[typ]+1);
|
||||
float *llr_pbch=NULL, *bit_pbch=NULL;
|
||||
int nx = sz;
|
||||
#ifdef WEBSRVSCOPE
|
||||
@@ -855,12 +861,15 @@ static void uePbchLLR (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_
|
||||
}
|
||||
|
||||
static void uePbchIQ (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
||||
|
||||
enum scopeDataType typ = (phy_vars_ue->sl_mode) ? psbchRxdataF_comp : pbchRxdataF_comp;
|
||||
|
||||
// PBCH I/Q of MF Output
|
||||
if (!data[pbchRxdataF_comp])
|
||||
if (!data[typ])
|
||||
return;
|
||||
|
||||
scopeSample_t *pbch_comp = (scopeSample_t *) (data[pbchRxdataF_comp]+1);
|
||||
const int sz=data[pbchRxdataF_comp]->lineSz;
|
||||
scopeSample_t *pbch_comp = (scopeSample_t *) (data[typ]+1);
|
||||
const int sz=data[typ]->lineSz;
|
||||
int newsz = sz;
|
||||
float *I=NULL, *Q=NULL;
|
||||
#ifdef WEBSRVSCOPE
|
||||
|
||||
@@ -67,6 +67,9 @@ enum scopeDataType {
|
||||
pdschRxdataF_comp,
|
||||
commonRxdataF,
|
||||
gNBRxdataF,
|
||||
psbchDlChEstimateTime,
|
||||
psbchLlr,
|
||||
psbchRxdataF_comp,
|
||||
MAX_SCOPE_TYPES
|
||||
};
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
#include <execinfo.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/sysinfo.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define __PHY_DEFS_GNB__H__
|
||||
|
||||
#include "defs_nr_common.h"
|
||||
#include "defs_nr_UE.h"
|
||||
#include "CODING/nrPolar_tools/nr_polar_pbch_defs.h"
|
||||
#include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
@@ -43,6 +44,7 @@
|
||||
#include "PHY/CODING/nrLDPC_decoder/nrLDPC_types.h"
|
||||
#include "executables/rt_profiling.h"
|
||||
#include "nfapi_nr_interface_scf.h"
|
||||
#include "sidelink_nr_ue_interface.h"
|
||||
|
||||
#define MAX_NUM_RU_PER_gNB 8
|
||||
#define MAX_PUCCH0_NID 8
|
||||
@@ -188,6 +190,10 @@ typedef struct {
|
||||
typedef struct {
|
||||
/// Nfapi ULSCH PDU
|
||||
nfapi_nr_pusch_pdu_t ulsch_pdu;
|
||||
/// PSSCH PDU
|
||||
sl_nr_rx_config_pssch_sci_pdu_t *pssch_pdu;
|
||||
/// SLSCH PDU
|
||||
sl_nr_rx_config_pssch_pdu_t *slsch_pdu;
|
||||
/// Index of current HARQ round for this DLSCH
|
||||
uint8_t round;
|
||||
bool new_rx;
|
||||
@@ -264,7 +270,7 @@ typedef struct {
|
||||
int pusch_delay_max_val;
|
||||
} NR_ULSCH_delay_t;
|
||||
|
||||
typedef struct {
|
||||
typedef struct NR_gNB_ULSCH_s {
|
||||
uint32_t frame;
|
||||
uint32_t slot;
|
||||
/// Pointers to 16 HARQ processes for the ULSCH
|
||||
@@ -325,7 +331,7 @@ typedef struct {
|
||||
} NR_gNB_COMMON;
|
||||
|
||||
|
||||
typedef struct {
|
||||
typedef struct NR_gNB_PUSCH_s {
|
||||
/// \brief Holds the received data in the frequency domain for the allocated RBs in repeated format.
|
||||
/// - first index: rx antenna id [0..nb_antennas_rx[
|
||||
/// - second index: ? [0..2*ofdm_symbol_size[
|
||||
@@ -548,7 +554,7 @@ typedef struct gNB_L1_proc_t_s {
|
||||
gNB_L1_rxtx_proc_t L1_proc, L1_proc_tx;
|
||||
} gNB_L1_proc_t;
|
||||
|
||||
typedef struct {
|
||||
typedef struct PHY_MEASUREMENTS_gNB_s {
|
||||
// common measurements
|
||||
//! estimated noise power (linear)
|
||||
unsigned int n0_power[MAX_NUM_RU_PER_gNB];
|
||||
@@ -782,6 +788,7 @@ typedef struct PHY_VARS_gNB_s {
|
||||
|
||||
typedef struct LDPCDecode_s {
|
||||
PHY_VARS_gNB *gNB;
|
||||
struct PHY_VARS_NR_UE_s *UE;
|
||||
NR_UL_gNB_HARQ_t *ulsch_harq;
|
||||
t_nrLDPC_dec_params decoderParms;
|
||||
NR_gNB_ULSCH_t *ulsch;
|
||||
|
||||
@@ -37,8 +37,10 @@
|
||||
#define _Atomic(X) std::atomic< X >
|
||||
#endif
|
||||
|
||||
#include "defs_nr_common.h"
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "CODING/nrPolar_tools/nr_polar_pbch_defs.h"
|
||||
#include "PHY/defs_nr_sl_UE.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -48,6 +50,7 @@
|
||||
#include "common_lib.h"
|
||||
#include "fapi_nr_ue_interface.h"
|
||||
#include "assertions.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef MEX
|
||||
#define msg mexPrintf
|
||||
@@ -94,6 +97,8 @@
|
||||
|
||||
#include "impl_defs_top.h"
|
||||
#include "impl_defs_nr.h"
|
||||
// This is for ULSCH RX structures used for Sidelink
|
||||
#include "defs_gNB.h"
|
||||
#include "time_meas.h"
|
||||
#include "PHY/CODING/coding_defs.h"
|
||||
#include "PHY/TOOLS/tools_defs.h"
|
||||
@@ -108,6 +113,14 @@
|
||||
#include "radio/COMMON/common_lib.h"
|
||||
#include "NR_IF_Module.h"
|
||||
|
||||
#define MAX_PUCCH0_NID 8
|
||||
|
||||
typedef struct {
|
||||
int nb_id;
|
||||
int Nid[MAX_PUCCH0_NID];
|
||||
int lut[MAX_PUCCH0_NID][160][14];
|
||||
} NR_UE_PUCCH0_LUT_t;
|
||||
|
||||
/// Context data structure for gNB subframe processing
|
||||
typedef struct {
|
||||
/// Component Carrier index
|
||||
@@ -309,7 +322,7 @@ typedef struct {
|
||||
#define NR_PSBCH_MAX_NB_MOD_SYMBOLS 99
|
||||
#define NR_PSBCH_DMRS_LENGTH 297 // in mod symbols
|
||||
#define NR_PSBCH_DMRS_LENGTH_DWORD 20 // ceil(2(QPSK)*NR_PBCH_DMRS_LENGTH/32)
|
||||
|
||||
#define NR_SLSCH_RX_MAX 2
|
||||
/* NR Sidelink PSBCH payload fields
|
||||
TODO: This will be removed in the future and
|
||||
filled in by the upper layers once developed. */
|
||||
@@ -362,7 +375,7 @@ typedef struct UE_NR_SCAN_INFO_s {
|
||||
} UE_NR_SCAN_INFO_t;
|
||||
|
||||
/// Top-level PHY Data Structure for UE
|
||||
typedef struct {
|
||||
typedef struct PHY_VARS_NR_UE_s {
|
||||
/// \brief Module ID indicator for this instance
|
||||
uint8_t Mod_id;
|
||||
/// \brief Component carrier ID for this PHY instance
|
||||
@@ -435,7 +448,7 @@ typedef struct {
|
||||
uint8_t prs_active_gNBs;
|
||||
NR_DL_UE_HARQ_t dl_harq_processes[2][NR_MAX_DLSCH_HARQ_PROCESSES];
|
||||
NR_UL_UE_HARQ_t ul_harq_processes[NR_MAX_ULSCH_HARQ_PROCESSES];
|
||||
|
||||
NR_UL_UE_HARQ_t sl_harq_processes[NR_MAX_SLSCH_HARQ_PROCESSES];
|
||||
//Paging parameters
|
||||
uint32_t IMSImod1024;
|
||||
uint32_t PF;
|
||||
@@ -649,6 +662,25 @@ typedef struct {
|
||||
notifiedFIFO_t phy_config_ind;
|
||||
notifiedFIFO_t *tx_resume_ind_fifo[NR_MAX_SLOTS_PER_FRAME];
|
||||
int tx_wait_for_dlsch[NR_MAX_SLOTS_PER_FRAME];
|
||||
|
||||
//Sidelink parameters
|
||||
sl_nr_sidelink_mode_t sl_mode;
|
||||
sl_nr_ue_phy_params_t SL_UE_PHY_PARAMS;
|
||||
struct PHY_MEASUREMENTS_gNB_s *sl_measurements;
|
||||
int max_nb_slsch;
|
||||
// we use the gNB ULSCH context for SLSCH reception
|
||||
struct NR_gNB_ULSCH_s *slsch;
|
||||
struct NR_gNB_PUSCH_s *pssch_vars;
|
||||
bool phy_config_request_sent;
|
||||
int pscch_dmrs_gold_init;
|
||||
/// PDCCH DMRS for TX
|
||||
uint32_t ***nr_gold_pscch_dmrs;
|
||||
/// PSCCH DMRS for RX
|
||||
uint32_t ***nr_gold_pscch;
|
||||
/// PSSCH signal detection threshold
|
||||
int pssch_thres;
|
||||
// PUCCH0 Look-up table for cyclic-shifts
|
||||
NR_UE_PUCCH0_LUT_t pucch0_lut;
|
||||
} PHY_VARS_NR_UE;
|
||||
|
||||
typedef struct {
|
||||
@@ -670,11 +702,27 @@ typedef struct {
|
||||
typedef struct nr_phy_data_tx_s {
|
||||
NR_UE_ULSCH_t ulsch;
|
||||
NR_UE_PUCCH pucch_vars;
|
||||
|
||||
//Sidelink Tx action decided by MAC
|
||||
sl_nr_tx_config_type_enum_t sl_tx_action;
|
||||
sl_nr_tx_config_psbch_pdu_t psbch_vars;
|
||||
sl_nr_tx_config_pscch_pssch_pdu_t nr_sl_pssch_pscch_pdu;
|
||||
uint32_t pscch_Nid;
|
||||
} nr_phy_data_tx_t;
|
||||
|
||||
typedef struct nr_phy_data_s {
|
||||
bool active;
|
||||
NR_UE_PDCCH_CONFIG phy_pdcch_config;
|
||||
NR_UE_DLSCH_t dlsch[2];
|
||||
|
||||
//Sidelink Rx action decided by MAC
|
||||
sl_nr_rx_config_type_enum_t sl_rx_action;
|
||||
sl_nr_rx_config_pscch_pdu_t nr_sl_pscch_pdu;
|
||||
sl_nr_rx_config_pssch_sci_pdu_t nr_sl_pssch_sci_pdu;
|
||||
sl_nr_rx_config_pssch_pdu_t nr_sl_pssch_pdu;
|
||||
sl_nr_tti_csi_rs_pdu_t nr_sl_csi_rs_pdu;
|
||||
sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu_list;
|
||||
uint8_t num_psfch_pdus;
|
||||
} nr_phy_data_t;
|
||||
/* this structure is used to pass both UE phy vars and
|
||||
* proc to the function UE_thread_rxn_txnp4
|
||||
|
||||
@@ -169,8 +169,6 @@ struct NR_DL_FRAME_PARMS {
|
||||
/// Frame type (0 FDD, 1 TDD)
|
||||
frame_type_t frame_type;
|
||||
uint8_t tdd_config;
|
||||
/// Sidelink Cell ID
|
||||
uint16_t Nid_SL;
|
||||
/// Cell ID
|
||||
uint16_t Nid_cell;
|
||||
/// subcarrier spacing (15,30,60,120)
|
||||
@@ -306,4 +304,34 @@ typedef struct {
|
||||
#define KHz (1000UL)
|
||||
#define MHz (1000*KHz)
|
||||
|
||||
static const int16_t idft12_re[12][12] = {
|
||||
{23170,23170,23170,23170,23170,23170,23170,23170,23170,23170,23170,23170},
|
||||
{23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585,0,11585,20066},
|
||||
{23170,11585,-11585,-23170,-11585,11585,23170,11585,-11585,-23170,-11585,11585},
|
||||
{23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170,0},
|
||||
{23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585},
|
||||
{23170,-20066,11585,0,-11585,20066,-23170,20066,-11585,0,11585,-20066},
|
||||
{23170,-23170,23170,-23170,23170,-23170,23170,-23170,23170,-23170,23170,-23170},
|
||||
{23170,-20066,11585,0,-11585,20066,-23170,20066,-11585,0,11585,-20066},
|
||||
{23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585},
|
||||
{23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170,0},
|
||||
{23170,11585,-11585,-23170,-11585,11585,23170,11585,-11585,-23170,-11585,11585},
|
||||
{23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585,0,11585,20066}
|
||||
};
|
||||
|
||||
static const int16_t idft12_im[12][12] = {
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0},
|
||||
{0,11585,20066,23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585},
|
||||
{0,20066,20066,0,-20066,-20066,0,20066,20066,0,-20066,-20066},
|
||||
{0,23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170},
|
||||
{0,20066,-20066,0,20066,-20066,0,20066,-20066,0,20066,-20066},
|
||||
{0,11585,-20066,23170,-20066,11585,0,-11585,20066,-23170,20066,-11585},
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0},
|
||||
{0,-11585,20066,-23170,20066,-11585,0,11585,-20066,23170,-20066,11585},
|
||||
{0,-20066,20066,0,-20066,20066,0,-20066,20066,0,-20066,20066},
|
||||
{0,-23170,0,23170,0,-23170,0,23170,0,-23170,0,23170},
|
||||
{0,-20066,-20066,0,20066,20066,0,-20066,-20066,0,20066,20066},
|
||||
{0,-11585,-20066,-23170,-20066,-11585,0,11585,20066,23170,20066,11585}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
223
openair1/PHY/defs_nr_sl_UE.h
Normal file
223
openair1/PHY/defs_nr_sl_UE.h
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* 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 PHY/defs_nr_sl_UE.h
|
||||
\brief Top-level defines and structure definitions
|
||||
\author
|
||||
\date
|
||||
\version
|
||||
\company Fraunhofer
|
||||
\email:
|
||||
\note
|
||||
\warning
|
||||
*/
|
||||
|
||||
#ifndef _DEFS_NR_SL_UE_H_
|
||||
#define _DEFS_NR_SL_UE_H_
|
||||
|
||||
|
||||
|
||||
#include "PHY/types.h"
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "nfapi/open-nFAPI/nfapi/public_inc/sidelink_nr_ue_interface.h"
|
||||
#include "common/utils/time_meas.h"
|
||||
|
||||
|
||||
// (33*(13-4))
|
||||
// Normal CP - NUM_SSB_Symbols = 13. 4 symbols for PSS, SSS
|
||||
#define SL_NR_NUM_PSBCH_DMRS_RE 297
|
||||
//ceil(2(QPSK)*SL_NR_NUM_PSBCH_DMRS_RE/32)
|
||||
#define SL_NR_NUM_PSBCH_DMRS_RE_DWORD 20
|
||||
//11 RBs for PSBCH in one symbol * 12 REs
|
||||
#define SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL 132
|
||||
//3 DMRS REs per RB * 11 RBS in one symbol
|
||||
#define SL_NR_NUM_PSBCH_DMRS_RE_IN_ONE_SYMBOL 33
|
||||
//9 PSBCH DATA REs * 11 RBS in one symbol
|
||||
#define SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL 99
|
||||
#define SL_NR_NUM_PSBCH_RBS_IN_ONE_SYMBOL 11
|
||||
// SL_NR_POLAR_PSBCH_E_NORMAL_CP/2 bits because QPSK used for PSBCH.
|
||||
// 11 * (12-3 DMRS REs) * 9 symbols for PSBCH
|
||||
#define SL_NR_NUM_PSBCH_MODULATED_SYMBOLS 891
|
||||
#define SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_RB 9
|
||||
#define SL_NR_NUM_PSBCH_DMRS_RE_IN_ONE_RB 3
|
||||
// 11 * (12-3 DMRS REs) * 9 symbols for PSBCH
|
||||
#define SL_NR_NUM_PSBCH_DATA_RE_IN_ALL_SYMBOLS 891
|
||||
|
||||
|
||||
|
||||
#define SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP 13
|
||||
#define SL_NR_NUM_SYMBOLS_SSB_EXT_CP 11
|
||||
#define SL_NR_NUM_PSS_SYMBOLS 2
|
||||
#define SL_NR_NUM_SSS_SYMBOLS 2
|
||||
#define SL_NR_PSS_START_SYMBOL 1
|
||||
#define SL_NR_SSS_START_SYMBOL 3
|
||||
#define SL_NR_NUM_PSS_OR_SSS_SYMBOLS 2
|
||||
#define SL_NR_PSS_SEQUENCE_LENGTH 127
|
||||
#define SL_NR_SSS_SEQUENCE_LENGTH 127
|
||||
#define SL_NR_NUM_IDs_IN_PSS 2
|
||||
#define SL_NR_NUM_IDs_IN_SSS 336
|
||||
#define SL_NR_NUM_SLSS_IDs 672
|
||||
#define SL_NR_PSBCH_REPETITION_IN_FRAMES 16
|
||||
|
||||
typedef enum sl_nr_sidelink_mode {
|
||||
SL_NOT_SUPPORTED = 0,
|
||||
SL_MODE1_SUPPORTED,
|
||||
SL_MODE2_SUPPORTED
|
||||
} sl_nr_sidelink_mode_t;
|
||||
|
||||
//(11*(12-3 DMRS REs) * 2 (QPSK used)
|
||||
#define SL_NR_NUM_PSBCH_DATA_BITS_IN_ONE_SYMBOL 198
|
||||
|
||||
typedef struct SL_NR_UE_INIT_PARAMS {
|
||||
|
||||
//gold sequences for PSBCH DMRS
|
||||
uint32_t psbch_dmrs_gold_sequences[SL_NR_NUM_SLSS_IDs][SL_NR_NUM_PSBCH_DMRS_RE_DWORD]; // Gold sequences for PSBCH DMRS
|
||||
|
||||
//PSBCH DMRS QPSK modulated symbols for all possible SLSS Ids
|
||||
struct complex16 psbch_dmrs_modsym[SL_NR_NUM_SLSS_IDs][SL_NR_NUM_PSBCH_DMRS_RE];
|
||||
|
||||
// Scaled values
|
||||
int16_t sl_pss[SL_NR_NUM_IDs_IN_PSS][SL_NR_PSS_SEQUENCE_LENGTH];
|
||||
int16_t sl_sss[SL_NR_NUM_SLSS_IDs][SL_NR_SSS_SEQUENCE_LENGTH];
|
||||
|
||||
// Contains Not scaled values just the simple generated sequence
|
||||
int16_t sl_pss_for_sync[SL_NR_NUM_IDs_IN_PSS][SL_NR_PSS_SEQUENCE_LENGTH];
|
||||
int16_t sl_sss_for_sync[SL_NR_NUM_SLSS_IDs][SL_NR_SSS_SEQUENCE_LENGTH];
|
||||
|
||||
int32_t **sl_pss_for_correlation; // IFFT samples for correlation
|
||||
|
||||
} SL_NR_UE_INIT_PARAMS_t;
|
||||
|
||||
typedef struct SL_NR_SYNC_PARAMS {
|
||||
|
||||
// Indicating start of SSB block in the initial set of samples
|
||||
uint32_t ssb_offset;
|
||||
// Freq Offset calculated
|
||||
int32_t freq_offset;
|
||||
|
||||
uint32_t remaining_frames;
|
||||
uint32_t rx_offset;
|
||||
uint32_t slot_offset;
|
||||
uint16_t N_sl_id2; //id2 determined from PSS during sync ref UE selection
|
||||
uint16_t N_sl_id1; //id2 determined from SSS during sync ref UE selection
|
||||
uint16_t N_sl_id; //ID calculated from ID1 and ID2
|
||||
int32_t psbch_rsrp; //rsrp of the decoded psbch during sync ref ue selection
|
||||
uint32_t DFN; // DFN calculated after sync ref UE search
|
||||
|
||||
} SL_NR_SYNC_PARAMS_t;
|
||||
|
||||
typedef struct SL_NR_UE_PSSCH {
|
||||
|
||||
// AVG POWER OF PSSCH DMRS in dB/RE
|
||||
int16_t rsrp_dB_per_RE;
|
||||
// AVG POWER OF PSSCH DMRS in dBm/RE
|
||||
int16_t rsrp_dBm_per_RE;
|
||||
|
||||
// STATS - CRC Errors observed during PSSCH reception (per HARQ round)
|
||||
uint32_t rx_errors[8];
|
||||
|
||||
// STATS - CRC Errors observed during PSSCH SCI2 reception
|
||||
uint32_t rx_sci2_errors;
|
||||
|
||||
// STATS - Receptions with CRC OK
|
||||
uint32_t rx_ok;
|
||||
|
||||
// STATS - Receptions with CRC OK
|
||||
uint32_t rx_sci2_ok;
|
||||
|
||||
// STATS - transmissions of PSSCH by the UE
|
||||
uint32_t num_pssch_tx;
|
||||
|
||||
// STATS - transmissions of PSSCH by the UE
|
||||
uint32_t num_pssch_sci2_tx;
|
||||
} SL_NR_UE_PSSCH_t;
|
||||
|
||||
typedef struct SL_NR_UE_PSCCH {
|
||||
|
||||
// AVG POWER OF PSCCH DMRS in dB/RE
|
||||
int16_t rsrp_dB_per_RE;
|
||||
// AVG POWER OF PSCCH DMRS in dBm/RE
|
||||
int16_t rsrp_dBm_per_RE;
|
||||
|
||||
// STATS - Receptions with CRC OK
|
||||
uint32_t rx_ok;
|
||||
|
||||
// STATS - transmissions of PSBCH by the UE
|
||||
uint32_t num_pscch_tx;
|
||||
|
||||
} SL_NR_UE_PSCCH_t;
|
||||
|
||||
typedef struct SL_NR_UE_PSBCH {
|
||||
|
||||
// AVG POWER OF PSBCH DMRS in dB/RE
|
||||
int16_t rsrp_dB_per_RE;
|
||||
// AVG POWER OF PSBCH DMRS in dBm/RE
|
||||
int16_t rsrp_dBm_per_RE;
|
||||
|
||||
// STATS - CRC Errors observed during PSBCH reception
|
||||
uint32_t rx_errors;
|
||||
|
||||
// STATS - Receptions with CRC OK
|
||||
uint32_t rx_ok;
|
||||
|
||||
// STATS - transmissions of PSBCH by the UE
|
||||
uint32_t num_psbch_tx;
|
||||
|
||||
} SL_NR_UE_PSBCH_t;
|
||||
|
||||
typedef struct SL_NR_UE_PSFCH {
|
||||
// STATS - transmissions of PSFCH by the UE
|
||||
uint32_t num_psfch_tx;
|
||||
uint32_t num_psfch_rx;
|
||||
} SL_NR_UE_PSFCH_t;
|
||||
|
||||
typedef struct sl_nr_ue_phy_params {
|
||||
|
||||
SL_NR_UE_INIT_PARAMS_t init_params;
|
||||
|
||||
SL_NR_SYNC_PARAMS_t sync_params;
|
||||
|
||||
// sidelink phy parameters used for psbch reception/txn
|
||||
SL_NR_UE_PSBCH_t psbch;
|
||||
|
||||
// sidelink phy parameters used for pscch reception/txn
|
||||
SL_NR_UE_PSCCH_t pscch;
|
||||
|
||||
// sidelink phy parameters used for pssch reception/txn
|
||||
SL_NR_UE_PSSCH_t pssch;
|
||||
|
||||
// sidelink phy parameters used for psfch reception/txn
|
||||
SL_NR_UE_PSFCH_t psfch;
|
||||
|
||||
//Configuration parameters from MAC
|
||||
sl_nr_phy_config_request_t sl_config;
|
||||
|
||||
NR_DL_FRAME_PARMS sl_frame_params;
|
||||
|
||||
time_stats_t phy_proc_sl_tx;
|
||||
time_stats_t phy_proc_sl_rx;
|
||||
time_stats_t channel_estimation_stats;
|
||||
time_stats_t ue_sl_indication_stats;
|
||||
|
||||
} sl_nr_ue_phy_params_t;
|
||||
|
||||
|
||||
#endif
|
||||
@@ -98,6 +98,8 @@ SystemInformationBlockType1_nr_t;
|
||||
#define NR_DOWNLINK_SLOT (0x01)
|
||||
#define NR_UPLINK_SLOT (0x02)
|
||||
#define NR_MIXED_SLOT (0x03)
|
||||
#define NR_SIDELINK_SLOT (0x04)
|
||||
#define NON_NR_SIDELINK_SLOT (0x05)
|
||||
|
||||
#define FRAME_DURATION_MICRO_SEC (10000) /* frame duration in microsecond */
|
||||
|
||||
|
||||
@@ -270,7 +270,7 @@
|
||||
/* FFS_NR_TODO it defines ue capability which is the number of slots */
|
||||
/* - between reception of pdsch and tarnsmission of its acknowlegment */
|
||||
/* - between reception of un uplink grant and its related transmission */
|
||||
#define NR_UE_CAPABILITY_SLOT_RX_TO_TX (3)
|
||||
#define NR_UE_CAPABILITY_SLOT_RX_TO_TX (4)
|
||||
|
||||
#ifndef NO_RAT_NR
|
||||
#define DURATION_RX_TO_TX (NR_UE_CAPABILITY_SLOT_RX_TO_TX) /* for NR this will certainly depends to such UE capability which is not yet defined */
|
||||
@@ -280,6 +280,7 @@
|
||||
|
||||
#define NR_MAX_ULSCH_HARQ_PROCESSES (NR_MAX_HARQ_PROCESSES) /* cf 38.214 6.1 UE procedure for receiving the physical uplink shared channel */
|
||||
#define NR_MAX_DLSCH_HARQ_PROCESSES (NR_MAX_HARQ_PROCESSES) /* cf 38.214 5.1 UE procedure for receiving the physical downlink shared channel */
|
||||
#define NR_MAX_SLSCH_HARQ_PROCESSES (NR_MAX_HARQ_PROCESSES)
|
||||
#endif
|
||||
|
||||
/// Data structure for transmission.
|
||||
|
||||
@@ -281,7 +281,7 @@ static void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
|
||||
ulsch->active = false;
|
||||
ulsch_harq->round = 0;
|
||||
LOG_D(PHY, "ULSCH received ok \n");
|
||||
nr_fill_indication(gNB, ulsch->frame, ulsch->slot, rdata->ulsch_id, rdata->harq_pid, 0, 0);
|
||||
nr_fill_indication((void*)gNB, ulsch->frame, ulsch->slot, rdata->ulsch_id, rdata->harq_pid, 0, 0);
|
||||
//dumpsig=1;
|
||||
} else {
|
||||
LOG_D(PHY,
|
||||
@@ -301,7 +301,7 @@ static void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
|
||||
r);
|
||||
ulsch->handled = 1;
|
||||
LOG_D(PHY, "ULSCH %d in error\n",rdata->ulsch_id);
|
||||
nr_fill_indication(gNB, ulsch->frame, ulsch->slot, rdata->ulsch_id, rdata->harq_pid, 1, 0);
|
||||
nr_fill_indication((void*)gNB, ulsch->frame, ulsch->slot, rdata->ulsch_id, rdata->harq_pid, 1, 0);
|
||||
// dumpsig=1;
|
||||
}
|
||||
ulsch->last_iteration_cnt = rdata->decodeIterations;
|
||||
@@ -406,14 +406,15 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int
|
||||
|
||||
start_meas(&gNB->ulsch_decoding_stats);
|
||||
int nbDecode =
|
||||
nr_ulsch_decoding(gNB, ULSCH_id, gNB->pusch_vars[ULSCH_id].llr, frame_parms, pusch_pdu, frame_rx, slot_rx, harq_pid, G);
|
||||
nr_ulsch_decoding(gNB, NULL, ULSCH_id, gNB->pusch_vars[ULSCH_id].llr, frame_parms, pusch_pdu, frame_rx, slot_rx, harq_pid, G, NULL, NULL, NULL, -1);
|
||||
stop_meas(&gNB->ulsch_decoding_stats);
|
||||
return nbDecode;
|
||||
}
|
||||
|
||||
|
||||
void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, uint8_t harq_pid, uint8_t crc_flag, int dtx_flag)
|
||||
void nr_fill_indication(void* p, int frame, int slot_rx, int ULSCH_id, uint8_t harq_pid, uint8_t crc_flag, int dtx_flag)
|
||||
{
|
||||
PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)p;
|
||||
if (!get_softmodem_params()->reorder_thread_disable)
|
||||
pthread_mutex_lock(&gNB->UL_INFO_mutex);
|
||||
|
||||
@@ -889,7 +890,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH, 1);
|
||||
start_meas(&gNB->rx_pusch_stats);
|
||||
nr_rx_pusch(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid);
|
||||
nr_rx_pusch(gNB, NULL, gNB->common_vars.rxdataF, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid);
|
||||
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ULSCH_id];
|
||||
pusch_vars->ulsch_power_tot = 0;
|
||||
pusch_vars->ulsch_noise_power_tot = 0;
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#define __openair_SCHED_H__
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/*enum THREAD_INDEX { OPENAIR_THREAD_INDEX = 0,
|
||||
TOP_LEVEL_SCHEDULER_THREAD_INDEX,
|
||||
@@ -181,15 +181,52 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
|
||||
int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int pscch_flag,
|
||||
int32_t pdcch_est_size,
|
||||
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
|
||||
nr_phy_data_t *phy_data,
|
||||
int n_ss,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
|
||||
int16_t *rsrp_dBm);
|
||||
|
||||
int nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
int get_nRECSI_RS(uint8_t freq_density,
|
||||
uint16_t nr_of_rbs);
|
||||
|
||||
void psbch_pscch_pssch_processing(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
nr_phy_data_t *phy_data);
|
||||
int phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
nr_phy_data_tx_t *phy_data);
|
||||
/*! \brief This function prepares the sl indication to pass to the MAC
|
||||
*/
|
||||
void nr_fill_sl_indication(nr_sidelink_indication_t *sl_ind,
|
||||
sl_nr_rx_indication_t *rx_ind,
|
||||
sl_nr_sci_indication_t *sci_ind,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
void *phy_data);
|
||||
void nr_fill_sl_rx_indication(sl_nr_rx_indication_t *rx_ind,
|
||||
uint8_t pdu_type,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
uint16_t n_pdus,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
void *typeSpecific,
|
||||
uint16_t rx_slss_id);
|
||||
|
||||
void nr_postDecode_slsch(PHY_VARS_NR_UE *UE, notifiedFIFO_elt_t *req,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
nr_phy_data_t *phy_data,
|
||||
int8_t *ack_nack_rcvd,
|
||||
uint8_t num_acks);
|
||||
|
||||
typedef struct {
|
||||
ldpcDecode_t *rdata;
|
||||
bool rxok;
|
||||
} slsch_status_t;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -389,7 +389,12 @@ void configure_ta_command(PHY_VARS_NR_UE *ue, fapi_nr_ta_command_pdu *ta_command
|
||||
int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){
|
||||
|
||||
bool found = false;
|
||||
|
||||
if(scheduled_response != NULL){
|
||||
if (scheduled_response->sl_rx_config || scheduled_response->sl_tx_config) {
|
||||
sl_handle_scheduled_response(scheduled_response);
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_id_t module_id = scheduled_response->module_id;
|
||||
uint8_t cc_id = scheduled_response->CC_id;
|
||||
@@ -661,3 +666,141 @@ void nr_ue_synch_request(nr_synch_request_t *synch_request)
|
||||
PHY_vars_UE_g[synch_request->Mod_id][synch_request->CC_id]->synch_request.received_synch_request = 1;
|
||||
}
|
||||
|
||||
int8_t nr_ue_sl_phy_config_request(nr_sl_phy_config_t *phy_config)
|
||||
{
|
||||
sl_nr_phy_config_request_t *sl_config = &PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->SL_UE_PHY_PARAMS.sl_config;
|
||||
if(phy_config != NULL) {
|
||||
memcpy(sl_config,&phy_config->sl_config_req,sizeof(sl_nr_phy_config_request_t));
|
||||
PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->phy_config_request_sent = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* MAC sends the scheduled response with either TX configrequest for Sidelink Transmission requests
|
||||
* or RX config request for Sidelink Reception requests.
|
||||
* This procedure handles these TX/RX config requests received in this slot and configures PHY
|
||||
* with a TTI action to be performed in this slot(TTI)
|
||||
*/
|
||||
int8_t sl_handle_scheduled_response(nr_scheduled_response_t *scheduled_response) {
|
||||
|
||||
module_id_t module_id = scheduled_response->module_id;
|
||||
uint8_t cc_id = scheduled_response->CC_id;
|
||||
uint32_t slot = scheduled_response->slot;
|
||||
uint32_t frame = scheduled_response->frame;
|
||||
const char *sl_rx_action[] = {"NONE", "RX_PSBCH", "RX_PSCCH", "RX_SCI2_ON_PSSCH", "RX_SLSCH_ON_PSSCH", "RX_PSFCH", "RX_SLSCH_ON_PSSCH_CSI_RS"};
|
||||
const char *sl_tx_action[] = {"TX_PSBCH", "TX_PSCCH_PSSCH", "TX_PSCCH_PSSCH_PSFCH", "TX_PSCCH_PSSCH_CSI_RS"};
|
||||
NR_UE_CSI_RS *csirs_vars = PHY_vars_UE_g[module_id][cc_id]->csirs_vars[0];
|
||||
if(scheduled_response->sl_rx_config != NULL) {
|
||||
|
||||
sl_nr_rx_config_request_t *sl_rx_config = scheduled_response->sl_rx_config;
|
||||
nr_phy_data_t *phy_data = (nr_phy_data_t *)scheduled_response->phy_data;
|
||||
sl_nr_tti_csi_rs_pdu_t *csirs_config_pdu;
|
||||
AssertFatal(sl_rx_config->number_pdus == SL_NR_RX_CONFIG_LIST_NUM,
|
||||
"sl_rx_config->number_pdus incorrect\n");
|
||||
|
||||
switch(sl_rx_config->sl_rx_config_list[0].pdu_type) {
|
||||
|
||||
case SL_NR_CONFIG_TYPE_RX_PSBCH:
|
||||
phy_data->sl_rx_action = SL_NR_CONFIG_TYPE_RX_PSBCH;
|
||||
LOG_D(PHY, "Recvd CONFIG_TYPE_RX_PSBCH\n");
|
||||
break;
|
||||
case SL_NR_CONFIG_TYPE_RX_PSCCH:
|
||||
phy_data->sl_rx_action = SL_NR_CONFIG_TYPE_RX_PSCCH;
|
||||
phy_data->nr_sl_pscch_pdu = sl_rx_config->sl_rx_config_list[0].rx_pscch_config_pdu;
|
||||
LOG_D(NR_PHY, "Recvd CONFIG_TYPE_RX_PSCCH\n");
|
||||
break;
|
||||
case SL_NR_CONFIG_TYPE_RX_PSSCH_SCI:
|
||||
phy_data->sl_rx_action = SL_NR_CONFIG_TYPE_RX_PSSCH_SCI;
|
||||
phy_data->nr_sl_pssch_sci_pdu = sl_rx_config->sl_rx_config_list[0].rx_sci2_config_pdu;
|
||||
LOG_D(NR_PHY, "Recvd CONFIG_TYPE_RX_PSSCH_SCI\n");
|
||||
break;
|
||||
case SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH:
|
||||
case SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_PSFCH:
|
||||
case SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_CSI_RS:
|
||||
phy_data->sl_rx_action = sl_rx_config->sl_rx_config_list[0].pdu_type;
|
||||
phy_data->nr_sl_pssch_pdu = sl_rx_config->sl_rx_config_list[0].rx_pssch_config_pdu;
|
||||
LOG_D(NR_PHY, "%4d.%2d Recvd %s\n", frame, slot, sl_rx_action[phy_data->sl_rx_action]);
|
||||
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_CSI_RS) {
|
||||
csirs_config_pdu = &sl_rx_config->sl_rx_config_list[0].rx_csi_rs_config_pdu;
|
||||
memcpy((void*)&(csirs_vars->csirs_config_pdu), (void*)csirs_config_pdu, sizeof(sl_nr_tti_csi_rs_pdu_t));
|
||||
csirs_vars->active = true;
|
||||
}
|
||||
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_PSFCH) {
|
||||
phy_data->psfch_pdu_list = calloc(sl_rx_config->sl_rx_config_list[0].num_psfch_pdus, sizeof(sl_nr_tx_rx_config_psfch_pdu_t));
|
||||
memcpy((void*)phy_data->psfch_pdu_list, (void*)sl_rx_config->sl_rx_config_list[0].rx_psfch_pdu_list,
|
||||
sl_rx_config->sl_rx_config_list[0].num_psfch_pdus * sizeof(sl_nr_tx_rx_config_psfch_pdu_t));
|
||||
phy_data->num_psfch_pdus = sl_rx_config->sl_rx_config_list[0].num_psfch_pdus;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
AssertFatal(0,"Incorrect sl_rx config req pdutype \n");
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_D(PHY, "[UE%d] TTI %d:%d, SL-RX action:%s\n",
|
||||
module_id,frame,slot,
|
||||
sl_rx_action[phy_data->sl_rx_action]);
|
||||
|
||||
} else if(scheduled_response->sl_tx_config != NULL) {
|
||||
|
||||
sl_nr_tx_config_request_t *sl_tx_config = scheduled_response->sl_tx_config;
|
||||
nr_phy_data_tx_t *phy_data_tx = (nr_phy_data_tx_t *)scheduled_response->phy_data;
|
||||
|
||||
AssertFatal(sl_tx_config->number_pdus == SL_NR_TX_CONFIG_LIST_NUM,
|
||||
"sl_tx_config->number_pdus incorrect \n");
|
||||
|
||||
switch(sl_tx_config->tx_config_list[0].pdu_type) {
|
||||
|
||||
case SL_NR_CONFIG_TYPE_TX_PSBCH:
|
||||
phy_data_tx->sl_tx_action = SL_NR_CONFIG_TYPE_TX_PSBCH;
|
||||
LOG_D(PHY, "Recvd CONFIG_TYPE_%s\n", sl_tx_action[phy_data_tx->sl_tx_action - SL_NR_CONFIG_TYPE_TX_PSBCH]);
|
||||
*((uint32_t *)phy_data_tx->psbch_vars.psbch_payload) =
|
||||
*((uint32_t *) sl_tx_config->tx_config_list[0].tx_psbch_config_pdu.psbch_payload);
|
||||
phy_data_tx->psbch_vars.psbch_tx_power =
|
||||
sl_tx_config->tx_config_list[0].tx_psbch_config_pdu.psbch_tx_power;
|
||||
phy_data_tx->psbch_vars.tx_slss_id =
|
||||
sl_tx_config->tx_config_list[0].tx_psbch_config_pdu.tx_slss_id;
|
||||
break;
|
||||
case SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH:
|
||||
case SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS:
|
||||
case SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH: {
|
||||
sl_nr_tx_config_pscch_pssch_pdu_t *tx_config_pdu = &sl_tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu;
|
||||
phy_data_tx->sl_tx_action = sl_tx_config->tx_config_list[0].pdu_type;
|
||||
phy_data_tx->nr_sl_pssch_pscch_pdu = *tx_config_pdu;
|
||||
LOG_D(PHY, "Recvd CONFIG_TYPE_%s in (%d.%d) PSCCH startRB %hhu, PSCCH numRB %hhu\n",
|
||||
sl_tx_action[phy_data_tx->sl_tx_action - SL_NR_CONFIG_TYPE_TX_PSBCH],
|
||||
frame, slot,
|
||||
phy_data_tx->nr_sl_pssch_pscch_pdu.startrb,
|
||||
phy_data_tx->nr_sl_pssch_pscch_pdu.pscch_numrbs);
|
||||
LOG_D(NR_PHY, "format 1A length %hu :%llx, format 2x length %hu : %llx, PSSCH mcs %hu, PSSCH tbslrm %u\n",
|
||||
phy_data_tx->nr_sl_pssch_pscch_pdu.pscch_sci_payload_len,
|
||||
(unsigned long long)*phy_data_tx->nr_sl_pssch_pscch_pdu.pscch_sci_payload,
|
||||
phy_data_tx->nr_sl_pssch_pscch_pdu.sci2_payload_len,
|
||||
(unsigned long long)*phy_data_tx->nr_sl_pssch_pscch_pdu.sci2_payload,
|
||||
phy_data_tx->nr_sl_pssch_pscch_pdu.mcs,
|
||||
phy_data_tx->nr_sl_pssch_pscch_pdu.tbslbrm);
|
||||
if (phy_data_tx->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS) {
|
||||
phy_data_tx->nr_sl_pssch_pscch_pdu.nr_sl_csi_rs_pdu = tx_config_pdu->nr_sl_csi_rs_pdu;
|
||||
}
|
||||
uint8_t current_harq_pid = tx_config_pdu->harq_pid;
|
||||
NR_UL_UE_HARQ_t *harq_process = &PHY_vars_UE_g[module_id][cc_id]->sl_harq_processes[current_harq_pid];
|
||||
harq_process->status = ACTIVE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
AssertFatal(0,"Incorrect sl_tx config req pdutype \n");
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_D(PHY, "[UE%d] TTI %d:%d, SL-TX action:%s slss_id:%d, sl-mib:%x, psbch pwr:%d\n",
|
||||
module_id,frame,slot,
|
||||
sl_tx_action[phy_data_tx->sl_tx_action - SL_NR_CONFIG_TYPE_TX_PSBCH],
|
||||
phy_data_tx->psbch_vars.tx_slss_id,
|
||||
*((uint32_t *)phy_data_tx->psbch_vars.psbch_payload),
|
||||
phy_data_tx->psbch_vars.psbch_tx_power);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -40,12 +40,14 @@
|
||||
/**\brief NR UE FAPI-like P7 messages, scheduled response from L2 indicating L1
|
||||
\param scheduled_response including transmission config(dl_config, ul_config) and data transmission (tx_req)*/
|
||||
int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response);
|
||||
int8_t sl_handle_scheduled_response(nr_scheduled_response_t *scheduled_response);
|
||||
|
||||
int8_t nr_ue_scheduled_response_stub(nr_scheduled_response_t *scheduled_response);
|
||||
|
||||
/**\brief NR UE FAPI-like P5 message, physical configuration from L2 to configure L1
|
||||
\param scheduled_response including transmission config(dl_config, ul_config) and data transmission (tx_req)*/
|
||||
int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config);
|
||||
int8_t nr_ue_sl_phy_config_request(nr_sl_phy_config_t *phy_config);
|
||||
|
||||
/**\brief NR UE FAPI message to schedule a synchronization with target gNB
|
||||
\param synch_request including target_Nid_cell*/
|
||||
|
||||
@@ -291,7 +291,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n
|
||||
pucch_procedures_ue_nr(ue, proc, phy_data, (c16_t **)&txdataF);
|
||||
|
||||
LOG_D(PHY, "Sending Uplink data \n");
|
||||
nr_ue_pusch_common_procedures(ue, proc->nr_slot_tx, &ue->frame_parms, ue->frame_parms.nb_antennas_tx, (c16_t **)txdataF);
|
||||
nr_ue_pusch_common_procedures(ue, proc->nr_slot_tx, &ue->frame_parms, ue->frame_parms.nb_antennas_tx, (c16_t **)txdataF,link_type_ul);
|
||||
|
||||
nr_ue_prach_procedures(ue, proc);
|
||||
|
||||
@@ -422,17 +422,22 @@ unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int N_RB_UL, int nb
|
||||
|
||||
int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int pscch_flag,
|
||||
int32_t pdcch_est_size,
|
||||
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
|
||||
nr_phy_data_t *phy_data,
|
||||
int n_ss,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
|
||||
int16_t *rsrp_dBm)
|
||||
{
|
||||
int frame_rx = proc->frame_rx;
|
||||
int nr_slot_rx = proc->nr_slot_rx;
|
||||
unsigned int dci_cnt=0;
|
||||
fapi_nr_dci_indication_t dci_ind = {0};
|
||||
sl_nr_sci_indication_t sci_ind = {0};
|
||||
nr_downlink_indication_t dl_indication;
|
||||
nr_sidelink_indication_t sl_indication;
|
||||
|
||||
NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config;
|
||||
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &phy_pdcch_config->pdcch_config[n_ss];
|
||||
@@ -444,7 +449,7 @@ int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
|
||||
int16_t pdcch_e_rx[pdcch_e_rx_size];
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_IN);
|
||||
nr_rx_pdcch(ue, proc, pdcch_est_size, pdcch_dl_ch_estimates, pdcch_e_rx, rel15, rxdataF);
|
||||
nr_rx_pdcch(ue, proc, pscch_flag, pdcch_est_size, pdcch_dl_ch_estimates, pdcch_e_rx, rel15, rxdataF);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_OUT);
|
||||
|
||||
|
||||
@@ -455,7 +460,7 @@ int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
|
||||
n_ss);
|
||||
#endif
|
||||
|
||||
dci_cnt = nr_dci_decoding_procedure(ue, proc, pdcch_e_rx, &dci_ind, rel15);
|
||||
dci_cnt = nr_dci_decoding_procedure(ue, proc, pscch_flag, pdcch_e_rx, pscch_flag==0 ? (void*)&dci_ind : (void*)&sci_ind, rel15, rsrp_dBm);
|
||||
|
||||
#ifdef NR_PDCCH_SCHED_DEBUG
|
||||
LOG_I(PHY,"<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Ending function nr_dci_decoding_procedure() -> dci_cnt=%u\n",dci_cnt);
|
||||
@@ -464,21 +469,35 @@ int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DCI_DECODING, VCD_FUNCTION_OUT);
|
||||
|
||||
for (int i=0; i<dci_cnt; i++) {
|
||||
LOG_D(PHY,"[UE %d] AbsSubFrame %d.%d: DCI %i of %d total DCIs found --> rnti %x : format %d\n",
|
||||
ue->Mod_id,frame_rx%1024,nr_slot_rx,
|
||||
i + 1,
|
||||
dci_cnt,
|
||||
dci_ind.dci_list[i].rnti,
|
||||
dci_ind.dci_list[i].dci_format);
|
||||
if (pscch_flag==0)
|
||||
LOG_D(PHY,"[UE %d] AbsSubFrame %d.%d: DCI %i of %d total DCIs found --> rnti %x : format %d\n",
|
||||
ue->Mod_id,frame_rx%1024,nr_slot_rx,
|
||||
i + 1,
|
||||
dci_cnt,
|
||||
dci_ind.dci_list[i].rnti,
|
||||
dci_ind.dci_list[i].dci_format);
|
||||
else
|
||||
LOG_D(PHY,"[UE %d] AbsSubFrame %d.%d: SCI 1A %i of %d total SCIs found \n",
|
||||
ue->Mod_id,frame_rx%1024,nr_slot_rx,
|
||||
i + 1,
|
||||
dci_cnt);
|
||||
}
|
||||
|
||||
dci_ind.number_of_dcis = dci_cnt;
|
||||
|
||||
// fill dl_indication message
|
||||
nr_fill_dl_indication(&dl_indication, &dci_ind, NULL, proc, ue, phy_data);
|
||||
// send to mac
|
||||
ue->if_inst->dl_indication(&dl_indication);
|
||||
if (pscch_flag == 0) {
|
||||
dci_ind.number_of_dcis = dci_cnt;
|
||||
|
||||
// fill dl_indication message
|
||||
nr_fill_dl_indication(&dl_indication, &dci_ind, NULL, proc, ue, phy_data);
|
||||
// send to mac
|
||||
ue->if_inst->dl_indication(&dl_indication);
|
||||
}
|
||||
else {
|
||||
sci_ind.number_of_SCIs = dci_cnt;
|
||||
// fill sl_indication message
|
||||
nr_fill_sl_indication(&sl_indication, NULL, &sci_ind, proc, ue, phy_data);
|
||||
// send to mac
|
||||
ue->if_inst->sl_indication(&sl_indication);
|
||||
}
|
||||
stop_meas(&ue->dlsch_rx_pdcch_stats);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT);
|
||||
@@ -875,12 +894,15 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
|
||||
|
||||
for (int i=1; i<4; i++) {
|
||||
nr_slot_fep(ue,
|
||||
fp,
|
||||
proc,
|
||||
(ssb_start_symbol+i)%(fp->symbols_per_slot),
|
||||
rxdataF);
|
||||
rxdataF,
|
||||
link_type_dl);
|
||||
|
||||
start_meas(&ue->dlsch_channel_estimation_stats);
|
||||
nr_pbch_channel_estimation(ue,
|
||||
&ue->frame_parms,
|
||||
estimateSz,
|
||||
dl_ch_estimates,
|
||||
dl_ch_estimates_time,
|
||||
@@ -889,7 +911,9 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
|
||||
i-1,
|
||||
ssb_index&7,
|
||||
ssb_slot_2 == nr_slot_rx,
|
||||
rxdataF);
|
||||
rxdataF,
|
||||
false,
|
||||
fp->Nid_cell);
|
||||
stop_meas(&ue->dlsch_channel_estimation_stats);
|
||||
}
|
||||
|
||||
@@ -939,9 +963,11 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
|
||||
for(int j = prs_config->SymbolStart; j < (prs_config->SymbolStart+prs_config->NumPRSSymbols); j++)
|
||||
{
|
||||
nr_slot_fep(ue,
|
||||
fp,
|
||||
proc,
|
||||
(j%fp->symbols_per_slot),
|
||||
rxdataF);
|
||||
rxdataF,
|
||||
link_type_dl);
|
||||
}
|
||||
nr_prs_channel_estimation(rsc_id,
|
||||
i,
|
||||
@@ -978,9 +1004,11 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
|
||||
|
||||
start_meas(&ue->ofdm_demod_stats);
|
||||
nr_slot_fep(ue,
|
||||
fp,
|
||||
proc,
|
||||
l,
|
||||
rxdataF);
|
||||
rxdataF,
|
||||
link_type_dl);
|
||||
}
|
||||
|
||||
// Hold the channel estimates in frequency domain.
|
||||
@@ -995,18 +1023,20 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
|
||||
|
||||
nr_pdcch_channel_estimation(ue,
|
||||
proc,
|
||||
0,
|
||||
l,
|
||||
&phy_pdcch_config->pdcch_config[n_ss].coreset,
|
||||
fp->first_carrier_offset,
|
||||
phy_pdcch_config->pdcch_config[n_ss].BWPStart,
|
||||
pdcch_est_size,
|
||||
pdcch_dl_ch_estimates,
|
||||
rxdataF);
|
||||
rxdataF,
|
||||
NULL);
|
||||
|
||||
stop_meas(&ue->ofdm_demod_stats);
|
||||
|
||||
}
|
||||
dci_cnt = dci_cnt + nr_ue_pdcch_procedures(ue, proc, pdcch_est_size, pdcch_dl_ch_estimates, phy_data, n_ss, rxdataF);
|
||||
dci_cnt = dci_cnt + nr_ue_pdcch_procedures(ue, proc, 0, pdcch_est_size, pdcch_dl_ch_estimates, phy_data, n_ss, rxdataF, NULL);
|
||||
}
|
||||
LOG_D(PHY,"[UE %d] Frame %d, nr_slot_rx %d: found %d DCIs\n", ue->Mod_id, frame_rx, nr_slot_rx, dci_cnt);
|
||||
phy_pdcch_config->nb_search_space = 0;
|
||||
@@ -1039,9 +1069,11 @@ void pdsch_processing(PHY_VARS_NR_UE *ue,
|
||||
|
||||
for (uint16_t m=start_symb_sch;m<(nb_symb_sch+start_symb_sch) ; m++){
|
||||
nr_slot_fep(ue,
|
||||
&ue->frame_parms,
|
||||
proc,
|
||||
m, //to be updated from higher layer
|
||||
rxdataF);
|
||||
rxdataF,
|
||||
link_type_dl);
|
||||
}
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_OUT);
|
||||
|
||||
@@ -1116,7 +1148,7 @@ void pdsch_processing(PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
l_csiim[symb_idx] = ue->csiim_vars[gNB_id]->csiim_config_pdu.l_csiim[symb_idx];
|
||||
if(nr_slot_fep_done == false) {
|
||||
nr_slot_fep(ue, proc, ue->csiim_vars[gNB_id]->csiim_config_pdu.l_csiim[symb_idx], rxdataF);
|
||||
nr_slot_fep(ue, &ue->frame_parms, proc, ue->csiim_vars[gNB_id]->csiim_config_pdu.l_csiim[symb_idx], rxdataF, link_type_dl);
|
||||
}
|
||||
}
|
||||
nr_ue_csi_im_procedures(ue, proc, rxdataF);
|
||||
@@ -1127,7 +1159,7 @@ void pdsch_processing(PHY_VARS_NR_UE *ue,
|
||||
if ((ue->csirs_vars[gNB_id]) && (ue->csirs_vars[gNB_id]->active == 1)) {
|
||||
for(int symb = 0; symb < NR_SYMBOLS_PER_SLOT; symb++) {
|
||||
if(is_csi_rs_in_symbol(ue->csirs_vars[gNB_id]->csirs_config_pdu,symb)) {
|
||||
nr_slot_fep(ue, proc, symb, rxdataF);
|
||||
nr_slot_fep(ue, &ue->frame_parms, proc, symb, rxdataF, link_type_dl);
|
||||
}
|
||||
}
|
||||
nr_ue_csi_rs_procedures(ue, proc, rxdataF);
|
||||
|
||||
843
openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c
Normal file
843
openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c
Normal file
@@ -0,0 +1,843 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
|
||||
#include "openair1/PHY/NR_TRANSPORT/nr_ulsch.h"
|
||||
#include "openair1/PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/utils.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "UTIL/OPT/opt.h"
|
||||
#include "intertask_interface.h"
|
||||
#include "T.h"
|
||||
#include "PHY/MODULATION/modulation_UE.h"
|
||||
#include "PHY/NR_UE_ESTIMATION/nr_estimation.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
#include "common/utils/colors.h"
|
||||
|
||||
void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, uint8_t harq_pid, uint8_t crc_flag, int dtx_flag) {
|
||||
AssertFatal(1==0,"Should never get here\n");
|
||||
}
|
||||
NR_gNB_PHY_STATS_t *get_phy_stats(PHY_VARS_gNB *gNB, uint16_t rnti) {
|
||||
return(NULL);
|
||||
}
|
||||
void nr_fill_sl_indication(nr_sidelink_indication_t *sl_ind,
|
||||
sl_nr_rx_indication_t *rx_ind,
|
||||
sl_nr_sci_indication_t *sci_ind,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
void *phy_data)
|
||||
{
|
||||
memset((void*)sl_ind, 0, sizeof(nr_sidelink_indication_t));
|
||||
|
||||
sl_ind->gNB_index = proc->gNB_id;
|
||||
sl_ind->module_id = ue->Mod_id;
|
||||
sl_ind->cc_id = ue->CC_id;
|
||||
sl_ind->frame_rx = proc->frame_rx;
|
||||
sl_ind->slot_rx = proc->nr_slot_rx;
|
||||
sl_ind->frame_tx = proc->frame_tx;
|
||||
sl_ind->slot_tx = proc->nr_slot_tx;
|
||||
sl_ind->phy_data = phy_data;
|
||||
sl_ind->slot_type = SIDELINK_SLOT_TYPE_RX;
|
||||
|
||||
if (rx_ind) {
|
||||
sl_ind->rx_ind = rx_ind; // hang on rx_ind instance
|
||||
sl_ind->sci_ind = NULL;
|
||||
}
|
||||
if (sci_ind) {
|
||||
sl_ind->rx_ind = NULL;
|
||||
sl_ind->sci_ind = sci_ind;
|
||||
}
|
||||
}
|
||||
|
||||
void nr_fill_sl_rx_indication(sl_nr_rx_indication_t *rx_ind,
|
||||
uint8_t pdu_type,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
uint16_t n_pdus,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
void *typeSpecific,
|
||||
uint16_t rx_slss_id)
|
||||
{
|
||||
|
||||
if (n_pdus > 1){
|
||||
LOG_E(PHY, "In %s: multiple number of SL PDUs not supported yet...\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
|
||||
|
||||
switch (pdu_type){
|
||||
case SL_NR_RX_PDU_TYPE_SLSCH:
|
||||
case SL_NR_RX_PDU_TYPE_SLSCH_PSFCH: {
|
||||
sl_nr_slsch_pdu_t *rx_slsch_pdu = &rx_ind->rx_indication_body[n_pdus - 1].rx_slsch_pdu;
|
||||
slsch_status_t *slsch_status = (slsch_status_t *)typeSpecific;
|
||||
rx_slsch_pdu->pdu = slsch_status->rdata->ulsch_harq->b;
|
||||
rx_slsch_pdu->pdu_length = slsch_status->rdata->ulsch_harq->TBS;
|
||||
rx_slsch_pdu->harq_pid = slsch_status->rdata->harq_pid;
|
||||
rx_slsch_pdu->ack_nack = (slsch_status->rxok==true) ? 1 : 0;
|
||||
|
||||
LOG_D(NR_MAC, "%4d.%2d Received %s SLSCH\n", rx_ind->sfn, rx_ind->slot, rx_slsch_pdu->ack_nack ? "Correct" : "Incorrect");
|
||||
if (slsch_status->rxok==true) ue->SL_UE_PHY_PARAMS.pssch.rx_ok++;
|
||||
else ue->SL_UE_PHY_PARAMS.pssch.rx_errors[0]++;
|
||||
}
|
||||
break;
|
||||
case FAPI_NR_RX_PDU_TYPE_SSB: {
|
||||
sl_nr_ssb_pdu_t *ssb_pdu = &rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu;
|
||||
if(typeSpecific) {
|
||||
uint8_t *psbch_decoded_output = (uint8_t *)typeSpecific;
|
||||
memcpy(ssb_pdu->psbch_payload, psbch_decoded_output, sizeof(4));//4 bytes of PSBCH payload bytes
|
||||
ssb_pdu->rsrp_dbm = sl_phy_params->psbch.rsrp_dBm_per_RE;
|
||||
ssb_pdu->rx_slss_id = rx_slss_id;
|
||||
ssb_pdu->decode_status = true;
|
||||
LOG_D(PHY, "SL-IND: SSB to MAC. rsrp:%d, slssid:%d, payload:%x\n",
|
||||
ssb_pdu->rsrp_dbm,ssb_pdu->rx_slss_id,
|
||||
*((uint32_t *)(ssb_pdu->psbch_payload)) );
|
||||
}
|
||||
else
|
||||
ssb_pdu->decode_status = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
rx_ind->rx_indication_body[n_pdus -1].pdu_type = pdu_type;
|
||||
rx_ind->number_pdus = n_pdus;
|
||||
|
||||
}
|
||||
|
||||
extern int dmrs_pscch_mask[2];
|
||||
int nr_slsch_procedures(PHY_VARS_NR_UE *ue, int frame_rx, int slot_rx, int SLSCH_id, UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data, bool is_csi_rs_slot, int8_t *ack_nack_rcvd, int num_acks) {
|
||||
|
||||
|
||||
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
|
||||
NR_DL_FRAME_PARMS *fp = &sl_phy_params->sl_frame_params;
|
||||
sl_nr_rx_config_pssch_pdu_t *slsch_pdu = &phy_data->nr_sl_pssch_pdu; //ue->slsch[SLSCH_id].harq_process->slsch_pdu;
|
||||
sl_nr_rx_config_pssch_sci_pdu_t *pssch_pdu = &phy_data->nr_sl_pssch_sci_pdu; //ue->slsch[SLSCH_id].harq_process->pssch_pdu;
|
||||
|
||||
uint8_t freq_density = 0;
|
||||
uint8_t nr_of_rbs = 0;
|
||||
if (is_csi_rs_slot) {
|
||||
freq_density = ue->csirs_vars[0]->csirs_config_pdu.freq_density;
|
||||
nr_of_rbs = ue->csirs_vars[0]->csirs_config_pdu.nr_of_rbs;
|
||||
AssertFatal((freq_density == 1) || (nr_of_rbs > 0), "CSI-RS parameters are not properly configured\n");
|
||||
}
|
||||
int harq_pid = slsch_pdu->harq_pid;
|
||||
uint16_t nb_re_dmrs;
|
||||
uint16_t start_symbol = 1;
|
||||
uint16_t number_symbols = pssch_pdu->pssch_numsym;
|
||||
ue->slsch[SLSCH_id].harq_process->harq_to_be_cleared=true;
|
||||
uint8_t number_dmrs_symbols = 0;
|
||||
for (int l = start_symbol; l < start_symbol + number_symbols; l++)
|
||||
number_dmrs_symbols += ((pssch_pdu->dmrs_symbol_position)>>l)&0x01;
|
||||
|
||||
nb_re_dmrs = 6;
|
||||
|
||||
uint32_t rb_size = pssch_pdu->num_subch*pssch_pdu->subchannel_size;
|
||||
int sci1_dmrs_overlap = pssch_pdu->dmrs_symbol_position & dmrs_pscch_mask[pssch_pdu->pscch_numsym-2];
|
||||
int sci2_re = get_NREsci2_2(pssch_pdu->sci2_alpha_times_100,
|
||||
pssch_pdu->sci2_len,
|
||||
pssch_pdu->sci2_beta_offset,
|
||||
pssch_pdu->pssch_numsym,
|
||||
pssch_pdu->pscch_numsym,
|
||||
pssch_pdu->pscch_numrbs,
|
||||
pssch_pdu->l_subch,
|
||||
pssch_pdu->subchannel_size,
|
||||
pssch_pdu->targetCodeRate,
|
||||
0);
|
||||
|
||||
uint8_t nr_rbs_w_csi_rs = nr_of_rbs / freq_density;
|
||||
uint8_t subcarriers_used = get_nrUE_params()->nb_antennas_tx > 2 ? 2 : get_nrUE_params()->nb_antennas_tx;
|
||||
int num_CSI_REs = is_csi_rs_slot ? nr_rbs_w_csi_rs * subcarriers_used : 0;
|
||||
uint16_t sci1_re = pssch_pdu->pscch_numsym * pssch_pdu->pscch_numrbs * NR_NB_SC_PER_RB;
|
||||
uint32_t G = nr_get_G_SL(rb_size,
|
||||
number_symbols,
|
||||
nb_re_dmrs,
|
||||
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
|
||||
sci1_dmrs_overlap,
|
||||
sci1_re,
|
||||
pssch_pdu->pscch_numrbs,
|
||||
sci2_re,
|
||||
num_CSI_REs,
|
||||
pssch_pdu->mod_order,
|
||||
pssch_pdu->num_layers);
|
||||
|
||||
AssertFatal(G>0,"G is 0 : rb_size %u, number_symbols %d, nb_re_dmrs %d, number_dmrs_symbols %d, qam_mod_order %u, nrOfLayer %u\n",
|
||||
rb_size,
|
||||
number_symbols,
|
||||
nb_re_dmrs,
|
||||
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
|
||||
pssch_pdu->mod_order,
|
||||
pssch_pdu->num_layers);
|
||||
LOG_D(NR_PHY,"slot %d rb_size %d, number_symbols %d, nb_re_dmrs %d, dmrs symbol positions %d, number_dmrs_symbols %d, qam_mod_order %d, nrOfLayer %d\n",
|
||||
slot_rx,
|
||||
rb_size,
|
||||
number_symbols,
|
||||
nb_re_dmrs,
|
||||
pssch_pdu->dmrs_symbol_position,
|
||||
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
|
||||
pssch_pdu->mod_order,
|
||||
pssch_pdu->num_layers);
|
||||
|
||||
nr_ulsch_layer_demapping(ue->pssch_vars[SLSCH_id].llr,
|
||||
pssch_pdu->num_layers,
|
||||
pssch_pdu->mod_order,
|
||||
G,
|
||||
ue->pssch_vars[SLSCH_id].llr_layers);
|
||||
|
||||
//for (int g=0;g<G;g++) LOG_I(NR_PHY,"prescrambling_llr[%d] %d\n",g,ue->pssch_vars[SLSCH_id].llr[g]);
|
||||
//----------------------------------------------------------
|
||||
//------------------- ULSCH unscrambling -------------------
|
||||
//----------------------------------------------------------
|
||||
//LOG_I(NR_PHY,"SLSCH, unscrambling with Nid %x\n",pssch_pdu->Nid);
|
||||
nr_ulsch_unscrambling(ue->pssch_vars[SLSCH_id].llr, G, pssch_pdu->Nid, 1010);
|
||||
// for (int g=0;g<32;g++) LOG_I(NR_PHY,"unscrambling_llr[%d] %d\n",g,ue->pssch_vars[SLSCH_id].llr[g]);
|
||||
//----------------------------------------------------------
|
||||
//--------------------- ULSCH decoding ---------------------
|
||||
//----------------------------------------------------------
|
||||
|
||||
|
||||
nfapi_nr_pusch_pdu_t pusch_pdu;
|
||||
|
||||
pusch_pdu.rb_size = rb_size;
|
||||
pusch_pdu.qam_mod_order = pssch_pdu->mod_order;
|
||||
pusch_pdu.mcs_index = slsch_pdu->mcs;
|
||||
pusch_pdu.nrOfLayers = pssch_pdu->num_layers;
|
||||
pusch_pdu.pusch_data.tb_size=slsch_pdu->tb_size;
|
||||
uint32_t A = slsch_pdu->tb_size<<3;
|
||||
pusch_pdu.target_code_rate=slsch_pdu->target_coderate;
|
||||
float Coderate = (float) (slsch_pdu->target_coderate) / 10240.0f;
|
||||
pusch_pdu.pusch_data.rv_index=slsch_pdu->rv_index;
|
||||
|
||||
if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25){
|
||||
pusch_pdu.maintenance_parms_v3.ldpcBaseGraph=2;
|
||||
}
|
||||
else{
|
||||
pusch_pdu.maintenance_parms_v3.ldpcBaseGraph=1;
|
||||
}
|
||||
pusch_pdu.maintenance_parms_v3.tbSizeLbrmBytes=slsch_pdu->tbslbrm>>3;
|
||||
|
||||
LOG_D(NR_PHY, "%4d.%2d Calling nr_ulsch_decoding\n", frame_rx, slot_rx);
|
||||
int nbDecode =
|
||||
nr_ulsch_decoding(NULL, ue, SLSCH_id, ue->pssch_vars[SLSCH_id].llr, fp, &pusch_pdu, frame_rx, slot_rx, harq_pid, G, proc, phy_data, ack_nack_rcvd, num_acks);
|
||||
return nbDecode;
|
||||
}
|
||||
|
||||
void nr_postDecode_slsch(PHY_VARS_NR_UE *UE, notifiedFIFO_elt_t *req,UE_nr_rxtx_proc_t *proc,nr_phy_data_t *phy_data, int8_t *ack_nack_rcvd, uint8_t num_acks)
|
||||
{
|
||||
ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req);
|
||||
NR_UL_gNB_HARQ_t *slsch_harq = rdata->ulsch_harq;
|
||||
NR_gNB_ULSCH_t *slsch = rdata->ulsch;
|
||||
int r = rdata->segment_r;
|
||||
sl_nr_rx_config_pssch_pdu_t *slsch_pdu = &phy_data->nr_sl_pssch_pdu;//UE->slsch[rdata->ulsch_id].harq_process->slsch_pdu;
|
||||
bool decodeSuccess = (rdata->decodeIterations <= rdata->decoderParms.numMaxIter);
|
||||
slsch_harq->processedSegments++;
|
||||
LOG_D(NR_PHY,
|
||||
"processing result of segment: %d, processed %d/%d\n",
|
||||
rdata->segment_r,
|
||||
slsch_harq->processedSegments,
|
||||
rdata->nbSegments);
|
||||
if (decodeSuccess) {
|
||||
memcpy(slsch_harq->b + rdata->offset, slsch_harq->c[r], rdata->Kr_bytes - (slsch_harq->F >> 3) - ((slsch_harq->C > 1) ? 3 : 0));
|
||||
|
||||
} else {
|
||||
LOG_D(NR_PHY, "ULSCH %d in error\n", rdata->ulsch_id);
|
||||
}
|
||||
|
||||
//int dumpsig=0;
|
||||
// if all segments are done
|
||||
if (rdata->nbSegments == slsch_harq->processedSegments) {
|
||||
sl_nr_rx_indication_t sl_rx_indication;
|
||||
nr_sidelink_indication_t sl_indication;
|
||||
slsch_status_t slsch_status;
|
||||
if (!check_abort(&slsch_harq->abort_decode) && !UE->pssch_vars[rdata->ulsch_id].DTX) {
|
||||
LOG_D(NR_PHY,
|
||||
"[UE] SLSCH: Setting ACK for SFN/SF %d.%d (pid %d, ndi %d, status %d, round %d, TBS %d, Max interation "
|
||||
"(all seg) %d)\n",
|
||||
slsch->frame,
|
||||
slsch->slot,
|
||||
rdata->harq_pid,
|
||||
slsch_pdu->ndi,
|
||||
slsch->active,
|
||||
slsch_harq->round,
|
||||
slsch_harq->TBS,
|
||||
rdata->decodeIterations);
|
||||
slsch->active = false;
|
||||
slsch_harq->round = 0;
|
||||
LOG_D(NR_PHY, "%4d.%2d SLSCH received ok \n", proc->frame_rx, proc->nr_slot_rx);
|
||||
slsch_status.rdata = rdata;
|
||||
slsch_status.rxok = true;
|
||||
//dumpsig=1;
|
||||
} else {
|
||||
LOG_E(NR_PHY,
|
||||
"[UE] SLSCH %d in error: Setting NAK for SFN/SF %d/%d (pid %d, ndi %d, status %d, round %d, RV %d, prb_start %d, prb_size %d, "
|
||||
"TBS %d) r %d\n",
|
||||
rdata->ulsch_id,
|
||||
slsch->frame,
|
||||
slsch->slot,
|
||||
rdata->harq_pid,
|
||||
slsch_pdu->ndi,
|
||||
slsch->active,
|
||||
slsch_harq->round,
|
||||
slsch_harq->ulsch_pdu.pusch_data.rv_index,
|
||||
slsch_harq->ulsch_pdu.rb_start,
|
||||
slsch_harq->ulsch_pdu.rb_size,
|
||||
slsch_harq->TBS,
|
||||
r);
|
||||
slsch->handled = 1;
|
||||
LOG_D(NR_PHY, "%4d.%2d SLSCH %d in error\n", proc->frame_rx, proc->nr_slot_rx, rdata->ulsch_id);
|
||||
slsch_status.rdata = rdata;
|
||||
slsch_status.rxok = false;
|
||||
// dumpsig=1;
|
||||
}
|
||||
slsch->last_iteration_cnt = rdata->decodeIterations;
|
||||
sl_rx_indication.sfn = proc->frame_rx;
|
||||
sl_rx_indication.slot = proc->nr_slot_rx;
|
||||
sl_rx_indication.rx_indication_body[0].rx_slsch_pdu.ack_nack_rcvd = calloc(num_acks, sizeof(uint8_t));
|
||||
memcpy((void*)sl_rx_indication.rx_indication_body[0].rx_slsch_pdu.ack_nack_rcvd, (void*)ack_nack_rcvd,
|
||||
num_acks * sizeof(uint8_t));
|
||||
sl_rx_indication.rx_indication_body[0].rx_slsch_pdu.num_acks_rcvd = num_acks;
|
||||
uint8_t pdu_type = phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_PSFCH ? SL_NR_RX_PDU_TYPE_SLSCH_PSFCH : SL_NR_RX_PDU_TYPE_SLSCH;
|
||||
nr_fill_sl_rx_indication(&sl_rx_indication, pdu_type, UE, 1, proc, (void*)&slsch_status, 0);
|
||||
nr_fill_sl_indication(&sl_indication,&sl_rx_indication,NULL,proc,UE,phy_data);
|
||||
if (UE->if_inst && UE->if_inst->sl_indication)
|
||||
UE->if_inst->sl_indication(&sl_indication);
|
||||
/*
|
||||
if (ulsch_harq->ulsch_pdu.mcs_index == 0 && dumpsig==1) {
|
||||
int off = ((ulsch_harq->ulsch_pdu.rb_size&1) == 1)? 4:0;
|
||||
|
||||
LOG_M("rxsigF0.m","rxsF0",&gNB->common_vars.rxdataF[0][(ulsch_harq->slot&3)*gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot],gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot,1,1);
|
||||
LOG_M("rxsigF0_ext.m","rxsF0_ext",
|
||||
&gNB->pusch_vars[0].rxdataF_ext[0][ulsch_harq->ulsch_pdu.start_symbol_index*NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("chestF0.m","chF0",
|
||||
&gNB->pusch_vars[0].ul_ch_estimates[0][ulsch_harq->ulsch_pdu.start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1);
|
||||
LOG_M("chestF0_ext.m","chF0_ext",
|
||||
&gNB->pusch_vars[0]->ul_ch_estimates_ext[0][(ulsch_harq->ulsch_pdu.start_symbol_index+1)*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size))], (ulsch_harq->ulsch_pdu.nr_of_symbols-1)*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("rxsigF0_comp.m","rxsF0_comp",
|
||||
&gNB->pusch_vars[0].rxdataF_comp[0][ulsch_harq->ulsch_pdu.start_symbol_index*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size))],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("rxsigF0_llr.m","rxsF0_llr",
|
||||
&gNB->pusch_vars[0].llr[0],(ulsch_harq->ulsch_pdu.nr_of_symbols-1)*NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size *
|
||||
ulsch_harq->ulsch_pdu.qam_mod_order,1,0); if (gNB->frame_parms.nb_antennas_rx > 1) {
|
||||
|
||||
LOG_M("rxsigF1_ext.m","rxsF0_ext",
|
||||
&gNB->pusch_vars[0].rxdataF_ext[1][ulsch_harq->ulsch_pdu.start_symbol_index*NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("chestF1.m","chF1",
|
||||
&gNB->pusch_vars[0].ul_ch_estimates[1][ulsch_harq->ulsch_pdu.start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1);
|
||||
LOG_M("chestF1_ext.m","chF1_ext",
|
||||
&gNB->pusch_vars[0].ul_ch_estimates_ext[1][(ulsch_harq->ulsch_pdu.start_symbol_index+1)*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size))], (ulsch_harq->ulsch_pdu.nr_of_symbols-1)*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("rxsigF1_comp.m","rxsF1_comp",
|
||||
&gNB->pusch_vars[0].rxdataF_comp[1][ulsch_harq->ulsch_pdu.start_symbol_index*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size))],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size)),1,1);
|
||||
}
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
*/
|
||||
slsch->last_iteration_cnt = rdata->decodeIterations;
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,0);
|
||||
}
|
||||
}
|
||||
static int nr_ue_psbch_procedures(PHY_VARS_NR_UE *ue,
|
||||
NR_DL_FRAME_PARMS *fp,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
nr_phy_data_t *phy_data,
|
||||
c16_t rxdataF[][fp->samples_per_slot_wCP])
|
||||
{
|
||||
|
||||
int ret = 0;
|
||||
DevAssert(ue);
|
||||
|
||||
int frame_rx = proc->frame_rx;
|
||||
int nr_slot_rx = proc->nr_slot_rx;
|
||||
|
||||
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
|
||||
uint16_t rx_slss_id = sl_phy_params->sl_config.sl_sync_source.rx_slss_id;
|
||||
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PSBCH_PROCEDURES, VCD_FUNCTION_IN);
|
||||
|
||||
LOG_D(PHY,"[UE %d] Frame %d Slot %d, Trying PSBCH (SLSS ID %d)\n",
|
||||
ue->Mod_id,frame_rx,nr_slot_rx,
|
||||
sl_phy_params->sl_config.sl_sync_source.rx_slss_id);
|
||||
|
||||
uint8_t decoded_pdu[4] = {0};
|
||||
ret = nr_rx_psbch(ue,
|
||||
proc,
|
||||
estimateSz,
|
||||
dl_ch_estimates,
|
||||
fp,
|
||||
decoded_pdu,
|
||||
rxdataF,
|
||||
sl_phy_params->sl_config.sl_sync_source.rx_slss_id);
|
||||
|
||||
nr_sidelink_indication_t sl_indication;
|
||||
sl_nr_rx_indication_t rx_ind = {0};
|
||||
uint16_t number_pdus = 1;
|
||||
|
||||
uint8_t *result = NULL;
|
||||
if (ret) sl_phy_params->psbch.rx_errors ++;
|
||||
else {
|
||||
result = decoded_pdu;
|
||||
sl_phy_params->psbch.rx_ok ++;
|
||||
}
|
||||
|
||||
nr_fill_sl_indication(&sl_indication, &rx_ind, NULL, proc, ue, phy_data);
|
||||
nr_fill_sl_rx_indication(&rx_ind, SL_NR_RX_PDU_TYPE_SSB, ue, number_pdus, proc, (void *)result, rx_slss_id);
|
||||
|
||||
if (ue->if_inst && ue->if_inst->sl_indication)
|
||||
ue->if_inst->sl_indication(&sl_indication);
|
||||
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PSBCH_PROCEDURES, VCD_FUNCTION_OUT);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void psbch_pscch_pssch_processing(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
nr_phy_data_t *phy_data) {
|
||||
|
||||
int frame_rx = proc->frame_rx;
|
||||
int nr_slot_rx = proc->nr_slot_rx;
|
||||
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
|
||||
NR_DL_FRAME_PARMS *fp = &sl_phy_params->sl_frame_params;
|
||||
bool is_csi_rs_slot = false;
|
||||
int8_t *ack_nack_rcvd = NULL;
|
||||
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX_SL, VCD_FUNCTION_IN);
|
||||
start_meas(&sl_phy_params->phy_proc_sl_rx);
|
||||
|
||||
LOG_D(PHY," ****** Sidelink RX-Chain for Frame.Slot %d.%d ****** \n",
|
||||
frame_rx%1024, nr_slot_rx);
|
||||
|
||||
const uint32_t rxdataF_sz = fp->samples_per_slot_wCP;
|
||||
__attribute__ ((aligned(32))) c16_t rxdataF[fp->nb_antennas_rx][rxdataF_sz];
|
||||
|
||||
if ((frame_rx&127) == 0) {
|
||||
LOG_I(NR_PHY,"============================================\n");
|
||||
|
||||
LOG_I(NR_PHY,"%s[UE%d] %d:%d PSBCH Stats: TX %u, RX ok %u, RX not ok %u\n",KGRN,
|
||||
ue->Mod_id, frame_rx, nr_slot_rx,
|
||||
sl_phy_params->psbch.num_psbch_tx,
|
||||
sl_phy_params->psbch.rx_ok,
|
||||
sl_phy_params->psbch.rx_errors);
|
||||
|
||||
LOG_I(NR_PHY,"%s[UE%d] %d:%d PSCCH Stats: TX %u, RX ok %u\n",KGRN,
|
||||
ue->Mod_id, frame_rx, nr_slot_rx,
|
||||
sl_phy_params->pscch.num_pscch_tx,
|
||||
sl_phy_params->pscch.rx_ok);
|
||||
|
||||
LOG_I(NR_PHY,"%s[UE%d] %d:%d PSSCH/SCI2 Stats: TX %u, RX ok %u, RX not ok %u\n",KGRN,
|
||||
ue->Mod_id, frame_rx, nr_slot_rx,
|
||||
sl_phy_params->pssch.num_pssch_sci2_tx,
|
||||
sl_phy_params->pssch.rx_sci2_ok,
|
||||
sl_phy_params->pssch.rx_sci2_errors);
|
||||
LOG_I(NR_PHY,"%s[UE%d] %d:%d PSSCH Stats: TX %u, RX ok %u, RX not ok (%u/%u/%u/%u)\n",KGRN,
|
||||
ue->Mod_id, frame_rx, nr_slot_rx,
|
||||
sl_phy_params->pssch.num_pssch_tx,
|
||||
sl_phy_params->pssch.rx_ok,
|
||||
sl_phy_params->pssch.rx_errors[0],
|
||||
sl_phy_params->pssch.rx_errors[1],
|
||||
sl_phy_params->pssch.rx_errors[2],
|
||||
sl_phy_params->pssch.rx_errors[3]);
|
||||
LOG_I(NR_PHY, "%s[UE%d] %d:%d PSFCH Stats: TX %u\n", KGRN,
|
||||
ue->Mod_id, frame_rx, nr_slot_rx,
|
||||
sl_phy_params->psfch.num_psfch_tx
|
||||
);
|
||||
LOG_I(NR_PHY,"============================================\n");
|
||||
}
|
||||
|
||||
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSBCH){
|
||||
|
||||
const int estimateSz = fp->symbols_per_slot * fp->ofdm_symbol_size;
|
||||
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PSBCH, VCD_FUNCTION_IN);
|
||||
LOG_D(PHY," ----- PSBCH RX TTI: frame.slot %d.%d ------ \n",
|
||||
frame_rx%1024, nr_slot_rx);
|
||||
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates[fp->nb_antennas_rx][estimateSz];
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_time[fp->nb_antennas_rx][fp->ofdm_symbol_size];
|
||||
|
||||
// 0 for Normal Cyclic Prefix and 1 for EXT CyclicPrefix
|
||||
const int numsym = (fp->Ncp) ? SL_NR_NUM_SYMBOLS_SSB_EXT_CP
|
||||
: SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP;
|
||||
|
||||
for (int sym=0; sym<numsym;) {
|
||||
nr_slot_fep(ue,
|
||||
fp,
|
||||
proc,
|
||||
sym,
|
||||
rxdataF,
|
||||
link_type_sl);
|
||||
|
||||
start_meas(&sl_phy_params->channel_estimation_stats);
|
||||
nr_pbch_channel_estimation(ue,
|
||||
fp,
|
||||
estimateSz,
|
||||
dl_ch_estimates,
|
||||
dl_ch_estimates_time,
|
||||
proc,
|
||||
sym,
|
||||
sym,
|
||||
0,
|
||||
0,
|
||||
rxdataF,
|
||||
true,
|
||||
sl_phy_params->sl_config.sl_sync_source.rx_slss_id);
|
||||
stop_meas(&sl_phy_params->channel_estimation_stats);
|
||||
|
||||
//PSBCH present in symbols 0, 5-12 for normal cp
|
||||
sym = (sym == 0) ? 5 : sym + 1;
|
||||
}
|
||||
|
||||
nr_sl_psbch_rsrp_measurements(sl_phy_params,fp, rxdataF,false);
|
||||
|
||||
LOG_D(PHY," ------ Decode SL-MIB: frame.slot %d.%d ------ \n",
|
||||
frame_rx%1024, nr_slot_rx);
|
||||
|
||||
const int psbchSuccess = nr_ue_psbch_procedures(ue, fp, proc, estimateSz,
|
||||
dl_ch_estimates, phy_data, rxdataF);
|
||||
|
||||
if (ue->no_timing_correction==0 && psbchSuccess == 0) {
|
||||
LOG_D(PHY,"start adjust sync slot = %d no timing %d\n", nr_slot_rx, ue->no_timing_correction);
|
||||
nr_adjust_synch_ue(fp,
|
||||
ue,
|
||||
proc->gNB_id,
|
||||
fp->ofdm_symbol_size,
|
||||
dl_ch_estimates_time,
|
||||
frame_rx,
|
||||
nr_slot_rx,
|
||||
0,
|
||||
16384);
|
||||
}
|
||||
ue->apply_timing_offset = true;
|
||||
|
||||
LOG_D(PHY, "Doing N0 measurements in %s\n", __FUNCTION__);
|
||||
// nr_ue_rrc_measurements(ue, proc, rxdataF);
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PSBCH, VCD_FUNCTION_OUT);
|
||||
|
||||
}
|
||||
else if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSCCH){
|
||||
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &phy_data->phy_pdcch_config.pdcch_config[0];
|
||||
LOG_D(NR_PHY,"pscch_numsym = %d\n",phy_data->nr_sl_pscch_pdu.pscch_numsym);
|
||||
LOG_D(NR_PHY,"pscch_startrb = %d\n",phy_data->nr_sl_pscch_pdu.pscch_startrb);
|
||||
LOG_D(NR_PHY,"pscch_numrbs = %d\n",phy_data->nr_sl_pscch_pdu.pscch_numrbs);
|
||||
LOG_D(NR_PHY,"pscch_dmrs_scrambling_id = %d\n",phy_data->nr_sl_pscch_pdu.pscch_dmrs_scrambling_id);
|
||||
|
||||
LOG_D(NR_PHY,"pscch_num_subch= %d\n",phy_data->nr_sl_pscch_pdu.num_subch);
|
||||
LOG_D(NR_PHY,"pscch_subchannel_size = %d\n",phy_data->nr_sl_pscch_pdu.subchannel_size);
|
||||
LOG_D(NR_PHY,"pscch_l_subch = %d\n",phy_data->nr_sl_pscch_pdu.l_subch);
|
||||
LOG_D(NR_PHY,"pscch_pssch_numsym = %d\n",phy_data->nr_sl_pscch_pdu.pssch_numsym);
|
||||
LOG_D(NR_PHY,"sense_pscch = %d\n",phy_data->nr_sl_pscch_pdu.sense_pscch);
|
||||
|
||||
rel15->rnti = 0;
|
||||
rel15->BWPSize = phy_data->nr_sl_pscch_pdu.num_subch * phy_data->nr_sl_pscch_pdu.subchannel_size;
|
||||
rel15->BWPStart = phy_data->nr_sl_pscch_pdu.pscch_startrb;
|
||||
rel15->SubcarrierSpacing = fp->subcarrier_spacing;
|
||||
rel15->coreset.frequency_domain_resource[0] = phy_data->nr_sl_pscch_pdu.pscch_startrb;
|
||||
rel15->coreset.frequency_domain_resource[1] = phy_data->nr_sl_pscch_pdu.pscch_numrbs;
|
||||
rel15->coreset.CoreSetType = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG;
|
||||
rel15->coreset.StartSymbolIndex = 1;
|
||||
rel15->coreset.RegBundleSize = 0;
|
||||
rel15->coreset.duration = phy_data->nr_sl_pscch_pdu.pscch_numsym;
|
||||
rel15->coreset.pdcch_dmrs_scrambling_id = phy_data->nr_sl_pscch_pdu.pscch_dmrs_scrambling_id;
|
||||
rel15->coreset.scrambling_rnti = 1010;
|
||||
rel15->coreset.tci_present_in_dci = 0;
|
||||
|
||||
rel15->number_of_candidates = phy_data->nr_sl_pscch_pdu.l_subch;
|
||||
rel15->num_dci_options = 1;
|
||||
rel15->dci_length_options[0] = phy_data->nr_sl_pscch_pdu.sci_1a_length;
|
||||
// L now provides the number of PRBs used by PSCCH instead of the number of CCEs
|
||||
rel15->L[0] = phy_data->nr_sl_pscch_pdu.pscch_numrbs * phy_data->nr_sl_pscch_pdu.pscch_numsym;
|
||||
// This provides the offset of the candidate of PSCCH in RBs instead of CCEs
|
||||
rel15->CCE[0] = 0;
|
||||
|
||||
// Hold the channel estimates in frequency domain.
|
||||
int32_t pscch_est_size = ((((fp->symbols_per_slot*(fp->ofdm_symbol_size+LTE_CE_FILTER_LENGTH))+15)/16)*16);
|
||||
__attribute__ ((aligned(16))) int32_t pscch_dl_ch_estimates[4*fp->nb_antennas_rx][pscch_est_size];
|
||||
//
|
||||
int16_t rsrp_dBm = 0;
|
||||
for (int sym=0; sym<rel15->coreset.duration;sym++) {
|
||||
nr_slot_fep(ue,
|
||||
fp,
|
||||
proc,
|
||||
1+sym,
|
||||
rxdataF,
|
||||
link_type_sl);
|
||||
nr_pdcch_channel_estimation(ue,
|
||||
proc,
|
||||
1,
|
||||
1+sym,
|
||||
&rel15->coreset,
|
||||
fp->first_carrier_offset,
|
||||
rel15->BWPStart,
|
||||
pscch_est_size,
|
||||
pscch_dl_ch_estimates,
|
||||
rxdataF,
|
||||
&rsrp_dBm);
|
||||
}
|
||||
|
||||
nr_ue_pdcch_procedures(ue, proc, 1, pscch_est_size, pscch_dl_ch_estimates, phy_data, 0, rxdataF, &rsrp_dBm);
|
||||
LOG_D(NR_PHY,"returned from nr_ue_pdcch_procedures\n");
|
||||
}
|
||||
|
||||
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SCI) {
|
||||
LOG_D(NR_PHY,"sci2_len = %d\n",phy_data->nr_sl_pssch_sci_pdu.sci2_len);
|
||||
LOG_D(NR_PHY,"sci2_beta_offset = %d\n",phy_data->nr_sl_pssch_sci_pdu.sci2_beta_offset);
|
||||
LOG_D(NR_PHY,"sci2_alpha_times_100= %d\n",phy_data->nr_sl_pssch_sci_pdu.sci2_alpha_times_100);
|
||||
LOG_D(NR_PHY,"pssch_targetCodeRate = %d\n",phy_data->nr_sl_pssch_sci_pdu.targetCodeRate);
|
||||
LOG_D(NR_PHY,"pssch_num_layers = %d\n",phy_data->nr_sl_pssch_sci_pdu.num_layers);
|
||||
LOG_D(NR_PHY,"dmrs_symbol_position = %d\n",phy_data->nr_sl_pssch_sci_pdu.dmrs_symbol_position);
|
||||
int num_dmrs = 0;
|
||||
for (int s = 0; s < NR_NUMBER_OF_SYMBOLS_PER_SLOT; s++)
|
||||
num_dmrs += (phy_data->nr_sl_pssch_sci_pdu.dmrs_symbol_position >> s) & 1;
|
||||
LOG_D(NR_PHY,"num_dmrs = %d\n",num_dmrs);
|
||||
LOG_D(NR_PHY,"Nid = %x\n",phy_data->nr_sl_pssch_sci_pdu.Nid);
|
||||
|
||||
LOG_D(NR_PHY,"startrb = %d\n",phy_data->nr_sl_pssch_sci_pdu.startrb);
|
||||
LOG_D(NR_PHY,"pscch_numsym = %d\n",phy_data->nr_sl_pssch_sci_pdu.pscch_numsym);
|
||||
LOG_D(NR_PHY,"pscch_numrbs = %d\n",phy_data->nr_sl_pssch_sci_pdu.pscch_numrbs);
|
||||
LOG_D(NR_PHY,"num_subch= %d\n",phy_data->nr_sl_pssch_sci_pdu.num_subch);
|
||||
LOG_D(NR_PHY,"subchannel_size = %d\n",phy_data->nr_sl_pssch_sci_pdu.subchannel_size);
|
||||
LOG_D(NR_PHY,"l_subch = %d\n",phy_data->nr_sl_pssch_sci_pdu.l_subch);
|
||||
LOG_D(NR_PHY,"pssch_numsym = %d\n",phy_data->nr_sl_pssch_sci_pdu.pssch_numsym);
|
||||
LOG_D(NR_PHY,"sense_pssch = %d\n",phy_data->nr_sl_pssch_sci_pdu.sense_pssch);
|
||||
ue->slsch->harq_process->pssch_pdu = &phy_data->nr_sl_pssch_sci_pdu;
|
||||
// compute number of REs containing SCI2
|
||||
int sci2_re = get_NREsci2_2(phy_data->nr_sl_pssch_sci_pdu.sci2_alpha_times_100,
|
||||
phy_data->nr_sl_pssch_sci_pdu.sci2_len,
|
||||
phy_data->nr_sl_pssch_sci_pdu.sci2_beta_offset,
|
||||
phy_data->nr_sl_pssch_sci_pdu.pssch_numsym,
|
||||
phy_data->nr_sl_pssch_sci_pdu.pscch_numsym,
|
||||
phy_data->nr_sl_pssch_sci_pdu.pscch_numrbs,
|
||||
phy_data->nr_sl_pssch_sci_pdu.l_subch,
|
||||
phy_data->nr_sl_pssch_sci_pdu.subchannel_size,
|
||||
phy_data->nr_sl_pssch_sci_pdu.targetCodeRate,
|
||||
0);
|
||||
LOG_D(NR_PHY,"Starting slot FEP for SLSCH (symbol %d to %d) pscch_numsym %d pssch_numsym %d REs with SCI2 %d\n",
|
||||
1 + phy_data->nr_sl_pssch_sci_pdu.pscch_numsym, phy_data->nr_sl_pssch_sci_pdu.pssch_numsym,
|
||||
phy_data->nr_sl_pssch_sci_pdu.pscch_numsym, phy_data->nr_sl_pssch_sci_pdu.pssch_numsym, sci2_re);
|
||||
for (int sym=1+phy_data->nr_sl_pssch_sci_pdu.pscch_numsym; sym<=phy_data->nr_sl_pssch_sci_pdu.pssch_numsym;sym++) {
|
||||
nr_slot_fep(ue,
|
||||
fp,
|
||||
proc,
|
||||
sym,
|
||||
rxdataF,
|
||||
link_type_sl);
|
||||
|
||||
}
|
||||
|
||||
nr_rx_pusch(NULL,
|
||||
ue,
|
||||
proc,
|
||||
phy_data,
|
||||
rxdataF_sz,
|
||||
rxdataF,
|
||||
0,
|
||||
frame_rx,
|
||||
nr_slot_rx,
|
||||
0,
|
||||
&is_csi_rs_slot);
|
||||
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_PSFCH) {
|
||||
ack_nack_rcvd = calloc(phy_data->num_psfch_pdus, sizeof(ack_nack_rcvd));
|
||||
LOG_D(NR_PHY, "num_psfch_pdus: %d\n", phy_data->num_psfch_pdus);
|
||||
for (int k = 0; k < phy_data->num_psfch_pdus; k++) {
|
||||
sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu = &phy_data->psfch_pdu_list[k];
|
||||
LOG_D(NR_PHY, "%s start_symbol_index %d, sl_bwp_start %d, sequence_hop_flag %d, \
|
||||
second_hop_prb %d, prb %d, nr_of_symbols %d, initial_cyclic_shift %d, hopping_id %d, \
|
||||
group_hop_flag %d, freq_hop_flag %d, bit_len_harq %d\n",
|
||||
__FUNCTION__,
|
||||
psfch_pdu->start_symbol_index, psfch_pdu->sl_bwp_start,
|
||||
psfch_pdu->sequence_hop_flag, psfch_pdu->second_hop_prb, psfch_pdu->prb,
|
||||
psfch_pdu->nr_of_symbols, psfch_pdu->initial_cyclic_shift, psfch_pdu->hopping_id,
|
||||
psfch_pdu->group_hop_flag, psfch_pdu->freq_hop_flag, psfch_pdu->bit_len_harq);
|
||||
nr_slot_fep(ue,
|
||||
fp,
|
||||
proc,
|
||||
psfch_pdu->start_symbol_index,
|
||||
rxdataF,
|
||||
link_type_sl);
|
||||
ack_nack_rcvd[k] = nr_ue_decode_psfch0(ue,
|
||||
frame_rx,
|
||||
nr_slot_rx,
|
||||
rxdataF,
|
||||
psfch_pdu);
|
||||
}
|
||||
free(phy_data->psfch_pdu_list);
|
||||
phy_data->psfch_pdu_list = NULL;
|
||||
}
|
||||
NR_gNB_PUSCH *pssch_vars = &ue->pssch_vars[0];
|
||||
pssch_vars->ulsch_power_tot = 0;
|
||||
pssch_vars->ulsch_noise_power_tot = 0;
|
||||
for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++) {
|
||||
pssch_vars->ulsch_power[aarx] /= num_dmrs;
|
||||
pssch_vars->ulsch_power_tot += pssch_vars->ulsch_power[aarx];
|
||||
pssch_vars->ulsch_noise_power[aarx] /= num_dmrs;
|
||||
pssch_vars->ulsch_noise_power_tot += pssch_vars->ulsch_noise_power[aarx];
|
||||
}
|
||||
if (dB_fixed_x10(pssch_vars->ulsch_power_tot) < dB_fixed_x10(pssch_vars->ulsch_noise_power_tot) + ue->pssch_thres) {
|
||||
|
||||
LOG_D(NR_PHY,
|
||||
"PSSCH not detected in %d.%d (%d,%d,%d)\n",
|
||||
frame_rx,
|
||||
nr_slot_rx,
|
||||
dB_fixed_x10(pssch_vars->ulsch_power_tot),
|
||||
dB_fixed_x10(pssch_vars->ulsch_noise_power_tot),
|
||||
ue->pssch_thres);
|
||||
pssch_vars->ulsch_power_tot = pssch_vars->ulsch_noise_power_tot;
|
||||
pssch_vars->DTX = 1;
|
||||
//if (stats)
|
||||
// stats->ulsch_stats.DTX++;
|
||||
// nr_fill_indication(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid, 1, 1);
|
||||
//pssch_DTX++;
|
||||
// continue;
|
||||
} else {
|
||||
pssch_vars->DTX = 0;
|
||||
int totalDecode = nr_slsch_procedures(ue, frame_rx, nr_slot_rx, 0, proc, phy_data, is_csi_rs_slot, ack_nack_rcvd, phy_data->num_psfch_pdus);
|
||||
LOG_D(NR_PHY,
|
||||
"Total %d decoded PSSCH detected in %d.%d (%d,%d,%d)\n",
|
||||
totalDecode,
|
||||
frame_rx,
|
||||
nr_slot_rx,
|
||||
dB_fixed_x10(pssch_vars->ulsch_power_tot),
|
||||
dB_fixed_x10(pssch_vars->ulsch_noise_power_tot),
|
||||
ue->pssch_thres);
|
||||
}
|
||||
}
|
||||
LOG_D(PHY,"****** end Sidelink RX-Chain for AbsSubframe %d.%d ******\n",
|
||||
frame_rx, nr_slot_rx);
|
||||
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_SL, VCD_FUNCTION_OUT);
|
||||
stop_meas(&sl_phy_params->phy_proc_sl_tx);
|
||||
|
||||
return;
|
||||
}
|
||||
int phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
nr_phy_data_tx_t *phy_data)
|
||||
{
|
||||
|
||||
int slot_tx = proc->nr_slot_tx;
|
||||
int frame_tx = proc->frame_tx;
|
||||
int tx_action = 0;
|
||||
|
||||
const char *sl_tx_actions[] = {"PSBCH", "PSCCH_PSSCH", "PSCCH_PSSCH_PSFCH", "PSCCH_PSSCH_CSI_RS"};
|
||||
if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS) {
|
||||
LOG_D(NR_PHY, "Generating %s (%d.%d)\n", sl_tx_actions[phy_data->sl_tx_action - SL_NR_CONFIG_TYPE_TX_PSBCH], frame_tx, slot_tx);
|
||||
}
|
||||
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
|
||||
NR_DL_FRAME_PARMS *fp = &sl_phy_params->sl_frame_params;
|
||||
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_SL,VCD_FUNCTION_IN);
|
||||
|
||||
const int samplesF_per_slot = NR_SYMBOLS_PER_SLOT * fp->ofdm_symbol_size;
|
||||
c16_t txdataF_buf[fp->nb_antennas_tx * samplesF_per_slot] __attribute__((aligned(32)));
|
||||
memset(txdataF_buf, 0, sizeof(txdataF_buf));
|
||||
c16_t *txdataF[fp->nb_antennas_tx]; /* workaround to be compatible with current txdataF usage in all tx procedures. */
|
||||
for(int i=0; i< fp->nb_antennas_tx; ++i)
|
||||
txdataF[i] = &txdataF_buf[i * samplesF_per_slot];
|
||||
|
||||
LOG_D(PHY,"****** start Sidelink TX-Chain for AbsSubframe %d.%d ******\n",
|
||||
frame_tx, slot_tx);
|
||||
|
||||
start_meas(&sl_phy_params->phy_proc_sl_tx);
|
||||
|
||||
if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSBCH) {
|
||||
sl_nr_tx_config_psbch_pdu_t *psbch_vars = &phy_data->psbch_vars;
|
||||
nr_tx_psbch(ue, frame_tx, slot_tx, psbch_vars, txdataF);
|
||||
sl_phy_params->psbch.num_psbch_tx ++;
|
||||
|
||||
tx_action = 1;
|
||||
}
|
||||
else if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH ||
|
||||
phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS ||
|
||||
phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH) {
|
||||
if (phy_data->sl_tx_action >= SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH && phy_data->sl_tx_action <= SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS)
|
||||
LOG_D(NR_PHY, "(%d.%d) Sending %s\n", frame_tx, slot_tx, sl_tx_actions[phy_data->sl_tx_action - SL_NR_CONFIG_TYPE_TX_PSBCH]);
|
||||
phy_data->pscch_Nid = nr_generate_sci1(ue, txdataF[0], fp, AMP, slot_tx, &phy_data->nr_sl_pssch_pscch_pdu) &0xFFFF;
|
||||
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)&phy_data->nr_sl_pssch_pscch_pdu.nr_sl_csi_rs_pdu;
|
||||
csi_params->scramb_id = phy_data->pscch_Nid % (1 << 10);
|
||||
for (uint8_t harq_pid = 0; harq_pid < NR_MAX_ULSCH_HARQ_PROCESSES; harq_pid++) {
|
||||
if (ue->sl_harq_processes[harq_pid].status == ACTIVE) {
|
||||
nr_ue_ulsch_procedures(ue, harq_pid, frame_tx, slot_tx, 0, phy_data, txdataF);
|
||||
}
|
||||
}
|
||||
|
||||
sl_phy_params->pscch.num_pscch_tx ++;
|
||||
sl_phy_params->pssch.num_pssch_sci2_tx ++;
|
||||
sl_phy_params->pssch.num_pssch_tx ++;
|
||||
if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS) {
|
||||
uint16_t beta_csirs = get_softmodem_params()->sl_mode ? (uint16_t)(AMP * (ceil(sqrt(phy_data->nr_sl_pssch_pscch_pdu.num_layers / fp->nb_antennas_tx)))) & 0xFFFF : AMP;
|
||||
LOG_D(NR_PHY, "Tx beta_csirs: %d, scramb_id %i (%d.%d)\n", beta_csirs, csi_params->scramb_id, frame_tx, slot_tx);
|
||||
nr_generate_csi_rs(fp,
|
||||
(int32_t **)txdataF,
|
||||
beta_csirs,
|
||||
ue->nr_csi_info,
|
||||
csi_params,
|
||||
slot_tx,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH) {
|
||||
for (int k = 0; k < phy_data->nr_sl_pssch_pscch_pdu.num_psfch_pdus; k++) {
|
||||
nr_generate_psfch0(ue,
|
||||
txdataF,
|
||||
fp,
|
||||
AMP,
|
||||
slot_tx,
|
||||
&phy_data->nr_sl_pssch_pscch_pdu.psfch_pdu_list[k]);
|
||||
}
|
||||
sl_phy_params->psfch.num_psfch_tx ++;
|
||||
free(phy_data->nr_sl_pssch_pscch_pdu.psfch_pdu_list);
|
||||
phy_data->nr_sl_pssch_pscch_pdu.psfch_pdu_list = NULL;
|
||||
}
|
||||
tx_action = 1;
|
||||
}
|
||||
if (tx_action) {
|
||||
LOG_D(PHY, "Sending SL data \n");
|
||||
nr_ue_pusch_common_procedures(ue,
|
||||
proc->nr_slot_tx,
|
||||
fp,
|
||||
fp->nb_antennas_tx,
|
||||
txdataF, link_type_sl);
|
||||
|
||||
}
|
||||
LOG_D(PHY,"****** end Sidelink TX-Chain for AbsSubframe %d.%d ******\n",
|
||||
frame_tx, slot_tx);
|
||||
return tx_action;
|
||||
}
|
||||
@@ -45,8 +45,9 @@
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include "common/openairinterface5g_limits.h"
|
||||
|
||||
|
||||
#include "pdcp.h"
|
||||
#include <executables/nr-uesoftmodem.h>
|
||||
|
||||
char nl_rx_buf[NL_MAX_PAYLOAD];
|
||||
|
||||
@@ -65,7 +66,24 @@ struct msghdr nas_msg_rx;
|
||||
|
||||
#define GRAAL_NETLINK_ID 31
|
||||
|
||||
static int tun_alloc(char *dev) {
|
||||
//Jin add for TAP
|
||||
typedef enum {
|
||||
OAI_TUNTAP_TUN = 0,
|
||||
OAI_TUNTAP_TAP = 1
|
||||
} oai_tuntap_mode_t;
|
||||
|
||||
static oai_tuntap_mode_t oai_get_tuntap_mode(void)
|
||||
{
|
||||
// Default: TUN (keeps your current behaviour)
|
||||
const char *s = getenv("OAI_TUNTAP_MODE"); // set to "tap" to enable TAP
|
||||
if (s && !strcasecmp(s, "tap"))
|
||||
return OAI_TUNTAP_TAP;
|
||||
return OAI_TUNTAP_TUN;
|
||||
}
|
||||
//Jin TAP end
|
||||
|
||||
//static int tun_alloc(char *dev) { //Jin origin
|
||||
static int tun_alloc(char *dev, oai_tuntap_mode_t mode) { //Jin replace TAP
|
||||
struct ifreq ifr;
|
||||
int fd, err;
|
||||
|
||||
@@ -80,7 +98,8 @@ static int tun_alloc(char *dev) {
|
||||
*
|
||||
* IFF_NO_PI - Do not provide packet information
|
||||
*/
|
||||
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
|
||||
//ifr.ifr_flags = IFF_TUN | IFF_NO_PI; //Jin origin
|
||||
ifr.ifr_flags = ((mode == OAI_TUNTAP_TAP) ? IFF_TAP : IFF_TUN) | IFF_NO_PI; //Jin replace TAP
|
||||
|
||||
if( *dev )
|
||||
strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)-1);
|
||||
@@ -105,14 +124,19 @@ int netlink_init_mbms_tun(char *ifprefix, int id) {//for UE, id = 1, 2, ...,
|
||||
else {
|
||||
sprintf(ifname, "oaitun_%.3s1", ifprefix); // added "1": for historical reasons
|
||||
}
|
||||
nas_sock_mbms_fd = tun_alloc(ifname);
|
||||
// nas_sock_mbms_fd = tun_alloc(ifname); //Jin origin
|
||||
oai_tuntap_mode_t mode = oai_get_tuntap_mode(); //Jin TAP
|
||||
nas_sock_mbms_fd = tun_alloc(ifname, mode); //Jin add TAP
|
||||
|
||||
if (nas_sock_mbms_fd == -1) {
|
||||
printf("[NETLINK] Error opening mbms socket %s (%d:%s)\n",ifname,errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("[NETLINK]Opened socket %s with fd %d\n",ifname,nas_sock_mbms_fd);
|
||||
//printf("[NETLINK]Opened socket %s with fd %d\n",ifname,nas_sock_mbms_fd); //Jin origin
|
||||
printf("[Jin TAP TAP NETLINK]%s Opened socket %s with fd %d\n", //Jin have a look at TAP
|
||||
(mode == OAI_TUNTAP_TAP) ? "TAP" : "TUN",
|
||||
ifname, nas_sock_mbms_fd);
|
||||
ret = fcntl(nas_sock_mbms_fd,F_SETFL,O_NONBLOCK);
|
||||
|
||||
if (ret == -1) {
|
||||
@@ -135,24 +159,33 @@ int netlink_init_mbms_tun(char *ifprefix, int id) {//for UE, id = 1, 2, ...,
|
||||
int netlink_init_tun(char *ifprefix, int num_if, int id) {//for UE, id = 1, 2, ...,
|
||||
int ret;
|
||||
char ifname[64];
|
||||
oai_tuntap_mode_t mode = oai_get_tuntap_mode(); //Jin add TAP
|
||||
|
||||
int begx = (id == 0) ? 0 : id - 1;
|
||||
int endx = (id == 0) ? num_if : id;
|
||||
int index;
|
||||
for (int i = begx; i < endx; i++) {
|
||||
sprintf(ifname, "oaitun_%.3s%d",ifprefix,i+1);
|
||||
nas_sock_fd[i] = tun_alloc(ifname);
|
||||
sprintf(ifname, "oaitun_%.3s%d", ifprefix, i+1);
|
||||
//index = get_softmodem_params()->sl_mode ? 0 : i; //Jin origin
|
||||
index = i; //Jin replace so TAP has different endpoints for multiple UES
|
||||
//nas_sock_fd[index] = tun_alloc(ifname); //Jin origin
|
||||
oai_tuntap_mode_t mode = oai_get_tuntap_mode(); //Jin add TAP
|
||||
nas_sock_fd[index] = tun_alloc(ifname, mode); //Jin add TAP
|
||||
|
||||
if (nas_sock_fd[i] == -1) {
|
||||
LOG_E(PDCP, "TUN: Error opening socket %s (%d:%s)\n",ifname,errno, strerror(errno));
|
||||
if (nas_sock_fd[index] == -1) {
|
||||
LOG_E(PDCP, "TUN: Error opening socket %s (%d:%s)\n", ifname, errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
LOG_I(PDCP, "TUN: Opened socket %s with fd nas_sock_fd[%d]=%d\n",
|
||||
ifname, i, nas_sock_fd[i]);
|
||||
ret = fcntl(nas_sock_fd[i],F_SETFL,O_NONBLOCK);
|
||||
ifname, index, nas_sock_fd[index]);
|
||||
LOG_D(PDCP, "JIN LOG TAP !!!!!!!!!! %s: Opened socket %s with fd nas_sock_fd[%d]=%d\n",
|
||||
(mode == OAI_TUNTAP_TAP) ? "TAP" : "TUN",
|
||||
ifname, index, nas_sock_fd[index]);
|
||||
ret = fcntl(nas_sock_fd[index], F_SETFL, O_NONBLOCK);
|
||||
|
||||
if (ret == -1) {
|
||||
LOG_E(PDCP, "TUN: Error fcntl (%d:%s)\n",errno, strerror(errno));
|
||||
LOG_E(PDCP, "TUN: Error fcntl (%d:%s)\n", errno, strerror(errno));
|
||||
|
||||
if (LINK_ENB_PDCP_TO_IP_DRIVER) {
|
||||
exit(1);
|
||||
@@ -224,4 +257,4 @@ void netlink_cleanup(void)
|
||||
{
|
||||
free(nas_nlh_tx);
|
||||
nas_nlh_tx = NULL;
|
||||
}
|
||||
}
|
||||
@@ -846,7 +846,7 @@ int main(int argc, char **argv)
|
||||
|
||||
// compute the scramblingID_pdcch and the gold pdcch
|
||||
UE->scramblingID_pdcch = frame_parms->Nid_cell;
|
||||
nr_gold_pdcch(UE, frame_parms->Nid_cell);
|
||||
nr_gold_pdcch(&UE->frame_parms, UE->nr_gold_pdcch[0],frame_parms->Nid_cell);
|
||||
|
||||
// compute the scrambling IDs for PDSCH DMRS
|
||||
for (int i = 0; i < 2; i++) {
|
||||
@@ -854,7 +854,7 @@ int main(int argc, char **argv)
|
||||
nr_gold_pdsch(UE, i, UE->scramblingID_dlsch[i]);
|
||||
}
|
||||
|
||||
nr_l2_init_ue(NULL);
|
||||
nr_l2_init_ue(NULL, NULL);
|
||||
UE_mac = get_mac_inst(0);
|
||||
ue_init_config_request(UE_mac, mu);
|
||||
|
||||
|
||||
@@ -49,3 +49,12 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id,
|
||||
const channel_t channel,
|
||||
const uint8_t* pduP,
|
||||
const sdu_size_t pdu_len) { return 0; }
|
||||
int8_t nr_mac_rrc_sl_mib_ind(const module_id_t module_id,
|
||||
const int CC_id,
|
||||
const uint8_t gNB_index,
|
||||
const frame_t frame,
|
||||
const int slot,
|
||||
const int channel,
|
||||
const uint8_t* pduP,
|
||||
const sdu_size_t pdu_len,
|
||||
const uint16_t rx_slss_id) {return 1;}
|
||||
|
||||
@@ -116,7 +116,8 @@ int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
|
||||
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
|
||||
nr_phy_data_t *phy_data,
|
||||
int n_ss,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
|
||||
int *rsrp_dBm) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -797,12 +798,13 @@ int main(int argc, char **argv)
|
||||
proc.gNB_id = 0;
|
||||
for (int i=UE->symbol_offset+1; i<UE->symbol_offset+4; i++) {
|
||||
nr_slot_fep(UE,
|
||||
frame_parms,
|
||||
&proc,
|
||||
i%frame_parms->symbols_per_slot,
|
||||
rxdataF);
|
||||
rxdataF, link_type_dl);
|
||||
|
||||
nr_pbch_channel_estimation(UE,estimateSz, dl_ch_estimates, dl_ch_estimates_time, &proc,
|
||||
i%frame_parms->symbols_per_slot,i-(UE->symbol_offset+1),ssb_index%8,n_hf,rxdataF);
|
||||
nr_pbch_channel_estimation(UE,&UE->frame_parms, estimateSz, dl_ch_estimates, dl_ch_estimates_time, &proc,
|
||||
i%frame_parms->symbols_per_slot,i-(UE->symbol_offset+1),ssb_index%8,n_hf,rxdataF,false,frame_parms->Nid_cell);
|
||||
|
||||
}
|
||||
fapiPbch_t result;
|
||||
|
||||
657
openair1/SIMULATION/NR_PHY/psbchsim.c
Normal file
657
openair1/SIMULATION/NR_PHY/psbchsim.c
Normal file
@@ -0,0 +1,657 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "common/ran_context.h"
|
||||
#include "PHY/types.h"
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/phy_vars.h"
|
||||
#include "NR_MasterInformationBlockSidelink.h"
|
||||
#include "PHY/INIT/phy_init.h"
|
||||
#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h"
|
||||
#include "openair1/SIMULATION/TOOLS/sim.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "openair2/RRC/NR/nr_rrc_extern.h"
|
||||
#include "openair2/RRC/LTE/rrc_vars.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "PHY/INIT/nr_phy_init.h"
|
||||
#include "SIMULATION/RF/rf.h"
|
||||
#include "common/utils/load_module_shlib.h"
|
||||
#include "PHY/MODULATION/nr_modulation.h"
|
||||
#include "NR_SL-SSB-TimeAllocation-r16.h"
|
||||
void exit_function(const char* file, const char* function, const int line, const char* s, const int assert) {
|
||||
const char * msg= s==NULL ? "no comment": s;
|
||||
printf("Exiting at: %s:%d %s(), %s\n", file, line, function, msg);
|
||||
exit(-1);
|
||||
}
|
||||
int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) { return 1; }
|
||||
// to solve link errors
|
||||
double cpuf;
|
||||
//void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {}
|
||||
void get_num_re_dmrs(nfapi_nr_ue_pusch_pdu_t *pusch_pdu,
|
||||
uint8_t *nb_dmrs_re_per_rb,
|
||||
uint16_t *number_dmrs_symbols){}
|
||||
uint64_t downlink_frequency[1][1];
|
||||
int32_t uplink_frequency_offset[1][1];
|
||||
THREAD_STRUCT thread_struct;
|
||||
instance_t DUuniqInstance=0;
|
||||
instance_t CUuniqInstance=0;
|
||||
openair0_config_t openair0_cfg[1];
|
||||
|
||||
RAN_CONTEXT_t RC;
|
||||
int oai_exit = 0;
|
||||
char *uecap_file;
|
||||
|
||||
void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP,
|
||||
const int CC_id,
|
||||
const uint8_t gNB_id,
|
||||
const frame_t frameP,
|
||||
const rb_id_t Srb_id,
|
||||
uint8_t *buffer_pP)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
nr_bler_struct nr_bler_data[NR_NUM_MCS];
|
||||
void get_nrUE_params(void) { return;}
|
||||
uint8_t check_if_ue_is_sl_syncsource() {return 0;}
|
||||
void nr_rrc_mac_config_req_sl_mib(module_id_t module_id,
|
||||
NR_SL_SSB_TimeAllocation_r16_t *ssb_ta,
|
||||
uint16_t rx_slss_id,
|
||||
uint8_t *sl_mib) {}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
static void prepare_mib_bits(uint8_t *buf, uint32_t frame_tx, uint32_t slot_tx) {
|
||||
|
||||
NR_MasterInformationBlockSidelink_t *sl_mib;
|
||||
asn_enc_rval_t enc_rval;
|
||||
|
||||
void *buffer = (void *)buf;
|
||||
|
||||
sl_mib = CALLOC(1, sizeof(NR_MasterInformationBlockSidelink_t));
|
||||
|
||||
sl_mib->inCoverage_r16 = 0;//TRUE;
|
||||
|
||||
// allocate buffer for 7 bits slotnumber
|
||||
sl_mib->slotIndex_r16.size = 1;
|
||||
sl_mib->slotIndex_r16.buf = CALLOC(1, sl_mib->slotIndex_r16.size);
|
||||
sl_mib->slotIndex_r16.bits_unused = sl_mib->slotIndex_r16.size*8 - 7;
|
||||
sl_mib->slotIndex_r16.buf[0] = slot_tx << sl_mib->slotIndex_r16.bits_unused;
|
||||
|
||||
sl_mib->directFrameNumber_r16.size = 2;
|
||||
sl_mib->directFrameNumber_r16.buf = CALLOC(1, sl_mib->directFrameNumber_r16.size);
|
||||
sl_mib->directFrameNumber_r16.bits_unused = sl_mib->directFrameNumber_r16.size*8 - 10;
|
||||
sl_mib->directFrameNumber_r16.buf[0] = frame_tx >> (8 - sl_mib->directFrameNumber_r16.bits_unused);
|
||||
sl_mib->directFrameNumber_r16.buf[1] = frame_tx << sl_mib->directFrameNumber_r16.bits_unused;
|
||||
|
||||
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_MasterInformationBlockSidelink,
|
||||
NULL,
|
||||
(void *)sl_mib,
|
||||
buffer,
|
||||
100);
|
||||
|
||||
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
|
||||
enc_rval.failed_type->name, enc_rval.encoded);
|
||||
|
||||
asn_DEF_NR_MasterInformationBlockSidelink.op->free_struct(&asn_DEF_NR_MasterInformationBlockSidelink, sl_mib, ASFM_FREE_EVERYTHING);
|
||||
|
||||
}
|
||||
|
||||
static int test_rx_mib(uint8_t *decoded_output, uint16_t frame, uint16_t slot) {
|
||||
|
||||
uint32_t sl_mib = *(uint32_t *)decoded_output;
|
||||
|
||||
uint32_t fn = 0, sl = 0;
|
||||
fn = (((sl_mib & 0x0700) >> 1) | ((sl_mib & 0xFE0000) >> 17));
|
||||
sl = (((sl_mib & 0x010000) >> 10) | ((sl_mib & 0xFC000000) >> 26));
|
||||
|
||||
printf("decoded output:%x, TX %d:%d, timing decoded from sl-MIB %d:%d\n",
|
||||
*(uint32_t *)decoded_output, frame, slot, fn, sl);
|
||||
|
||||
if (frame == fn && slot == sl)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void configure_NR_UE(PHY_VARS_NR_UE *UE, int mu, int N_RB) {
|
||||
|
||||
fapi_nr_config_request_t config;
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
|
||||
config.ssb_config.scs_common = mu;
|
||||
config.cell_config.frame_duplex_type = TDD;
|
||||
config.carrier_config.dl_grid_size[mu] = N_RB;
|
||||
config.carrier_config.ul_grid_size[mu] = N_RB;
|
||||
config.carrier_config.dl_frequency = 0;
|
||||
config.carrier_config.uplink_frequency = 0;
|
||||
|
||||
int band;
|
||||
if (mu == 1) band = 78;
|
||||
if (mu == 0) band = 34;
|
||||
nr_init_frame_parms_ue(fp, &config, band);
|
||||
fp->ofdm_offset_divisor = 8;
|
||||
nr_dump_frame_parms(fp);
|
||||
|
||||
if (init_nr_ue_signal(UE, 1) != 0) {
|
||||
printf("Error at UE NR initialisation\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
static void sl_init_frame_parameters(PHY_VARS_NR_UE *UE) {
|
||||
|
||||
NR_DL_FRAME_PARMS *nr_fp = &UE->frame_parms;
|
||||
NR_DL_FRAME_PARMS *sl_fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
memcpy(sl_fp, nr_fp, sizeof(NR_DL_FRAME_PARMS));
|
||||
sl_fp->ofdm_offset_divisor = 8; // What is this used for?
|
||||
|
||||
sl_fp->att_tx = 1;
|
||||
sl_fp->att_rx = 1;
|
||||
// band47 //UL freq will be set to Sidelink freq
|
||||
sl_fp->ul_CarrierFreq = 5880000000;
|
||||
|
||||
sl_fp->ssb_start_subcarrier = UE->SL_UE_PHY_PARAMS.sl_config.sl_bwp_config.sl_ssb_offset_point_a;
|
||||
sl_fp->Nid_cell = UE->SL_UE_PHY_PARAMS.sl_config.sl_sync_source.rx_slss_id;
|
||||
|
||||
#ifdef DEBUG_INIT
|
||||
LOG_I(PHY, "Dumping Sidelink Frame Parameters\n");
|
||||
nr_dump_frame_parms(sl_fp);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static void configure_SL_UE(PHY_VARS_NR_UE *UE, int mu, int N_RB, int ssb_offset, int slss_id) {
|
||||
|
||||
sl_nr_phy_config_request_t *config = &UE->SL_UE_PHY_PARAMS.sl_config;
|
||||
NR_DL_FRAME_PARMS *fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
config->sl_bwp_config.sl_scs = mu;
|
||||
config->sl_bwp_config.sl_ssb_offset_point_a = ssb_offset;
|
||||
config->sl_carrier_config.sl_bandwidth = N_RB;
|
||||
config->sl_carrier_config.sl_grid_size = 106;
|
||||
config->sl_sync_source.rx_slss_id = slss_id;
|
||||
|
||||
sl_init_frame_parameters(UE);
|
||||
sl_ue_phy_init(UE);
|
||||
init_symbol_rotation(fp);
|
||||
init_timeshift_rotation(fp);
|
||||
LOG_I(PHY, "Dumping Sidelink Frame Parameters\n");
|
||||
nr_dump_frame_parms(fp);
|
||||
}
|
||||
|
||||
static int freq_domain_loopback(PHY_VARS_NR_UE *UE_tx, PHY_VARS_NR_UE *UE_rx,
|
||||
int frame, int slot,
|
||||
nr_phy_data_tx_t *phy_data) {
|
||||
|
||||
sl_nr_ue_phy_params_t *sl_ue1 = &UE_tx->SL_UE_PHY_PARAMS;
|
||||
sl_nr_ue_phy_params_t *sl_ue2 = &UE_rx->SL_UE_PHY_PARAMS;
|
||||
|
||||
printf("\nPSBCH SIM -F: %d:%d slss id TX UE:%d, RX UE:%d\n",
|
||||
frame, slot,phy_data->psbch_vars.tx_slss_id,
|
||||
sl_ue2->sl_config.sl_sync_source.rx_slss_id);
|
||||
|
||||
NR_DL_FRAME_PARMS *fp = &sl_ue1->sl_frame_params;
|
||||
const int samplesF_per_slot = NR_SYMBOLS_PER_SLOT * fp->ofdm_symbol_size;
|
||||
c16_t txdataF_buf[fp->nb_antennas_tx * samplesF_per_slot] __attribute__((aligned(32)));
|
||||
memset(txdataF_buf, 0, sizeof(txdataF_buf));
|
||||
c16_t *txdataF[fp->nb_antennas_tx]; /* workaround to be compatible with current txdataF usage in all tx procedures. */
|
||||
for(int i=0; i< fp->nb_antennas_tx; ++i)
|
||||
txdataF[i] = &txdataF_buf[i * samplesF_per_slot];
|
||||
|
||||
nr_tx_psbch(UE_tx,frame, slot, &phy_data->psbch_vars, txdataF);
|
||||
|
||||
int estimateSz = sl_ue2->sl_frame_params.samples_per_slot_wCP;
|
||||
__attribute__ ((aligned(32))) struct complex16 rxdataF[1][estimateSz];
|
||||
for (int i=0; i<sl_ue1->sl_frame_params.samples_per_slot_wCP; i++) {
|
||||
struct complex16 *txdataF_ptr = (struct complex16 *)&txdataF[0][i];
|
||||
struct complex16 *rxdataF_ptr = (struct complex16 *)&rxdataF[0][i];
|
||||
rxdataF_ptr->r = txdataF_ptr->r;
|
||||
rxdataF_ptr->i = txdataF_ptr->i;
|
||||
//printf("r,i TXDATAF[%d]- %d:%d, RXDATAF[%d]- %d:%d\n",
|
||||
// i, txdataF_ptr->r, txdataF_ptr->i, i, txdataF_ptr->r, txdataF_ptr->i);
|
||||
}
|
||||
|
||||
uint8_t err_status = 0;
|
||||
|
||||
UE_nr_rxtx_proc_t proc;
|
||||
proc.frame_rx = frame;
|
||||
proc.nr_slot_rx = slot;
|
||||
|
||||
struct complex16 dl_ch_estimates[1][estimateSz];
|
||||
uint8_t decoded_output[4] = {0};
|
||||
|
||||
LOG_I(PHY,"DEBUG: HIJACKING DL CHANNEL ESTIMATES.\n");
|
||||
for (int s=0; s<14; s++) {
|
||||
for (int j=0; j<sl_ue2->sl_frame_params.ofdm_symbol_size; j++) {
|
||||
struct complex16 *dlch = (struct complex16 *)(&dl_ch_estimates[0][s*sl_ue2->sl_frame_params.ofdm_symbol_size]);
|
||||
dlch[j].r = 128;
|
||||
dlch[j].i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
err_status = nr_rx_psbch(UE_rx,
|
||||
&proc,
|
||||
estimateSz,
|
||||
dl_ch_estimates,
|
||||
&sl_ue2->sl_frame_params,
|
||||
decoded_output,
|
||||
rxdataF,
|
||||
sl_ue2->sl_config.sl_sync_source.rx_slss_id);
|
||||
|
||||
|
||||
int error_payload = 0;
|
||||
error_payload = test_rx_mib(decoded_output, frame, slot);
|
||||
|
||||
if (err_status == 0 || error_payload == 0) {
|
||||
LOG_I(PHY,"---------PSBCH -F TEST OK.\n");
|
||||
return 0;
|
||||
}
|
||||
LOG_E(PHY, "--------PSBCH -F TEST NOK. FAIL.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
PHY_VARS_NR_UE *UE_TX; // for tx
|
||||
PHY_VARS_NR_UE *UE_RX; // for rx
|
||||
double cpuf;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
char c;
|
||||
int test_freqdomain_loopback = 0,test_slss_search = 0;
|
||||
int frame = 5, slot = 10, frame_tx = 0, slot_tx = 0;
|
||||
int loglvl = OAILOG_INFO;
|
||||
uint16_t slss_id = 336, ssb_offset = 0;
|
||||
double snr1 = 2.0, snr0 = 2.0, SNR;
|
||||
double sigma2 = 0.0, sigma2_dB = 0.0;
|
||||
double cfo=0, ip =0.0;
|
||||
|
||||
SCM_t channel_model=AWGN;//Rayleigh1_anticorr;
|
||||
int N_RB_DL=106,mu=1;
|
||||
|
||||
uint16_t errors = 0, n_trials = 1;
|
||||
|
||||
int frame_length_complex_samples;
|
||||
//int frame_length_complex_samples_no_prefix;
|
||||
NR_DL_FRAME_PARMS *frame_parms;
|
||||
|
||||
int seed = 0;
|
||||
|
||||
cpuf = get_cpu_freq_GHz();
|
||||
|
||||
if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0 ) {
|
||||
exit_fun("SIDELINK PSBCH SIM Error, configuration module init failed\n");
|
||||
}
|
||||
|
||||
randominit(0);
|
||||
|
||||
while ((c = getopt(argc, argv, "c:hn:o:s:FIL:N:R:S:T:")) != -1) {
|
||||
|
||||
printf("SIDELINK PSBCH SIM: handling optarg %c\n",c);
|
||||
switch (c) {
|
||||
|
||||
case 'c':
|
||||
cfo = atof(optarg);
|
||||
printf("Setting CFO to %f Hz\n",cfo);
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
switch((char)*optarg) {
|
||||
case 'A':
|
||||
channel_model=SCM_A;
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
channel_model=SCM_B;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
channel_model=SCM_C;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
channel_model=SCM_D;
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
channel_model=EPA;
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
channel_model=EVA;
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
channel_model=ETU;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Unsupported channel model! Exiting.\n");
|
||||
exit(-1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
n_trials = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
ssb_offset = atoi(optarg);
|
||||
printf("SIDELINK PSBCH SIM: ssb offset from pointA:%d\n",ssb_offset);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
slss_id = atoi(optarg);
|
||||
printf("SIDELINK PSBCH SIM: slss_id from arg:%d\n",slss_id);
|
||||
AssertFatal(slss_id >= 0 && slss_id <= 671,"SLSS ID not within Range 0-671\n");
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
test_freqdomain_loopback = 1;
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
test_slss_search = 1;
|
||||
printf("SIDELINK PSBCH SIM: SLSS search will be tested\n");
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
loglvl = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
snr0 = atoi(optarg);
|
||||
snr1 = snr0;
|
||||
printf("Setting SNR0 to %f. Test uses this SNR as target SNR\n",snr0);
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
N_RB_DL = atoi(optarg);
|
||||
printf("SIDELINK PSBCH SIM: N_RB_DL:%d\n",N_RB_DL);
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
snr1 = atof(optarg);
|
||||
printf("Setting SNR1 to %f. Test will run until this SNR as target SNR\n",snr1);
|
||||
AssertFatal(snr1 <= snr0, "Test runs SNR down, set snr1 to a lower value than %f\n", snr0);
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
frame = atoi(argv[2]);
|
||||
slot = atoi(argv[3]);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
default :
|
||||
printf("\n\nSIDELINK PSBCH SIM OPTIONS LIST - hus:FL:T:\n");
|
||||
printf("-h: HELP\n");
|
||||
printf("-c Carrier frequency offset in Hz\n");
|
||||
printf("-n Number of trials\n");
|
||||
printf("-o ssb offset from PointA - indicates ssb_start subcarrier\n");
|
||||
printf("-s: set Sidelink sync id slss_id. ex -s 100\n");
|
||||
printf("-F: Run PSBCH frequency domain loopback test of the samples\n");
|
||||
printf("-I: Sidelink SLSS search will be tested.\n");
|
||||
printf("-L: Set Log Level.\n");
|
||||
printf("-N: Test with Noise. target SNR0 eg -N 10\n");
|
||||
printf("-R N_RB_DL\n");
|
||||
printf("-S Ending SNR, runs from SNR0 to SNR1\n");
|
||||
printf("-T: Frame,Slot to be sent in sl-MIB eg -T 4 2\n");
|
||||
return 1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
randominit(seed);
|
||||
|
||||
logInit();
|
||||
set_glog(loglvl);
|
||||
T_stdout = 1;
|
||||
|
||||
double fs=0, eps;
|
||||
double scs = 30000;
|
||||
double bw = 100e6;
|
||||
|
||||
switch (mu) {
|
||||
case 1:
|
||||
scs = 30000;
|
||||
if (N_RB_DL == 217) {
|
||||
fs = 122.88e6;
|
||||
bw = 80e6;
|
||||
}
|
||||
else if (N_RB_DL == 245) {
|
||||
fs = 122.88e6;
|
||||
bw = 90e6;
|
||||
}
|
||||
else if (N_RB_DL == 273) {
|
||||
fs = 122.88e6;
|
||||
bw = 100e6;
|
||||
}
|
||||
else if (N_RB_DL == 106) {
|
||||
fs = 61.44e6;
|
||||
bw = 40e6;
|
||||
}
|
||||
else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL);
|
||||
break;
|
||||
case 3:
|
||||
scs = 120000;
|
||||
if (N_RB_DL == 66) {
|
||||
fs = 122.88e6;
|
||||
bw = 100e6;
|
||||
}
|
||||
else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL);
|
||||
break;
|
||||
}
|
||||
|
||||
// cfo with respect to sub-carrier spacing
|
||||
eps = cfo/scs;
|
||||
|
||||
// computation of integer and fractional FO to compare with estimation results
|
||||
int IFO;
|
||||
if(eps!=0.0){
|
||||
printf("Introducing a CFO of %lf relative to SCS of %d kHz\n",eps,(int)(scs/1000));
|
||||
if (eps>0)
|
||||
IFO=(int)(eps+0.5);
|
||||
else
|
||||
IFO=(int)(eps-0.5);
|
||||
printf("FFO = %lf; IFO = %d\n",eps-IFO,IFO);
|
||||
}
|
||||
|
||||
channel_desc_t *UE2UE;
|
||||
int n_tx = 1, n_rx = 1;
|
||||
UE2UE = new_channel_desc_scm(n_tx,
|
||||
n_rx,
|
||||
channel_model,
|
||||
fs,
|
||||
0,
|
||||
bw,
|
||||
300e-9,
|
||||
0.0,
|
||||
CORR_LEVEL_LOW,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
|
||||
if (UE2UE==NULL) {
|
||||
printf("Problem generating channel model. Exiting.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*****configure UE *************************/
|
||||
UE_TX = calloc(1, sizeof(PHY_VARS_NR_UE));
|
||||
UE_RX = calloc(1, sizeof(PHY_VARS_NR_UE));
|
||||
LOG_I(PHY, "Configure UE-TX and sidelink UE-TX.\n");
|
||||
configure_NR_UE(UE_TX, mu, N_RB_DL);
|
||||
configure_SL_UE(UE_TX, mu, N_RB_DL,ssb_offset, 0xFFFF);
|
||||
|
||||
LOG_I(PHY, "Configure UE-RX and sidelink UE-RX.\n");
|
||||
configure_NR_UE(UE_RX, mu, N_RB_DL);
|
||||
UE_RX->is_synchronized = (test_slss_search) ? 0 : 1;
|
||||
configure_SL_UE(UE_RX, mu, N_RB_DL,ssb_offset, slss_id);
|
||||
/*****************************************/
|
||||
sl_nr_ue_phy_params_t *sl_uetx = &UE_TX->SL_UE_PHY_PARAMS;
|
||||
sl_nr_ue_phy_params_t *sl_uerx = &UE_RX->SL_UE_PHY_PARAMS;
|
||||
frame_parms = &sl_uetx->sl_frame_params;
|
||||
frame_tx = frame % 1024;
|
||||
slot_tx = slot % frame_parms->slots_per_frame;
|
||||
|
||||
frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
|
||||
//frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP;
|
||||
|
||||
double **s_re,**s_im,**r_re,**r_im;
|
||||
s_re = malloc(2*sizeof(double*));
|
||||
s_im = malloc(2*sizeof(double*));
|
||||
r_re = malloc(2*sizeof(double*));
|
||||
r_im = malloc(2*sizeof(double*));
|
||||
|
||||
s_re[0] = malloc16_clear(frame_length_complex_samples*sizeof(double));
|
||||
s_im[0] = malloc16_clear(frame_length_complex_samples*sizeof(double));
|
||||
r_re[0] = malloc16_clear(frame_length_complex_samples*sizeof(double));
|
||||
r_im[0] = malloc16_clear(frame_length_complex_samples*sizeof(double));
|
||||
|
||||
if(eps!=0.0)
|
||||
UE_RX->UE_fo_compensation = 1; // if a frequency offset is set then perform fo estimation and compensation
|
||||
|
||||
UE_nr_rxtx_proc_t proc;
|
||||
proc.frame_tx = frame;
|
||||
proc.nr_slot_tx = slot;
|
||||
nr_phy_data_tx_t phy_data_tx;
|
||||
phy_data_tx.psbch_vars.tx_slss_id = slss_id;
|
||||
|
||||
uint8_t sl_mib[4] = {0};
|
||||
prepare_mib_bits(sl_mib,frame, slot);
|
||||
memcpy(phy_data_tx.psbch_vars.psbch_payload,sl_mib, 4);
|
||||
|
||||
phy_data_tx.sl_tx_action = SL_NR_CONFIG_TYPE_TX_PSBCH;
|
||||
proc.frame_rx = frame;
|
||||
proc.nr_slot_rx = slot;
|
||||
nr_phy_data_t phy_data_rx;
|
||||
phy_data_rx.sl_rx_action = SL_NR_CONFIG_TYPE_RX_PSBCH;
|
||||
|
||||
if (test_freqdomain_loopback) {
|
||||
errors += freq_domain_loopback(UE_TX, UE_RX, frame_tx, slot_tx, &phy_data_tx);
|
||||
}
|
||||
|
||||
printf("\nSidelink TX UE - Frame.Slot %d.%d SLSS id:%d\n",
|
||||
frame, slot,phy_data_tx.psbch_vars.tx_slss_id);
|
||||
printf("Sidelink RX UE - Frame.Slot %d.%d SLSS id:%d\n",
|
||||
proc.frame_rx, proc.nr_slot_rx,
|
||||
sl_uerx->sl_config.sl_sync_source.rx_slss_id);
|
||||
|
||||
phy_procedures_nrUE_SL_TX(UE_TX, &proc, &phy_data_tx);
|
||||
|
||||
for (SNR=snr0; SNR>=snr1; SNR-=1) {
|
||||
|
||||
for (int trial=0; trial<n_trials; trial++) {
|
||||
|
||||
for (int i=0; i<frame_length_complex_samples; i++) {
|
||||
for (int aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
|
||||
struct complex16 *txdata_ptr = (struct complex16 *)&UE_TX->common_vars.txData[aa][i];
|
||||
r_re[aa][i] = (double)txdata_ptr->r;
|
||||
r_im[aa][i] = (double)txdata_ptr->i;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_M("txData0.m","txd0", UE_TX->common_vars.txData[0],frame_parms->samples_per_frame,1,1);
|
||||
|
||||
//AWGN
|
||||
sigma2_dB = 20*log10((double)AMP/4)-SNR;
|
||||
sigma2 = pow(10,sigma2_dB/10);
|
||||
//printf("sigma2 %f (%f dB), tx_lev %f (%f dB)\n",sigma2,sigma2_dB,txlev,10*log10((double)txlev));
|
||||
|
||||
if(eps!=0.0) {
|
||||
rf_rx(r_re, // real part of txdata
|
||||
r_im, // imag part of txdata
|
||||
NULL, // interference real part
|
||||
NULL, // interference imag part
|
||||
0, // interference power
|
||||
frame_parms->nb_antennas_rx, // number of rx antennas
|
||||
frame_length_complex_samples, // number of samples in frame
|
||||
1.0e9/fs, //sampling time (ns)
|
||||
cfo, // frequency offset in Hz
|
||||
0.0, // drift (not implemented)
|
||||
0.0, // noise figure (not implemented)
|
||||
0.0, // rx gain in dB ?
|
||||
200, // 3rd order non-linearity in dB ?
|
||||
&ip, // initial phase
|
||||
30.0e3, // phase noise cutoff in kHz
|
||||
-500.0, // phase noise amplitude in dBc
|
||||
0.0, // IQ imbalance (dB),
|
||||
0.0); // IQ phase imbalance (rad)
|
||||
}
|
||||
|
||||
for (int i=0; i<frame_length_complex_samples; i++) {
|
||||
for (int aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
||||
UE_RX->common_vars.rxdata[aa][i].r = (short)(r_re[aa][i] + sqrt(sigma2 / 2) * gaussdouble(0.0, 1.0));
|
||||
UE_RX->common_vars.rxdata[aa][i].i = (short)(r_im[aa][i] + sqrt(sigma2 / 2) * gaussdouble(0.0, 1.0));
|
||||
}
|
||||
}
|
||||
|
||||
if (UE_RX->is_synchronized == 0) {
|
||||
int ret = -1;
|
||||
UE_nr_rxtx_proc_t proc={0};
|
||||
//Should not have SLSS id configured. Search should find SLSS id from TX UE
|
||||
UE_RX->SL_UE_PHY_PARAMS.sl_config.sl_sync_source.rx_slss_id = 0xFFFF;
|
||||
ret = sl_nr_slss_search(UE_RX, &proc, 1);
|
||||
printf("Sidelink SLSS search returns %d\n",ret);
|
||||
if (ret!=0) sl_uerx->psbch.rx_errors = 1;
|
||||
else {
|
||||
AssertFatal(UE_RX->SL_UE_PHY_PARAMS.sync_params.N_sl_id == slss_id,
|
||||
"DETECTED INCORRECT SLSS ID in SEARCH.CHECK id:%d\n", UE_RX->SL_UE_PHY_PARAMS.sync_params.N_sl_id);
|
||||
sl_uerx->psbch.rx_ok = 1;
|
||||
}
|
||||
} else psbch_pscch_processing(UE_RX,&proc,&phy_data_rx);
|
||||
|
||||
} //noise trials
|
||||
|
||||
printf("Runs:%d SNR %f: SLSS Search:%d crc ERRORs = %d, OK = %d\n",
|
||||
n_trials, SNR, !UE_RX->is_synchronized,
|
||||
sl_uerx->psbch.rx_errors, sl_uerx->psbch.rx_ok);
|
||||
errors += sl_uerx->psbch.rx_errors;
|
||||
sl_uerx->psbch.rx_errors = 0;
|
||||
sl_uerx->psbch.rx_ok = 0;
|
||||
|
||||
} // NSR
|
||||
|
||||
if (errors == 0)
|
||||
LOG_I(PHY,"PSBCH test OK\n");
|
||||
else
|
||||
LOG_E(PHY,"PSBCH test NOT OK\n");
|
||||
|
||||
free_channel_desc_scm(UE2UE);
|
||||
|
||||
free(s_re[0]);
|
||||
free(s_im[0]);
|
||||
free(r_re[0]);
|
||||
free(r_im[0]);
|
||||
free(s_re);
|
||||
free(s_im);
|
||||
free(r_re);
|
||||
free(r_im);
|
||||
|
||||
term_nr_ue_signal(UE_TX, 1);
|
||||
term_nr_ue_signal(UE_RX, 1);
|
||||
|
||||
free(UE_TX);
|
||||
free(UE_RX);
|
||||
logTerm();
|
||||
loader_reset();
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
@@ -593,7 +593,7 @@ int main(int argc, char **argv)
|
||||
rel15_ul->qam_mod_order,
|
||||
rel15_ul->nrOfLayers);
|
||||
|
||||
int nbDecode = nr_ulsch_decoding(gNB, UE_id, channel_output_fixed, frame_parms, rel15_ul, frame, subframe, harq_pid, G);
|
||||
int nbDecode = nr_ulsch_decoding(gNB, NULL, UE_id, channel_output_fixed, frame_parms, rel15_ul, frame, subframe, harq_pid, G, NULL, NULL, NULL, -1);
|
||||
int nb_ok = 0;
|
||||
if (nbDecode > 0)
|
||||
while (nbDecode > 0) {
|
||||
|
||||
@@ -726,7 +726,7 @@ int main(int argc, char **argv)
|
||||
NR_UE_RRC_INST_t rrcue = {0};
|
||||
rrcue.mib = mib->message.choice.mib;
|
||||
rrcue.scell_group_config = secondaryCellGroup;
|
||||
nr_l2_init_ue(&rrcue);
|
||||
nr_l2_init_ue(&rrcue, NULL);
|
||||
|
||||
NR_UE_MAC_INST_t* UE_mac = get_mac_inst(0);
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <cblas.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <cblas.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -527,15 +526,13 @@ double get_normalization_ch_factor(channel_desc_t *desc)
|
||||
bzero(acorr, desc->nb_tx * desc->nb_rx * sizeof(struct complexd));
|
||||
for (int aatx = 0; aatx < desc->nb_tx; aatx++) {
|
||||
for (int aarx = 0; aarx < desc->nb_rx; aarx++) {
|
||||
cblas_zaxpy(desc->nb_tx * desc->nb_rx,
|
||||
(void *)&anew[aarx + (aatx * desc->nb_rx)],
|
||||
(void *)desc->R_sqrt[aarx + (aatx * desc->nb_rx)],
|
||||
1,
|
||||
(void *)acorr,
|
||||
1);
|
||||
for (int inside = 0; inside < desc->nb_tx * desc->nb_rx; inside++) {
|
||||
const cd_t tmp = cdMul(anew[aarx + aatx * desc->nb_rx], desc->R_sqrt[aarx + aatx * desc->nb_rx][inside]);
|
||||
csum(acorr[inside], tmp, acorr[inside]);
|
||||
}
|
||||
} // for (int aarx = 0; aarx < desc->nb_rx; aarx++)
|
||||
} // for (int aatx = 0; aatx < desc->nb_tx; aatx++)
|
||||
cblas_zcopy(desc->nb_tx * desc->nb_rx, (void *)acorr, 1, (void *)a[l], 1);
|
||||
memcpy(a[l], acorr, desc->nb_tx * desc->nb_rx * sizeof(*acorr));
|
||||
} // for (int l = 0; l < (int)desc->nb_taps; l++)
|
||||
|
||||
for (int aarx = 0; aarx < desc->nb_rx; aarx++) {
|
||||
@@ -1759,7 +1756,7 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
|
||||
acorr[aarx+(aatx*desc->nb_rx)].i = desc->ch[aarx+(aatx*desc->nb_rx)][0].i;
|
||||
}
|
||||
}
|
||||
cblas_zcopy(desc->nb_tx*desc->nb_rx, (void *) acorr, 1, (void *) desc->a[0], 1);
|
||||
memcpy(desc->a[0], acorr, desc->nb_tx * desc->nb_rx * sizeof(*acorr));
|
||||
stop_meas(&desc->random_channel);
|
||||
desc->first_run = 0;
|
||||
return 0;
|
||||
@@ -1810,16 +1807,17 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
|
||||
if (desc->modelid >= TDL_A && desc->modelid <= TDL_E) {
|
||||
for (aatx = 0; aatx < desc->nb_tx; aatx++) {
|
||||
for (aarx=0; aarx<desc->nb_rx; aarx++) {
|
||||
cblas_zaxpy(desc->nb_tx*desc->nb_rx,
|
||||
(void *) &anew[aarx+(aatx*desc->nb_rx)],
|
||||
(void *) desc->R_sqrt[aarx+(aatx*desc->nb_rx)],
|
||||
1,
|
||||
(void *) acorr,
|
||||
1);
|
||||
for (int inside = 0; inside < desc->nb_tx * desc->nb_rx; inside++) {
|
||||
const cd_t tmp = cdMul(anew[aarx + aatx * desc->nb_rx], desc->R_sqrt[aarx + aatx * desc->nb_rx][inside]);
|
||||
csum(acorr[inside], tmp, acorr[inside]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cblas_zaxpy(desc->nb_tx*desc->nb_rx, (void *) desc->R_sqrt[i/3], (void *) anew, 1, (void *) acorr, 1);
|
||||
for (int inside = 0; inside < desc->nb_tx * desc->nb_rx; inside++) {
|
||||
const cd_t tmp = cdMul(desc->R_sqrt[i / 3][0], anew[inside]);
|
||||
csum(acorr[inside], tmp, acorr[inside]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1844,7 +1842,7 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
|
||||
*/
|
||||
|
||||
if (desc->first_run==1) {
|
||||
cblas_zcopy(desc->nb_tx*desc->nb_rx, (void *) acorr, 1, (void *) desc->a[i], 1);
|
||||
memcpy(desc->a[i], acorr, desc->nb_tx * desc->nb_rx * sizeof(*acorr));
|
||||
} else {
|
||||
// a = alpha*acorr+beta*a
|
||||
// a = beta*a
|
||||
@@ -1853,8 +1851,11 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
|
||||
alpha.i = 0;
|
||||
beta.r = sqrt(desc->forgetting_factor);
|
||||
beta.i = 0;
|
||||
cblas_zscal(desc->nb_tx*desc->nb_rx, (void *) &beta, (void *) desc->a[i], 1);
|
||||
cblas_zaxpy(desc->nb_tx*desc->nb_rx, (void *) &alpha, (void *) acorr, 1, (void *) desc->a[i], 1);
|
||||
for (int inside = 0; inside < desc->nb_tx * desc->nb_rx; inside++) {
|
||||
desc->a[i][inside] = cdMul(beta, desc->a[i][inside]);
|
||||
const cd_t tmp = cdMul(alpha, acorr[inside]);
|
||||
csum(desc->a[i][inside], tmp, desc->a[i][inside]);
|
||||
}
|
||||
// desc->a[i][aarx+(aatx*desc->nb_rx)].x = (sqrt(desc->forgetting_factor)*desc->a[i][aarx+(aatx*desc->nb_rx)].x) + sqrt(1-desc->forgetting_factor)*anew.x;
|
||||
// desc->a[i][aarx+(aatx*desc->nb_rx)].y = (sqrt(desc->forgetting_factor)*desc->a[i][aarx+(aatx*desc->nb_rx)].y) + sqrt(1-desc->forgetting_factor)*anew.y;
|
||||
}
|
||||
|
||||
@@ -153,7 +153,12 @@ typedef enum ip_traffic_type_e {
|
||||
TRAFFIC_IPV4_TYPE_BROADCAST = 7,
|
||||
TRAFFIC_IPV4_TYPE_UNKNOWN = 8,
|
||||
TRAFFIC_PC5S_SIGNALLING = 9,
|
||||
TRAFFIC_PC5S_SESSION_INIT = 10
|
||||
TRAFFIC_PC5S_SESSION_INIT = 10,
|
||||
// MC ADDED: New types for non-IP packets, for each type cast
|
||||
TRAFFIC_NONIP_TYPE_UNKOWN = 11,
|
||||
TRAFFIC_NONIP_TYPE_UNICAST = 12,
|
||||
TRAFFIC_NONIP_TYPE_MULTICAST = 13,
|
||||
TRAFFIC_NONIP_TYPE_BROADCAST = 14
|
||||
} ip_traffic_type_t;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user