mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-16 06:00:28 +00:00
Compare commits
354 Commits
develop
...
sl-release
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53a8ac81d1 | ||
|
|
9c13a74ca0 | ||
|
|
347834aed2 | ||
|
|
c899cec386 | ||
|
|
c60d01a3ad | ||
|
|
75e5fa40f4 | ||
|
|
22790038c2 | ||
|
|
b601dda5b1 | ||
|
|
0fc91578fb | ||
|
|
0bd8a36ea8 | ||
|
|
8e48532788 | ||
|
|
8fc6992504 | ||
|
|
542d66ee39 | ||
|
|
865c16af28 | ||
|
|
cecd342090 | ||
|
|
7810cbc47f | ||
|
|
aeb5496c8f | ||
|
|
000ff23bde | ||
|
|
bea3ac37a3 | ||
|
|
573572658a | ||
|
|
d998959156 | ||
|
|
4dc7cd3661 | ||
|
|
8d7429aa3d | ||
|
|
6c05cc14d7 | ||
|
|
e111bba0ff | ||
|
|
edb74908bb | ||
|
|
97877cc578 | ||
|
|
5e02dd0f9c | ||
|
|
bbad01dfa4 | ||
|
|
f1d692c815 | ||
|
|
f02e48727f | ||
|
|
1e138e530d | ||
|
|
d5c101abd8 | ||
|
|
92a9b431e0 | ||
|
|
147c0a6119 | ||
|
|
9e3f196b0e | ||
|
|
776ca250e6 | ||
|
|
f3a5feb4cf | ||
|
|
2603961364 | ||
|
|
cf68063e74 | ||
|
|
0f92269f92 | ||
|
|
c6890eba25 | ||
|
|
99aa174ac1 | ||
|
|
1157476adf | ||
|
|
1eb08bc03e | ||
|
|
cee4c078ea | ||
|
|
d4b935cbda | ||
|
|
156b0f8988 | ||
|
|
cfa3e29797 | ||
|
|
422c9ac863 | ||
|
|
0474f27fcb | ||
|
|
ddee7b38da | ||
|
|
487b6a78d0 | ||
|
|
947445ee13 | ||
|
|
2973f6bf70 | ||
|
|
b1fa771f7b | ||
|
|
8daac951cf | ||
|
|
48f9414692 | ||
|
|
80e7f5c886 | ||
|
|
d084676677 | ||
|
|
166b13eff3 | ||
|
|
9a20be0d0c | ||
|
|
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 | ||
|
|
dd4c1851f3 | ||
|
|
665143e3f6 | ||
|
|
1a904623e1 | ||
|
|
c9e48b8ce9 | ||
|
|
2abf30ad6e | ||
|
|
d37bf06d39 | ||
|
|
eca4d6a572 | ||
|
|
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 | ||
|
|
1ff86924ff | ||
|
|
e13e26759e | ||
|
|
885d5cd426 | ||
|
|
6536425c4b | ||
|
|
c7e08dffbe | ||
|
|
6fcda3dcc0 | ||
|
|
3e81184deb | ||
|
|
4c4a667fd6 | ||
|
|
da6f3251f3 | ||
|
|
9d8db83ebd | ||
|
|
9ceb3ddf93 | ||
|
|
289991b0fe | ||
|
|
38a43f3be6 | ||
|
|
6fc72eae0f | ||
|
|
14420f24cb | ||
|
|
53aa746075 | ||
|
|
4e10e4fa2c | ||
|
|
63454cebf8 | ||
|
|
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
|
||||
@@ -1003,6 +1004,7 @@ set(PHY_SRC_UE
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_scrambling.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/scrambling_luts.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_pscch_pssch_rx.c
|
||||
)
|
||||
|
||||
set(PHY_NR_SRC
|
||||
@@ -1028,6 +1030,7 @@ set(PHY_SRC_UE
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/ul_ref_seq_nr.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_dmrs_rx.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold_ue.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gen_mod_table.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/dmrs_nr.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/ptrs_nr.c
|
||||
@@ -1060,8 +1063,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 +1096,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 +1138,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)
|
||||
@@ -1215,7 +1233,15 @@ set(NR_SDAP_SRC
|
||||
${OPENAIR2_DIR}/SDAP/nr_sdap/nr_sdap.c
|
||||
${OPENAIR2_DIR}/SDAP/nr_sdap/nr_sdap_entity.c
|
||||
)
|
||||
|
||||
|
||||
set(NR_SRAP_SRC
|
||||
${OPENAIR2_DIR}/LAYER2/nr_srap/nr_srap_header.c
|
||||
${OPENAIR2_DIR}/LAYER2/nr_srap/nr_srap_sdu.c
|
||||
${OPENAIR2_DIR}/LAYER2/nr_srap/nr_srap_entity.c
|
||||
${OPENAIR2_DIR}/LAYER2/nr_srap/nr_srap_oai_api.c
|
||||
${OPENAIR2_DIR}/LAYER2/nr_srap/nr_srap_manager.c
|
||||
)
|
||||
|
||||
set(L2_SRC
|
||||
${PDCP_DIR}/pdcp.c
|
||||
${PDCP_DIR}/pdcp_fifo.c
|
||||
@@ -1259,6 +1285,7 @@ set(L2_NR_SRC
|
||||
${NR_RLC_SRC}
|
||||
${NR_PDCP_SRC}
|
||||
${NR_SDAP_SRC}
|
||||
${NR_SRAP_SRC}
|
||||
${NR_RRC_DIR}/rrc_gNB.c
|
||||
${NR_RRC_DIR}/nr_rrc_common.c
|
||||
${NR_RRC_DIR}/L2_nr_interface.c
|
||||
@@ -1297,6 +1324,7 @@ set(NR_L2_SRC_UE
|
||||
${NR_RLC_SRC}
|
||||
${NR_PDCP_SRC}
|
||||
${NR_SDAP_SRC}
|
||||
${NR_SRAP_SRC}
|
||||
${NR_UE_RRC_DIR}/L2_interface_ue.c
|
||||
${NR_UE_RRC_DIR}/main_ue.c
|
||||
${NR_RRC_DIR}/nr_rrc_config.c
|
||||
@@ -1352,7 +1380,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 +1394,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 +1908,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)
|
||||
@@ -2092,6 +2122,7 @@ add_executable(nr-cuup
|
||||
${OPENAIR2_DIR}/E1AP/e1ap_setup.c
|
||||
${NR_PDCP_SRC}
|
||||
${NR_SDAP_SRC}
|
||||
${NR_SRAP_SRC}
|
||||
)
|
||||
|
||||
target_link_libraries(nr-cuup PRIVATE
|
||||
@@ -2225,6 +2256,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
|
||||
|
||||
176
ci-scripts/chat_client.py
Normal file
176
ci-scripts/chat_client.py
Normal file
@@ -0,0 +1,176 @@
|
||||
#
|
||||
# For the usage of this script, refer to ../doc/episys/README_RUN_CHAT.md
|
||||
#
|
||||
|
||||
import os
|
||||
import socket
|
||||
import threading
|
||||
import tkinter as tk
|
||||
from tkinter import scrolledtext, simpledialog, filedialog, messagebox
|
||||
|
||||
class ChatClient:
|
||||
"""Client Object to provide Communication with the other ChatClient(s) via ChatServer."""
|
||||
def __init__(self, host='127.0.0.1', port=5555):
|
||||
self.host = simpledialog.askstring(title="Client", prompt="Enter Server IP address:", initialvalue=host)
|
||||
self.port = port
|
||||
self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
|
||||
self.root = tk.Tk()
|
||||
self.root.title("Chat Client")
|
||||
|
||||
self.root.bind("<Control-c>", lambda event: self.disconnect_from_server())
|
||||
|
||||
self.chat_area = scrolledtext.ScrolledText(self.root, wrap=tk.WORD, state=tk.DISABLED)
|
||||
self.chat_area.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)
|
||||
|
||||
input_frame = tk.Frame(self.root)
|
||||
input_frame.pack(padx=10, pady=5, fill=tk.X)
|
||||
|
||||
self.input_area = tk.Entry(input_frame)
|
||||
self.input_area.pack(side=tk.LEFT, fill=tk.X, expand=True)
|
||||
self.input_area.bind("<Return>", self.send_message)
|
||||
|
||||
self.send_button = tk.Button(input_frame, text="Send", command=self.send_message)
|
||||
self.send_button.pack(side=tk.LEFT)
|
||||
|
||||
self.file_button = tk.Button(input_frame, text="File", command=self.send_file)
|
||||
self.file_button.pack(side=tk.LEFT)
|
||||
|
||||
self.connect()
|
||||
self.root.mainloop()
|
||||
|
||||
def connect(self):
|
||||
"""Connecting to server."""
|
||||
try:
|
||||
self.client_socket.connect((self.host, self.port))
|
||||
self.username = simpledialog.askstring("Username", "Enter your username:")
|
||||
if not self.username:
|
||||
self.root.destroy()
|
||||
return
|
||||
threading.Thread(target=self.receive_messages, daemon=True).start()
|
||||
except Exception as e:
|
||||
self.chat_area.config(state=tk.NORMAL)
|
||||
self.chat_area.insert(tk.END, f"Failed to connect: {e}\n")
|
||||
self.chat_area.config(state=tk.DISABLED)
|
||||
|
||||
def receive_messages(self):
|
||||
"""Handles header first. Based on the header field value, it process recv."""
|
||||
while True:
|
||||
try:
|
||||
# First, receive the message header (type and size)
|
||||
header = b''
|
||||
while True: # Loop to receive the complete header
|
||||
chunk = self.client_socket.recv(1)
|
||||
if not chunk:
|
||||
raise ConnectionResetError("Client disconnected.")
|
||||
header += chunk
|
||||
if header.endswith(b'\n'): # Check for the header delimiter
|
||||
break
|
||||
header = header.decode('utf-8')[:-1] # Remove the trailing '\n'
|
||||
msg_type, msg_size = header.split('|', maxsplit=1)
|
||||
|
||||
if msg_type == "text":
|
||||
msg_size = int(msg_size)
|
||||
message = self.client_socket.recv(msg_size).decode('utf-8')
|
||||
self.display_message(message)
|
||||
elif msg_type == "file":
|
||||
filename, file_size = msg_size.split('|')
|
||||
file_size = int(file_size)
|
||||
# Ask the user if they want to receive the file
|
||||
if messagebox.askyesno(
|
||||
f"Incoming File: {filename}",
|
||||
"Do you want to receive this file?"):
|
||||
self.receive_file(file_size, filename)
|
||||
else:
|
||||
# Ignore the file
|
||||
self.client_socket.recv(file_size)
|
||||
self.display_message("Incoming file ignored.")
|
||||
except Exception as e:
|
||||
self.chat_area.config(state=tk.NORMAL)
|
||||
self.chat_area.insert(tk.END, f"Disconnected from server: {e}\n")
|
||||
self.chat_area.config(state=tk.DISABLED)
|
||||
break
|
||||
|
||||
def send_message(self, event=None):
|
||||
"""Sending message with header."""
|
||||
message = self.input_area.get()
|
||||
if message:
|
||||
try:
|
||||
# Send text message header (type and size)
|
||||
user_msg = f"{self.username}: {message}"
|
||||
disp_msg = f"You: {message}"
|
||||
header = f"text|{len(user_msg)}\n".encode('utf-8')
|
||||
self.client_socket.sendall(header)
|
||||
self.display_message(disp_msg, 'user')
|
||||
self.client_socket.sendall(user_msg.encode('utf-8'))
|
||||
self.input_area.delete(0, tk.END)
|
||||
except Exception as e:
|
||||
self.chat_area.config(state=tk.NORMAL)
|
||||
self.chat_area.insert(tk.END, f"Error sending message: {e}\n")
|
||||
self.chat_area.config(state=tk.DISABLED)
|
||||
|
||||
def send_file(self):
|
||||
"""Sending file with header."""
|
||||
file_path = filedialog.askopenfilename()
|
||||
if file_path:
|
||||
try:
|
||||
# Send file header (type, filename, and file size)
|
||||
file_size = os.path.getsize(file_path)
|
||||
filename = os.path.basename(file_path) # Extract filename
|
||||
header = f"file|{filename}|{file_size}\n".encode('utf-8')
|
||||
self.client_socket.sendall(header)
|
||||
|
||||
# Send the file data
|
||||
with open(file_path, 'rb') as f:
|
||||
while True:
|
||||
bytes_read = f.read(4096)
|
||||
if not bytes_read:
|
||||
break
|
||||
self.client_socket.sendall(bytes_read)
|
||||
self.display_message(f"File '{os.path.basename(file_path)}' sent successfully.")
|
||||
except Exception as e:
|
||||
self.display_message(f"Error sending file: {e}")
|
||||
|
||||
def receive_file(self, file_size, filename):
|
||||
"""Receiving file. It requires file name to save."""
|
||||
try:
|
||||
save_path = filedialog.asksaveasfilename(initialfile=filename)
|
||||
if not save_path:
|
||||
return
|
||||
|
||||
with open(save_path, 'wb') as f:
|
||||
bytes_received = 0
|
||||
while bytes_received < file_size:
|
||||
bytes_read = self.client_socket.recv(4096)
|
||||
if not bytes_read:
|
||||
break
|
||||
f.write(bytes_read)
|
||||
bytes_received += len(bytes_read)
|
||||
self.display_message(f"File saved to '{os.path.basename(save_path)}'.")
|
||||
except Exception as e:
|
||||
self.display_message(f"Error receiving file: {e}")
|
||||
|
||||
def display_message(self, message, tag=''):
|
||||
"""Display message in chat_area."""
|
||||
self.chat_area.config(state=tk.NORMAL)
|
||||
self.chat_area.insert(tk.END, message + "\n", tag)
|
||||
self.chat_area.config(state=tk.DISABLED)
|
||||
self.chat_area.see(tk.END)
|
||||
|
||||
def disconnect_from_server(self):
|
||||
"""Handles the Ctrl+C event to gracefully exit the application."""
|
||||
try:
|
||||
self.display_message("Disconnecting from server...")
|
||||
# Close the client socket
|
||||
if self.client_socket:
|
||||
self.client_socket.shutdown(socket.SHUT_RDWR)
|
||||
self.client_socket.close()
|
||||
self.client_socket = None
|
||||
self.display_message("Disconnected from server.")
|
||||
self.root.destroy() # Close the GUI window
|
||||
except Exception as e:
|
||||
self.display_message(f"Error disconnecting from server: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
client = ChatClient()
|
||||
154
ci-scripts/chat_server.py
Normal file
154
ci-scripts/chat_server.py
Normal file
@@ -0,0 +1,154 @@
|
||||
#
|
||||
# For the usage of this script, refer to ../doc/episys/README_RUN_CHAT.md
|
||||
#
|
||||
|
||||
import time
|
||||
import socket
|
||||
import threading
|
||||
import tkinter as tk
|
||||
from tkinter import scrolledtext, simpledialog
|
||||
|
||||
class ChatServer:
|
||||
"""Server object to provide multicast service between ChatClient(s)."""
|
||||
def __init__(self, host='127.0.0.1', port=5555):
|
||||
self.host = simpledialog.askstring(title="Server", prompt="Enter Server IP address:", initialvalue=host)
|
||||
self.port = port
|
||||
self.clients = {} # Use a dictionary to store client sockets and usernames
|
||||
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.server_socket.bind((self.host, self.port))
|
||||
self.server_socket.listen()
|
||||
|
||||
self.root = tk.Tk()
|
||||
self.root.title("Chat Server")
|
||||
|
||||
self.shutdown_event = threading.Event()
|
||||
self.root.bind("<Control-c>", lambda event: self.stop_server())
|
||||
|
||||
self.log_text = scrolledtext.ScrolledText(self.root, wrap=tk.WORD, state=tk.DISABLED)
|
||||
self.log_text.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)
|
||||
|
||||
threading.Thread(target=self.accept_connections).start()
|
||||
self.root.mainloop()
|
||||
|
||||
def log(self, message):
|
||||
"""Display (log) message in log_text."""
|
||||
self.log_text.config(state=tk.NORMAL)
|
||||
self.log_text.insert(tk.END, message + "\n")
|
||||
self.log_text.config(state=tk.DISABLED)
|
||||
self.log_text.see(tk.END)
|
||||
|
||||
def accept_connections(self):
|
||||
"""Accepting connection from client(s)."""
|
||||
self.log(f"Server listening on {self.host}:{self.port}")
|
||||
th_list = []
|
||||
while True:
|
||||
try:
|
||||
self.server_socket.settimeout(5)
|
||||
client_socket, client_address = self.server_socket.accept()
|
||||
self.log(f"Accepted connection from {client_address}")
|
||||
self.clients[client_socket] = client_address # Store client address with socket
|
||||
th = threading.Thread(target=self.handle_client, args=(client_socket,), daemon=True)
|
||||
th.start()
|
||||
th_list.append(th)
|
||||
except Exception as e:
|
||||
if self.shutdown_event.is_set():
|
||||
break
|
||||
time.sleep(2)
|
||||
for th in th_list:
|
||||
th.join()
|
||||
|
||||
def handle_client(self, client_socket):
|
||||
"""Main handler function to forward message or file to other clients(s). Based on header field value, it handles each type."""
|
||||
while not self.shutdown_event.is_set():
|
||||
try:
|
||||
# First, receive the message header (type and size)
|
||||
header = b''
|
||||
while True: # Loop to receive the complete header
|
||||
chunk = client_socket.recv(1)
|
||||
if not chunk:
|
||||
raise Exception("Client disconnected.")
|
||||
header += chunk
|
||||
if header.endswith(b'\n'): # Check for the header delimiter
|
||||
break
|
||||
header = header.decode('utf-8')[:-1] # Remove the trailing '\n'
|
||||
msg_type, msg_size = header.split('|', maxsplit=1)
|
||||
|
||||
if msg_type == "text":
|
||||
msg_size = int(msg_size)
|
||||
message = client_socket.recv(msg_size).decode('utf-8')
|
||||
self.broadcast(f"{message}", client_socket)
|
||||
elif msg_type == "file":
|
||||
filename, file_size = msg_size.split('|')
|
||||
file_size = int(file_size)
|
||||
# Receive the file data from the client
|
||||
|
||||
file_data = b''
|
||||
bytes_received = 0
|
||||
while bytes_received < file_size:
|
||||
chunk = client_socket.recv(4096)
|
||||
if not chunk:
|
||||
break
|
||||
file_data += chunk
|
||||
bytes_received += len(chunk)
|
||||
# Broadcast the file to other clients
|
||||
self.broadcast_file(file_data, filename, file_size, client_socket)
|
||||
|
||||
except Exception as e:
|
||||
self.log(f"Error handling client: {e}")
|
||||
username = self.clients.pop(client_socket)
|
||||
peername = client_socket.getpeername()
|
||||
client_socket.close()
|
||||
self.broadcast(f"{username} has left the chat!")
|
||||
self.log(f"Connection closed from {peername}")
|
||||
if len(self.clients) == 0:
|
||||
break
|
||||
|
||||
def broadcast(self, message, sender_socket=None):
|
||||
"""Broadcasting message."""
|
||||
for client in self.clients:
|
||||
if client != sender_socket:
|
||||
try:
|
||||
# Send text message header (type and size)
|
||||
header = f"text|{len(message)}\n".encode('utf-8')
|
||||
client.sendall(header) # Use sendall() to ensure complete header is sent
|
||||
client.sendall(message.encode('utf-8'))
|
||||
except Exception as e:
|
||||
self.log(f"Error broadcasting message: {e}")
|
||||
|
||||
|
||||
def broadcast_file(self, file_data, filename, file_size, sender_socket):
|
||||
"""Broadcasting file."""
|
||||
sender_address = self.clients[sender_socket]
|
||||
for client in self.clients:
|
||||
if client != sender_socket:
|
||||
try:
|
||||
# Send file header (type, filename, and file size)
|
||||
header = f"file|{filename}|{file_size}\n".encode('utf-8')
|
||||
client.sendall(header)
|
||||
client.sendall(file_data)
|
||||
self.log(f"File from {sender_address} sent to {self.clients[client]}")
|
||||
except Exception as e:
|
||||
self.log(f"Error broadcasting file: {e}")
|
||||
|
||||
def stop_server(self):
|
||||
"""Stops the server gracefully."""
|
||||
try:
|
||||
self.shutdown_event.set()
|
||||
self.log("Stopping server...")
|
||||
# Close all client sockets
|
||||
for client in list(self.clients.keys()):
|
||||
client.shutdown(socket.SHUT_RDWR)
|
||||
client.close()
|
||||
self.clients.clear()
|
||||
# Close the server socket
|
||||
if self.server_socket:
|
||||
self.server_socket.close()
|
||||
self.server_socket = None
|
||||
self.log("Server stopped.")
|
||||
self.root.destroy() # Close the GUI window
|
||||
except Exception as e:
|
||||
self.log(f"Error stopping server: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
server = ChatServer()
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ get_distribution_release() {
|
||||
check_supported_distribution() {
|
||||
local distribution=$(get_distribution_release)
|
||||
case "$distribution" in
|
||||
"ubuntu24.04") return 0 ;;
|
||||
"ubuntu23.10") return 0 ;;
|
||||
"ubuntu22.04") return 0 ;;
|
||||
"ubuntu21.04") return 0 ;;
|
||||
@@ -549,7 +550,7 @@ check_install_additional_tools (){
|
||||
"ubuntu18.04")
|
||||
optional_packages="python-dev python-pip python-pyroute2 python python-numpy python-scipy python-matplotlib ctags"
|
||||
;;
|
||||
"ubuntu20.04" | "ubuntu21.04" | "ubuntu22.04" | "debian11" )
|
||||
"ubuntu20.04" | "ubuntu21.04" | "ubuntu22.04" | "ubuntu23.10" | "ubuntu24.04" | "debian11" )
|
||||
optional_packages="python3 python3-pip python3-dev python3-scipy python3-matplotlib python3-pyroute2 universal-ctags"
|
||||
;;
|
||||
esac
|
||||
@@ -593,10 +594,20 @@ check_install_oai_software() {
|
||||
add_cmake_repo
|
||||
specific_packages=""
|
||||
;;
|
||||
"ubuntu24.04")
|
||||
specific_packages=""
|
||||
;;
|
||||
"debian11")
|
||||
specific_packages="libz-dev"
|
||||
;;
|
||||
esac
|
||||
|
||||
# For Ubuntu 24.04, skip libatlas-base-dev due to version conflict with liblapacke
|
||||
if [[ "$(get_distribution_release)" == "ubuntu24.04" ]]; then
|
||||
BLAS_PACKAGES="libblas-dev liblapack-dev liblapacke-dev"
|
||||
else
|
||||
BLAS_PACKAGES="libatlas-base-dev libblas-dev liblapack-dev liblapacke-dev"
|
||||
fi
|
||||
$SUDO apt-get install -y \
|
||||
$specific_packages \
|
||||
automake \
|
||||
@@ -605,10 +616,7 @@ check_install_oai_software() {
|
||||
ninja-build \
|
||||
pkg-config \
|
||||
git \
|
||||
libatlas-base-dev \
|
||||
libblas-dev \
|
||||
liblapack-dev \
|
||||
liblapacke-dev \
|
||||
$BLAS_PACKAGES \
|
||||
libreadline-dev \
|
||||
libconfig-dev \
|
||||
libsctp-dev \
|
||||
@@ -670,7 +678,7 @@ install_asn1c_from_source(){
|
||||
# GIT_SSL_NO_VERIFY=true git clone https://gitlab.eurecom.fr/oai/asn1c.git /tmp/asn1c
|
||||
git clone https://github.com/mouse07410/asn1c /tmp/asn1c
|
||||
cd /tmp/asn1c
|
||||
git checkout vlm_master
|
||||
git checkout 998e7ea2
|
||||
autoreconf -iv
|
||||
./configure --prefix /opt/asn1c/
|
||||
make -j`nproc`
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
#include "common/config/config_paramdesc.h"
|
||||
#include "common/utils/T/T.h"
|
||||
#define CONFIG_MAX_OOPT_PARAMS 10 // maximum number of parameters in the -O option (-O <cfgmode>:P1:P2...
|
||||
#define CONFIG_MAX_ALLOCATEDPTRS 2048 // maximum number of parameters that can be dynamicaly allocated in the config module
|
||||
#define CONFIG_MAX_ALLOCATEDPTRS 2560 // maximum number of parameters that can be dynamicaly allocated in the config module
|
||||
|
||||
/* default values for configuration module parameters */
|
||||
#define CONFIG_LIBCONFIGFILE "libconfig" // use libconfig file
|
||||
|
||||
@@ -492,6 +492,7 @@ int logInit (void)
|
||||
register_log_component("NFAPI_PNF","log",NFAPI_PNF);
|
||||
register_log_component("GNB_APP","log",GNB_APP);
|
||||
register_log_component("NR_RRC","log",NR_RRC);
|
||||
register_log_component("NR_SRAP","log",NR_SRAP);
|
||||
register_log_component("NR_MAC","log",NR_MAC);
|
||||
register_log_component("NR_PHY","log",NR_PHY);
|
||||
register_log_component("NGAP","",NGAP);
|
||||
|
||||
@@ -245,6 +245,7 @@ typedef enum {
|
||||
NFAPI_PNF,
|
||||
ITTI,
|
||||
UTIL,
|
||||
NR_SRAP,
|
||||
MAX_LOG_PREDEF_COMPONENTS,
|
||||
}
|
||||
comp_name_t;
|
||||
|
||||
@@ -550,6 +550,27 @@ ID = LEGACY_NR_RRC_TRACE
|
||||
GROUP = ALL:LEGACY_NR_RRC:LEGACY_GROUP_TRACE:LEGACY
|
||||
FORMAT = string,log
|
||||
|
||||
ID = LEGACY_NR_SRAP_INFO
|
||||
DESC = NR_SRAP legacy logs - info level
|
||||
GROUP = ALL:LEGACY_NR_SRAP:LEGACY_GROUP_INFO:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_NR_SRAP_ERROR
|
||||
DESC = NR_SRAP legacy logs - error level
|
||||
GROUP = ALL:LEGACY_NR_SRAP:LEGACY_GROUP_ERROR:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_NR_SRAP_WARNING
|
||||
DESC = NR_SRAP legacy logs - warning level
|
||||
GROUP = ALL:LEGACY_NR_SRAP:LEGACY_GROUP_WARNING:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_NR_SRAP_DEBUG
|
||||
DESC = NR_SRAP legacy logs - debug level
|
||||
GROUP = ALL:LEGACY_NR_SRAP:LEGACY_GROUP_DEBUG:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_NR_SRAP_TRACE
|
||||
DESC = NR_SRAP legacy logs - trace level
|
||||
GROUP = ALL:LEGACY_NR_SRAP:LEGACY_GROUP_TRACE:LEGACY
|
||||
FORMAT = string,log
|
||||
|
||||
ID = LEGACY_RLC_INFO
|
||||
DESC = RLC legacy logs - info level
|
||||
GROUP = ALL:LEGACY_RLC:LEGACY_GROUP_INFO:LEGACY
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#define NR_MAX_HARQ_PROCESSES 16
|
||||
#define NR_NB_REG_PER_CCE 6
|
||||
#define NR_NB_SC_PER_RB 12
|
||||
#define MAX_SL_UE_CONNECTIONS 8
|
||||
|
||||
typedef enum {
|
||||
nr_FR1 = 0,
|
||||
@@ -72,6 +73,11 @@ typedef enum frequency_range_e {
|
||||
FR2
|
||||
} frequency_range_t;
|
||||
|
||||
typedef enum {
|
||||
UU,
|
||||
PC5,
|
||||
} nr_intf_type_t;
|
||||
|
||||
extern const nr_bandentry_t nr_bandtable[];
|
||||
|
||||
static inline int get_num_dmrs(uint16_t dmrs_mask ) {
|
||||
@@ -90,6 +96,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 +120,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())
|
||||
|
||||
BIN
doc/episys/EpiSci_logo.png
Normal file
BIN
doc/episys/EpiSci_logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
81
doc/episys/README_RUN_CHAT.md
Normal file
81
doc/episys/README_RUN_CHAT.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# Chat Application
|
||||
This application is composed of two scripts, chat_server.py and chat_client.py.
|
||||
chat_server.py provides server role, and chat_client.py provides client role.
|
||||
Currently, as of 03/13/2025, this application has only been tested and ran with OAI but can be utilized for plain TCP/IP communications as well.
|
||||
|
||||
## Prerequisites
|
||||
- Tkinter is a default package in the standard Python interface to the Tcl/Tk GUI toolkit:
|
||||
`pip install tk`
|
||||
|
||||
## Usage ##
|
||||
### Run Chat Client with OAI ###
|
||||
#### Get openairinterface5g source code ####
|
||||
```bash
|
||||
git clone https://gitlab.applied.dev/old_episci/csrf/5g/openairinterface5g ~/openairinterface5g
|
||||
cd ~/openairinterface5g
|
||||
git checkout episys/sl-eurecom2
|
||||
```
|
||||
|
||||
#### Install OAI dependencies ####
|
||||
```bash
|
||||
cd ~/openairinterface5g/cmake_targets
|
||||
./build_oai -I
|
||||
```
|
||||
|
||||
#### Build OAI gNB and OAI nrUE ####
|
||||
```bash
|
||||
cd ~/openairinterface5g/cmake_targets
|
||||
./build_oai -w SIMU --nrUE --gNB -w USRP
|
||||
```
|
||||
|
||||
#### Run OAI nrUEs ####
|
||||
After connecting the USRPs to the two host machines, open a new terminal on each machine. Note, you can validate the USRPs are properly connected with the `uhd_find_devices` and `uhd_usrp_probe` commands. Run the following commands in each terminal:
|
||||
|
||||
SyncRef UE terminal (terminal 1):
|
||||
```bash
|
||||
cd ~/openairinterface5g/cmake_targets/ran_build/build
|
||||
sudo -E LD_LIBRARY_PATH=$PWD:$LD_LIBRARY_PATH \
|
||||
./nr-uesoftmodem -O ~/openairinterface5g/targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf \
|
||||
--sa --sl-mode 2 --sync-ref --ue-txgain 10 --ue-rxgain 100 --mcs 9
|
||||
```
|
||||
|
||||
Nearby UE terminal (terminal 1):
|
||||
```bash
|
||||
cd ~/openairinterface5g/cmake_targets/ran_build/build
|
||||
sudo -E LD_LIBRARY_PATH=$PWD:$LD_LIBRARY_PATH \
|
||||
./nr-uesoftmodem -O ~/openairinterface5g/targets/PROJECTS/NR-SIDELINK/CONF/sl_ue1.conf \
|
||||
--sa --sl-mode 2 --ue-txgain 10 --ue-rxgain 100 --mcs 9
|
||||
```
|
||||
|
||||
### Check tun/tap Interface ###
|
||||
After launching the OAI commands, find tun/tap IP address of interface named `oaitun_ue1` using the `ifconfig` command on the SyncRef machine. Note, for validation you should see the `oaitun_ue1` IP address appropriately set as `10.0.0.1`. The SyncRef UE is the server.
|
||||
|
||||
### Launch chat script ###
|
||||
Open two new terminals on the SyncRef (terminal 2 and termianl 3) and one new terminal on the Nearby UE (terminal 2).
|
||||
|
||||
#### Launch chat_server.py
|
||||
SyncRef UE terminal (terminal 2):
|
||||
```bash
|
||||
python3 ./chat_server.py
|
||||
```
|
||||
|
||||
#### Launch chat_client.py
|
||||
Run `./chat_client.py` on the SyncRef and Nearby UE:
|
||||
|
||||
SyncRef UE terminal (terminal 3):
|
||||
```bash
|
||||
python3 ./chat_client.py
|
||||
```
|
||||
Nearby UE terminal (terminal 2):
|
||||
```bash
|
||||
python3 ./chat_client.py
|
||||
```
|
||||
|
||||
### Test chatting ###
|
||||
#### Enter Server IP address ####
|
||||
After launching the scripts, you are prompted to enter the server IP address and user ID in the dialog box for each chat client.
|
||||
|
||||
To use OAI tun/tap interface, enter the IP address dialog box found. See the ### Check tun/tap Interface ### step if you are unsure where to get the IP address. Note, in this test, it is `10.0.0.1`.
|
||||
|
||||
#### Chatting ####
|
||||
After the connection is established between the server and clients, you can then begin using the chat services. You can send text messages or files using the client chatting windows.
|
||||
301
doc/episys/README_SL.md
Normal file
301
doc/episys/README_SL.md
Normal file
@@ -0,0 +1,301 @@
|
||||
|
||||
<p align="center">
|
||||
<a href="http://www.openairinterface.org/">
|
||||
<img src="./EpiSci_logo.png" alt="OAI Logo" height="90"/>
|
||||
</a>
|
||||
</p>
|
||||
<h1 align="center">
|
||||
5G Sidelink (SL) Mode 2 Implementation in OpenAirInterface (OAI) Overview
|
||||
</h>
|
||||
|
||||
## 1. Overview of 5G SL Features
|
||||
This implementation adds support for **5G sidelink (SL) Mode 2** features within the **OpenAirInterface (OAI)** codebase, enabling device-to-device (D2D) communication without the need for a network infrastructure. Currently, the following features are implemented:
|
||||
|
||||
####   ✅ **Key Features**
|
||||
   ◉ **SL Synchronization:**<br>     Devices can autonomously synchronize over the PC5 interface, Sidelink, using predefined synchronization resources.<br>
|
||||
   ◉ **SL Configuration:**<br>     Pre-configured SL resource pools are supported to enable flexible networking scenarios.<br>
|
||||
   ◉ **Data Transmission and Reception:**<br>     End-to-end transmission and reception of SL data packets, including SL-SCH and SL-PSCCH channel handling.<br>
|
||||
   ◉ **CSI Reporting:**<br>     Support for basic Channel State Information (CSI) reporting mechanisms for better link adaptation.<br>
|
||||
   ◉ **Basic Scheduling:**<br>     A basic SL MAC scheduler has been implemented to enable time resource allocations in Mode 2.<br>
|
||||
   ◉ **Resource Pool Scheme:**<br>     Static and pre-configured resource pool definitions are supported to enable Mode 2 communication.<br>
|
||||
   ◉ **Data Feedback:**<br>     Provided a data feedback for 5G SL communication to share the reception status with the transmitter.<br>
|
||||
   ◉ **Hybrid Automatic Repeat reQuest:**<br>     Enhances reliability and throughput by combining error detection with retransmission and error correction.<br>
|
||||
   ◉ **UE-to-Network (U2N) Relay**<br>     U2N Relay capabilities are supported to facilitate the communication between Remote UE and gNB via Relay UE.<br>
|
||||
|
||||
## 2. Added Features
|
||||
|
||||
  The following features have been implemented and integrated into the OAI codebase to support 5G SL Mode 2:
|
||||
|
||||
   ◉ Full PHY and MAC channel support <br>
|
||||
    🔹 **PHY:** PSBCH, PSSCH, PSCCH, PSFCH <br>
|
||||
    🔹 **PHY ⇄ MAC:** SL-SCH, SL-BCH<br>
|
||||
    🔹 **MAC ⇄ RLC:** SBCCH, SCCH, STCH<br>
|
||||
  ◉ TX/RX data path support for SL Mode 2<br>
|
||||
    🔹 CSI Reporting (basic support)<br>
|
||||
    🔹 CSI Reference Signals (CSI-RS)<br>
|
||||
    🔹 SINR Estimation<br>
|
||||
  ◉ Basic MAC scheduling for Mode 2 operation<br>
|
||||
  ◉ Resource pool configuration (pre-configured/static)<br>
|
||||
  ◉ Dynamic MCS support (currently up to MCS 9)<br>
|
||||
  ◉ HARQ retransmission handling (basic)<br>
|
||||
  ◉ SL pre-configuration support (static configuration via .conf files)<br>
|
||||
  ◉ SL IP Traffic support (updates to PDCP, RLC, and SDAP layers)<br>
|
||||
  ◉ 5G Sidelink Relay Adaptation Protocol (SRAP) based U2N relay support
|
||||
|
||||
## 3. Missing Features or Features Needing Updates
|
||||
  The following features are either missing or require further updates and debugging:
|
||||
|
||||
  ❌ MCS Dynamic Range Limitation:<br>
|
||||
    Current implementation limits MCS values to a maximum of 9. This may be due to the lack of support for multiple PDUs in a single transmission time interval.<br>
|
||||
  ❌ Multiple PDU Support:<br>
|
||||
    Not yet implemented; needed for higher MCS values and throughput.<br>
|
||||
  ❌ Multiple Subchannel Support:<br>
|
||||
    Currently limited to single subchannel operation; lacks logical channel prioritization.<br>
|
||||
  ❌ Sensing Algorithm:<br>
|
||||
    No support for channel sensing (needed for advanced Mode 2 and resource allocation decisions).<br>
|
||||
  ❌ N310 Hardware Support:<br>
|
||||
    SL communication does not work on N310; only tested successfully on B210.<br>
|
||||
  ❌ HARQ PID Detection:<br>
|
||||
    Lacks dynamic handling of HARQ process IDs.<br>
|
||||
  ❌ Advanced MAC Scheduling:<br>
|
||||
    Only a basic round-robin/time-domain scheduler is in place. No support for advanced algorithms (e.g., sensing-based or QoS-aware).<br>
|
||||
  ❌ Logical Channel Prioritization:<br>
|
||||
    Not currently implemented; needed for multiple logical channel management.<br>
|
||||
  ❌ 5G SL Relay Validation on USRP:<br>
|
||||
     Not currently supported; only validated in RFSim.<br>
|
||||
  ❌ Control Plane for SRAP:<br>
|
||||
     Not currently supported; only user plane of UE-to-Network mode is developed and validated.<br>
|
||||
|
||||
## 4. Test Features
|
||||
  The current implementation has been tested with the following configuration:
|
||||
|
||||
  ✅ Working Setup:<br>
|
||||
     ◉ Two UE devices communicating over sidelink Mode 2 using Ettus B210 SDRs<br>
|
||||
       Basic SL transmission and reception are confirmed functional in this setup<br>
|
||||
     ◉ Three node Relay scenario (remote UE, relay UE and gNB) is working only on RFSIM<br>
|
||||
  ❌ Unsupported or Non-Functional Setup:<br>
|
||||
     ◉ Ettus N310 devices: SL Mode 2 does not currently work. Debugging in work.<br>
|
||||
|
||||
## 5. EpiSci's 5G Sidelink Mode 2
|
||||
### 5.1 **Build OAI:**
|
||||
 Follow these steps to build OpenAirInterface (OAI) with support for 5G Sidelink and related features:
|
||||
```
|
||||
$ git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git
|
||||
$ cd ~/openairinterface5g
|
||||
$ git fetch
|
||||
$ git clean -fdX
|
||||
$ git checkout sl-release-1.0
|
||||
$ source oaienv
|
||||
$ cd cmake_targets
|
||||
$ ./build_oai -C -I --install-optional-packages # Only necessary on fresh installs
|
||||
$ ./build_oai --nrUE --gNB -w USRP -w SIMU
|
||||
```
|
||||
|
||||
#### 5.1.1 **For Active Development and Faster Build Times:**
|
||||
|
||||
 If you are actively developing and want to speed up the build process, you can directly build only the executables:
|
||||
```
|
||||
$ cd ~/openairinterface5g/cmake_targets/ran_build/build
|
||||
$ make nr-uesoftmodem rfsimulator nr_psbchsim nr_psschsim -j128
|
||||
```
|
||||
|
||||
#### 5.1.2 **Ubuntu 24 + Address Sanitizer Workaround:**
|
||||
 If you encounter a DEADLYSIGNAL error from AddressSanitizer (ASan) during OAI compilation on Ubuntu 24, apply the following workaround:
|
||||
```
|
||||
$ sudo sysctl vm.mmap_rnd_bits=28
|
||||
```
|
||||
|
||||
#### 5.1.3 **Ubuntu 24.04 Build Support:**
|
||||
|
||||
 This branch includes Ubuntu 24.04 support with necessary build system modifications. Simply follow the standard build instructions:
|
||||
|
||||
```bash
|
||||
$ cd ~/openairinterface5g/cmake_targets
|
||||
$ ./build_oai -C -I --install-optional-packages # Installs all dependencies
|
||||
$ ./build_oai --nrUE --gNB -w USRP -w SIMU
|
||||
```
|
||||
|
||||
  **Note:** This branch includes a fix for ASN.1 compiler installation. The build system will automatically install **ASN.1 compiler v0.9.29** (commit 998e7ea2) instead of the newer vlm_master branch. This is required because the codebase is currently compatible with v0.9.29 (June 2024), while newer versions (v1.2+, v1.4+) generate incompatible pointer structures instead of structs, which would require approximately 1500 code changes throughout the codebase.
|
||||
|
||||
  **Verification (after running `./build_oai -I`):**
|
||||
```bash
|
||||
$ /opt/asn1c/bin/asn1c -version
|
||||
# Should output: ASN.1 Compiler, v0.9.29
|
||||
```
|
||||
|
||||
### 5.2 **Running on RF Simulator:**
|
||||
|
||||
  RFSim in OAI codebase is a radio frequency (RF) simulation module that enables end-to-end testing without physical RF hardware by simulating the wireless channel and signal propagation. It facilitates testing of 4G/5G network components entirely in software, making it ideal for CI/CD, development, and validation environments.
|
||||
|
||||
#### 5.2.1 **Test Environment: (SL Mode 2)**
|
||||
|
||||
  To test IP traffic using `ping` in 5G SL Mode 2, SyncRef and the Nearby UE should run on separate machines. Currently, IP traffic is not supported when both processes are running on the same machine. Following commands allow testing of 5G SL Mode 2 with two UEs in RF simulator.
|
||||
|
||||
#### 5.2.1.1 **Commands:**
|
||||
|
||||
  ***SyncRef UE on Machine 1:***
|
||||
```
|
||||
$ cd $HOME/openairinterface5g/cmake_targets/ran_build/build
|
||||
$ sudo LD_LIBRARY_PATH=$PWD:$LD_LIBRARY_PATH -E \
|
||||
./nr-uesoftmodem -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf \
|
||||
--sa --sl-mode 2 --sync-ref --rfsim --thread-pool -1,-1,-1,-1 \
|
||||
--rfsimulator.serveraddrsl server --rfsimulator.serverportsl 4048
|
||||
```
|
||||
  ***Nearby UE on Machine 2:***
|
||||
```
|
||||
$ cd $HOME/openairinterface5g/cmake_targets/ran_build/build
|
||||
$ sudo LD_LIBRARY_PATH=$PWD:$LD_LIBRARY_PATH -E \
|
||||
./nr-uesoftmodem -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_ue1.conf \
|
||||
--sa --sl-mode 2 --rfsim --thread-pool -1,-1,-1,-1 \
|
||||
--rfsimulator.serveraddrsl <MACHINE 1 IP Address> --rfsimulator.serverportsl 4048
|
||||
```
|
||||
Run `ping` command on a terminal in Machine 2. Note, oaitun_ue2 is the interface name of the Nearby UE. 10.0.0.1 is the IP address of the SyncRef UE.
|
||||
|
||||
```
|
||||
ping -I oaitun_ue2 10.0.0.1
|
||||
```
|
||||
|
||||
**🔔Note:** Following errors can be seen when PSFCH is enabled (sl_PSFCH_period = 1, 2, 3) in the configurations files; we are working to fix this issue.
|
||||
```
|
||||
[NR_PHY] [UE] SLSCH 0 in error: Setting NAK for SFN/SF 254/19 (pid 5, ndi 0, status 0, round 0, RV 0, prb_start 0, subchannel_size 50, TBS 656) r 0
|
||||
[PDCP] discard NR PDU rcvd_count=9, entity->rx_deliv 10,sdu_in_list 0
|
||||
```
|
||||
|
||||
To perform full system testing (including CSI Reporting and PSFCH feedback), the commands remain unchanged - you only need to update the UE configuration files as outlined below.
|
||||
|
||||
#### 5.2.1.2 **Changing Configurations (CSI Reporting and PSFCH Period):**
|
||||
  To change CSI Reporting and PSFCH configurations for sidelink testing, modify the following configuration files:
|
||||
|
||||
SyncRef UE Configuration File:
|
||||
```
|
||||
$HOME/openairinterface5g/targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf
|
||||
```
|
||||
Nearby UE Configuration File:
|
||||
```
|
||||
$HOME/openairinterface5g/targets/PROJECTS/NR-SIDELINK/CONF/sl_ue1.conf
|
||||
```
|
||||
In each file, update the following variables values provided in given Table 1:
|
||||
|
||||
  ◉ sl_CSI_Acquisition<br>
|
||||
  ◉ sl_TxResPools → sl_PSFCH_period<br>
|
||||
  ◉ sl_RxResPools → sl_PSFCH_period<br>
|
||||
|
||||
<h>Table 1: Configuration Table</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Configuration</th>
|
||||
<th>sl_CSI_Acquisition</th>
|
||||
<th>sl_PSFCH_period (Tx/Rx Pools)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>CSI Disabled 0</td>
|
||||
<td style="text-align: center;">1</td>
|
||||
<td style="text-align: center;">0/0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>CSI Disabled 1</td>
|
||||
<td style="text-align: center;">1</td>
|
||||
<td style="text-align: center;">1/1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>CSI Disabled 2</td>
|
||||
<td style="text-align: center;">1</td>
|
||||
<td style="text-align: center;">2/2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>CSI Disabled 4</td>
|
||||
<td style="text-align: center;">1</td>
|
||||
<td style="text-align: center;">3/3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>CSI Enabled 0</td>
|
||||
<td style="text-align: center;">0</td>
|
||||
<td style="text-align: center;">0/0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>CSI Enabled 1</td>
|
||||
<td style="text-align: center;">0</td>
|
||||
<td style="text-align: center;">1/1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>CSI Enabled 2</td>
|
||||
<td style="text-align: center;">0</td>
|
||||
<td style="text-align: center;">2/2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>CSI Enabled 4</td>
|
||||
<td style="text-align: center;">0</td>
|
||||
<td style="text-align: center;">3/3</td>
|
||||
</tr>
|
||||
<tbody>
|
||||
</table>
|
||||
|
||||
**🔔Note:** Ensure the **sl_CSI_Acquisition** and **sl_PSFCH_period** values are set consistently across both UEs for valid test.
|
||||
|
||||
### 5.3 **5G SL Relay**
|
||||
|
||||
  To enable relay scenario support in our system, we have implemented the Sidelink Relay Adaptation Protocol (SRAP). The SRAP supports two types of relaying modes:<br>
|
||||
   ◉ UE-to-Network (U2N)<br>
|
||||
   ◉ UE-to-UE (U2U)<br>
|
||||
Currently, only the U2N mode is implemented, which enables a Relay UE to forward traffic from a Remote UE to the gNB. The code of SRAP implementation is available under `openair2/LAYER2/nr_srap`, which provides following support:<br>
|
||||
   ◉ structures and functions to define the SRAP entity.<br>
|
||||
   ◉ addition and removal of SRAP headers.<br>
|
||||
   ◉ processing of the received pdu.<br>
|
||||
   ◉ forwarding of the received messages.<br>
|
||||
   ◉ passing of the PDU to lower layers.<br>
|
||||
   ◉ passing of the SDU to upper layers.<br>
|
||||
|
||||
### 5.4 **Over-the-air (OTA) USRP Testing:**
|
||||
The OTA USRP testing was conducted using two B210s. The following commands are OTA USRP commands used for testing Sidelink Mode 2 on B210s. The following UHD commands will verify the USRP is ready for deployment and provide you with the necessary information, such as the serial and addr values.
|
||||
|
||||
```
|
||||
$ uhd_find_devices # This will find all USRPs
|
||||
$ uhd_usrp_probe # This will probe the USRP and will ensure the status is ready
|
||||
```
|
||||
|
||||
The USRPs can be connected through either cable or over-the-air medium. In a case of cable connectivity, an attenuator can be used in lab environment to simulate real-world signal loss conditions.
|
||||
|
||||
#### 5.4.1 **Set the Attenuation Value**
|
||||
|
||||
In order to set the attenuation for each channel, run the following command.
|
||||
```
|
||||
curl http://169.254.10.10/:CHAN:<channel number>:SETATT:<attenuation in dB>
|
||||
```
|
||||
An example command is shown below, where we are setting the attenuation of channels 1 to 4 to 30 dB.
|
||||
```
|
||||
curl http://169.254.10.10/:CHAN:1:2:3:4:SETATT:30
|
||||
```
|
||||
Additionally, if you want to view the current attenuation values for each channel, run the folloiwng command.
|
||||
```
|
||||
curl http://169.254.10.10/:ATT?
|
||||
```
|
||||
|
||||
#### 5.4.2 **Running of SL Mode 2 on B210s**
|
||||
|
||||
SSH to Machine 1. Note, the serial field may need to be changed to match the USRPs:
|
||||
```
|
||||
$ cd ~/openairinterface5g/cmake_targets/ran_build/build
|
||||
$ sudo LD_LIBRARY_PATH=$PWD:$LD_LIBRARY_PATH -E \
|
||||
./nr-uesoftmodem -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_ue1.conf \
|
||||
--sa --sl-mode 2 --ue-txgain 10 --ue-rxgain 100 --usrp-args "serial=3150361,type=b200" \
|
||||
--thread-pool -1,-1 -E
|
||||
```
|
||||
|
||||
SSH to Machine 2. Note, the serial field may need to be changed to match the USRPs:
|
||||
|
||||
```
|
||||
$ cd ~/openairinterface5g/cmake_targets/ran_build/build
|
||||
$ sudo LD_LIBRARY_PATH=$PWD:$LD_LIBRARY_PATH -E \
|
||||
./nr-uesoftmodem -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf \
|
||||
--sa --sl-mode 2 --sync-ref --ue-txgain 10 --ue-rxgain 100 --usrp-args "serial=3150384,type=b200" \
|
||||
--thread-pool -1,-1 -E
|
||||
```
|
||||
Run `ping` command on a terminal in Machine 2. Note, oaitun_ue1 is the interface name of the SyncRef UE. 10.0.0.2 is the IP address of the Nearby UE.
|
||||
```
|
||||
ping -I oaitun_ue1 10.0.0.2
|
||||
```
|
||||
|
||||
|
||||
@@ -72,7 +72,8 @@ rlc_op_status_t rlc_data_req(const protocol_ctxt_t *const pc,
|
||||
const sdu_size_t size,
|
||||
mem_block_t *const buf,
|
||||
const uint32_t *const a,
|
||||
const uint32_t *const b)
|
||||
const uint32_t *const b,
|
||||
nr_intf_type_t intf_type)
|
||||
{
|
||||
abort();
|
||||
return 0;
|
||||
|
||||
@@ -81,6 +81,7 @@ unsigned short config_frames[4] = {2,9,11,13};
|
||||
#include "gnb_config.h"
|
||||
#include "openair2/E1AP/e1ap_common.h"
|
||||
#include "openair2/E1AP/e1ap_api.h"
|
||||
#include "nr_srap/nr_srap_oai_api.h"
|
||||
|
||||
#ifdef E2_AGENT
|
||||
#include "openair2/E2AP/flexric/src/agent/e2_agent_api.h"
|
||||
@@ -572,6 +573,14 @@ void init_pdcp(void) {
|
||||
nr_pdcp_layer_init();
|
||||
nr_pdcp_module_init(pdcp_initmask, 0);
|
||||
}
|
||||
if (!NODE_IS_CU(get_node_type())) {
|
||||
uint8_t relay_type = get_softmodem_params()->relay_type;
|
||||
if (relay_type == U2N || relay_type == U2U) {
|
||||
bool gNB_flag = true;
|
||||
nr_srap_layer_init(gNB_flag);
|
||||
srap_module_init(gNB_flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main( int argc, char **argv ) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -86,6 +86,8 @@ 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"
|
||||
#include "openair2/LAYER2/nr_srap/nr_srap_header.h"
|
||||
|
||||
extern const char *duplex_mode[];
|
||||
THREAD_STRUCT thread_struct;
|
||||
@@ -281,6 +283,8 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){
|
||||
UE->tx_power_max_dBm = tx_max_power[CC_id];
|
||||
UE->rf_map.card = card_offset;
|
||||
UE->rf_map.chain = CC_id + chain_offset;
|
||||
UE->rf_map_sl.card = card_offset + 1;
|
||||
UE->rf_map_sl.chain = CC_id + chain_offset + 1;
|
||||
UE->max_ldpc_iterations = nrUE_params.max_ldpc_iterations;
|
||||
UE->UE_scan_carrier = nrUE_params.UE_scan_carrier;
|
||||
UE->UE_fo_compensation = nrUE_params.UE_fo_compensation;
|
||||
@@ -290,6 +294,7 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){
|
||||
UE->chest_time = nrUE_params.chest_time;
|
||||
UE->no_timing_correction = nrUE_params.no_timing_correction;
|
||||
UE->timing_advance = nrUE_params.timing_advance;
|
||||
UE->timing_advance_sl = nrUE_params.timing_advance_sl;
|
||||
|
||||
LOG_I(PHY,"Set UE_fo_compensation %d, UE_scan_carrier %d, UE_no_timing_correction %d \n, chest-freq %d, chest-time %d\n",
|
||||
UE->UE_fo_compensation, UE->UE_scan_carrier, UE->no_timing_correction, UE->chest_freq, UE->chest_time);
|
||||
@@ -312,23 +317,20 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){
|
||||
|
||||
}
|
||||
|
||||
void init_openair0(void) {
|
||||
int card;
|
||||
int freq_off = 0;
|
||||
NR_DL_FRAME_PARMS *frame_parms = &PHY_vars_UE_g[0][0]->frame_parms;
|
||||
|
||||
for (card=0; card<MAX_CARDS; card++) {
|
||||
uint64_t dl_carrier, ul_carrier, sl_carrier;
|
||||
void init_openair0() {
|
||||
NR_DL_FRAME_PARMS *frame_parms;
|
||||
for (int card = 0; card < MAX_CARDS; card++) {
|
||||
// Assigning even cards to represent the Uu interface and odd cards to represent the PC5 interface.
|
||||
if (card % 2 == 0)
|
||||
frame_parms = &PHY_vars_UE_g[0][0]->frame_parms;
|
||||
else
|
||||
frame_parms = &PHY_vars_UE_g[0][0]->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
uint64_t dl_carrier = frame_parms->dl_CarrierFreq;
|
||||
uint64_t ul_carrier = frame_parms->ul_CarrierFreq;
|
||||
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].samples_per_frame = frame_parms->samples_per_frame;
|
||||
|
||||
if (frame_parms->frame_type==TDD)
|
||||
openair0_cfg[card].duplex_mode = duplex_mode_TDD;
|
||||
else
|
||||
openair0_cfg[card].duplex_mode = duplex_mode_FDD;
|
||||
|
||||
openair0_cfg[card].Mod_id = 0;
|
||||
openair0_cfg[card].num_rb_dl = frame_parms->N_RB_DL;
|
||||
openair0_cfg[card].clock_source = get_softmodem_params()->clock_source;
|
||||
@@ -336,7 +338,10 @@ void init_openair0(void) {
|
||||
openair0_cfg[card].tune_offset = get_softmodem_params()->tune_offset;
|
||||
openair0_cfg[card].tx_num_channels = min(4, frame_parms->nb_antennas_tx);
|
||||
openair0_cfg[card].rx_num_channels = min(4, frame_parms->nb_antennas_rx);
|
||||
|
||||
if (frame_parms->frame_type == TDD)
|
||||
openair0_cfg[card].duplex_mode = duplex_mode_TDD;
|
||||
else
|
||||
openair0_cfg[card].duplex_mode = duplex_mode_FDD;
|
||||
LOG_I(PHY, "HW: Configuring card %d, sample_rate %f, tx/rx num_channels %d/%d, duplex_mode %s\n",
|
||||
card,
|
||||
openair0_cfg[card].sample_rate,
|
||||
@@ -344,27 +349,24 @@ 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 (card % 2 == 1) { // sidelink for odd indices
|
||||
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);
|
||||
|
||||
int freq_off = 0;
|
||||
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;
|
||||
|
||||
if (usrp_args) openair0_cfg[card].sdr_addrs = usrp_args;
|
||||
if (tx_subdev) openair0_cfg[card].tx_subdev = tx_subdev;
|
||||
if (rx_subdev) openair0_cfg[card].rx_subdev = rx_subdev;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void init_pdcp(int ue_id) {
|
||||
static void init_pdcp(int ue_id, bool srap_enabled) {
|
||||
uint32_t pdcp_initmask = (!IS_SOFTMODEM_NOS1) ? LINK_ENB_PDCP_TO_GTPV1U_BIT : (LINK_ENB_PDCP_TO_GTPV1U_BIT | PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT);
|
||||
|
||||
/*if (IS_SOFTMODEM_RFSIM || (nfapi_getmode()==NFAPI_UE_STUB_PNF)) {
|
||||
@@ -381,6 +383,12 @@ static void init_pdcp(int ue_id) {
|
||||
nr_pdcp_module_init(pdcp_initmask, ue_id);
|
||||
pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req);
|
||||
pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind);
|
||||
// creates srap module, which will instanitate srap manager responsible for creating srap entitites and managing the entities operations
|
||||
if (srap_enabled) {
|
||||
bool gNB_flag = false;
|
||||
nr_srap_layer_init(gNB_flag);
|
||||
srap_module_init(gNB_flag);
|
||||
}
|
||||
}
|
||||
|
||||
// Stupid function addition because UE itti messages queues definition is common with eNB
|
||||
@@ -472,18 +480,38 @@ 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);
|
||||
bool srap_enabled = get_softmodem_params()->relay_type > 0 ? true : false;
|
||||
if (srap_enabled) {
|
||||
// FIXIT: This is temporary code until we get the ue configurations via RRC
|
||||
if (!get_softmodem_params()->remote_ue_id)
|
||||
get_softmodem_params()->remote_ue_id = ueinfo.remote_ue_id;
|
||||
if (!get_softmodem_params()->is_relay_ue)
|
||||
get_softmodem_params()->is_relay_ue = ueinfo.is_relay_ue;
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
uint8_t sl_mode = get_softmodem_params()->sl_mode;
|
||||
if(IS_SOFTMODEM_NOS1 || get_softmodem_params()->sa || get_softmodem_params()->nsa) {
|
||||
if(node_number == 0) {
|
||||
init_pdcp(0);
|
||||
}
|
||||
else {
|
||||
init_pdcp(mode_offset + ue_id_g);
|
||||
if(node_number == 0 && (sl_mode == 0 || sl_mode == 1)) {
|
||||
init_pdcp(0, srap_enabled);
|
||||
} else if (sl_mode == 2) {
|
||||
init_pdcp(1+ueinfo.srcid, srap_enabled);
|
||||
} else {
|
||||
init_pdcp(mode_offset + ue_id_g, srap_enabled);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -522,7 +550,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,6 +560,17 @@ 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) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -582,6 +621,8 @@ int main( int argc, char **argv ) {
|
||||
PHY_VARS_NR_UE *phy_vars = PHY_vars_UE_g[0][CC_id];
|
||||
if (phy_vars && phy_vars->rfdevice.trx_end_func)
|
||||
phy_vars->rfdevice.trx_end_func(&phy_vars->rfdevice);
|
||||
if (phy_vars && phy_vars->rfdevice_sl.trx_end_func)
|
||||
phy_vars->rfdevice_sl.trx_end_func(&phy_vars->rfdevice_sl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,13 +5,22 @@
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "SIMULATION/ETH_TRANSPORT/proto.h"
|
||||
|
||||
|
||||
typedef struct ueinfo {
|
||||
int srcid;
|
||||
int thirdOctet;
|
||||
int fourthOctet;
|
||||
uint8_t remote_ue_id;
|
||||
uint8_t is_relay_ue;
|
||||
} 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 +33,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 +71,9 @@
|
||||
{"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}, \
|
||||
{"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
|
||||
|
||||
@@ -72,6 +85,7 @@ typedef struct {
|
||||
int UE_scan_carrier;
|
||||
int UE_fo_compensation;
|
||||
int timing_advance;
|
||||
int timing_advance_sl;
|
||||
uint64_t if_freq;
|
||||
int if_freq_off;
|
||||
int chest_freq;
|
||||
@@ -82,6 +96,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,12 +108,17 @@ 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);
|
||||
extern void start_oai_nrue_threads(void);
|
||||
void *UE_thread_sl(void *arg);
|
||||
void *UE_thread(void *arg);
|
||||
void update_curMsg(PHY_VARS_NR_UE *UE, nr_rxtx_thread_data_t *curMsg, int absolute_slot, const int nb_slot_frame, nr_intf_type_t intf_type);
|
||||
void rfdevice_trx(PHY_VARS_NR_UE *UE, openair0_device *rfdevice, c16_t **rxdata, int slot_nr, int *rdBlkSz, int *wtBlkSz, openair0_timestamp *ts, openair0_timestamp *wts, int *ta, nr_intf_type_t intf_type);
|
||||
void UE_processing(PHY_VARS_NR_UE *UE, nr_rxtx_thread_data_t *curMsg, int readBlockSize, int writeBlockSize, openair0_timestamp writeTimestamp, notifiedFIFO_t *txFifo, nr_intf_type_t intf_type);
|
||||
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);
|
||||
int get_node_type();
|
||||
#endif
|
||||
|
||||
@@ -332,6 +332,17 @@ void init_ue_devices(PHY_VARS_UE *UE) {
|
||||
UE->rfdevice.trx_stop_func = UE_trx_stop;
|
||||
UE->rfdevice.trx_set_freq_func = UE_trx_set_freq;
|
||||
UE->rfdevice.trx_set_gains_func = UE_trx_set_gains;
|
||||
|
||||
UE->rfdevice_sl.Mod_id = UE->Mod_id;
|
||||
UE->rfdevice_sl.CC_id = UE->CC_id;
|
||||
UE->rfdevice_sl.trx_start_func = UE_trx_start;
|
||||
UE->rfdevice_sl.trx_read_func = UE_trx_read;
|
||||
UE->rfdevice_sl.trx_write_func = UE_trx_write;
|
||||
UE->rfdevice_sl.trx_end_func = UE_trx_end;
|
||||
UE->rfdevice_sl.trx_stop_func = UE_trx_stop;
|
||||
UE->rfdevice_sl.trx_set_freq_func = UE_trx_set_freq;
|
||||
UE->rfdevice_sl.trx_set_gains_func = UE_trx_set_gains;
|
||||
|
||||
sim.last_UE_rx_timestamp[UE->Mod_id][UE->CC_id] = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "softmodem-common.h"
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
#include "openair2/LAYER2/nr_srap/nr_srap_header.h"
|
||||
|
||||
|
||||
static softmodem_params_t softmodem_params;
|
||||
@@ -118,6 +119,9 @@ void get_common_options(uint32_t execmask) {
|
||||
config_set_checkfunctions(cmdline_logparams, cmdline_log_CheckParams, numlogparams);
|
||||
config_get(cmdline_logparams, numlogparams, NULL);
|
||||
|
||||
uint8_t relay_type = get_softmodem_params()->relay_type;
|
||||
AssertFatal((relay_type >= NO_RELAY) && (relay_type <= U2U), "Incorrect relay type!!!\n");
|
||||
|
||||
if(config_isparamset(cmdline_logparams,config_paramidx_fromname(cmdline_logparams,numparams, CONFIG_FLOG_OPT))) {
|
||||
set_glog_onlinelog(online_log_messages);
|
||||
}
|
||||
|
||||
@@ -109,6 +109,9 @@ extern "C"
|
||||
#define CONFIG_HLP_SYNC_REF "Sync Reference in Sidelink\n"
|
||||
#define CONFIG_HLP_NID1 "Set NID1 value in Sidelink\n"
|
||||
#define CONFIG_HLP_NID2 "Set NID2 value in Sidelink\n"
|
||||
#define CONFIG_HLP_RELAY_TYPE "Set Relay type to represent No Relay (0), U2N (1) and U2U (2) cases. Later this will be properly configured from RRC."
|
||||
#define CONFIG_HLP_REMOTE_UE_ID "Set Remote UE ID to fill in SRAP header"
|
||||
#define CONFIG_HLP_IS_RELAY_UE "Set to configure a UE Relay role"
|
||||
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* command line parameters common to eNodeB and UE */
|
||||
@@ -143,6 +146,9 @@ extern "C"
|
||||
#define SYNC_REF softmodem_params.sync_ref
|
||||
#define NID1 softmodem_params.nid1
|
||||
#define NID2 softmodem_params.nid2
|
||||
#define RELAY_TYPE softmodem_params.relay_type
|
||||
#define REMOTE_UE_ID softmodem_params.remote_ue_id
|
||||
#define IS_RELAY_UE softmodem_params.is_relay_ue
|
||||
|
||||
#define REORDER_THREAD_DISABLE softmodem_params.reorder_thread_disable
|
||||
#define DEFAULT_RFCONFIG_FILE "/usr/local/etc/syriq/ue.band7.tm1.PRB100.NR40.dat";
|
||||
@@ -190,6 +196,9 @@ extern int usrp_tx_thread;
|
||||
{"disable-stats", CONFIG_HLP_STATS_DISABLE, PARAMFLAG_BOOL, .iptr=&stats_disabled, .defintval=0, TYPE_INT, 0}, \
|
||||
{"nid1", CONFIG_HLP_NID1, 0, .iptr=&NID1, .defintval=10, TYPE_INT, 0}, \
|
||||
{"nid2", CONFIG_HLP_NID2, 0, .iptr=&NID2, .defintval=1, TYPE_INT, 0}, \
|
||||
{"relay-type", CONFIG_HLP_RELAY_TYPE, 0, .u8ptr=&RELAY_TYPE, .defintval=0, TYPE_UINT8, 0}, \
|
||||
{"remote-ue-id", CONFIG_HLP_REMOTE_UE_ID, 0, .u8ptr=&REMOTE_UE_ID, .defintval=0, TYPE_UINT8, 0}, \
|
||||
{"is-relay-ue", CONFIG_HLP_IS_RELAY_UE, 0, .u8ptr=&IS_RELAY_UE, .defintval=0, TYPE_UINT8, 0}, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
@@ -238,6 +247,9 @@ extern int usrp_tx_thread;
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
@@ -349,6 +361,9 @@ typedef struct {
|
||||
int sync_ref;
|
||||
int nid1;
|
||||
int nid2;
|
||||
uint8_t relay_type;
|
||||
uint8_t remote_ue_id;
|
||||
uint8_t is_relay_ue;
|
||||
} softmodem_params_t;
|
||||
|
||||
extern uint64_t get_softmodem_optmask(void);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
|
||||
@@ -5,11 +5,31 @@
|
||||
|
||||
#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_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 +40,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 +50,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 +59,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 +92,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 +214,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 +237,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 +286,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 +311,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 +404,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 +416,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 +435,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)
|
||||
{
|
||||
@@ -288,16 +292,23 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
|
||||
// init TX buffers
|
||||
common_vars->txData = malloc16(fp->nb_antennas_tx * sizeof(c16_t *));
|
||||
common_vars->txDataSl = malloc16(fp->nb_antennas_tx * sizeof(c16_t *));
|
||||
|
||||
for (i=0; i<fp->nb_antennas_tx; i++) {
|
||||
common_vars->txData[i] = malloc16_clear((fp->samples_per_frame) * sizeof(c16_t));
|
||||
common_vars->txDataSl[i] = malloc16_clear((fp->samples_per_frame) * sizeof(c16_t));
|
||||
}
|
||||
|
||||
// init RX buffers
|
||||
common_vars->rxdata = malloc16(fp->nb_antennas_rx * sizeof(c16_t *));
|
||||
common_vars->rxdata_sl = malloc16(fp->nb_antennas_rx * sizeof(c16_t *));
|
||||
|
||||
int num_samples = 2 * fp->samples_per_frame + fp->ofdm_symbol_size;
|
||||
int num_samples_sl = (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));
|
||||
common_vars->rxdata_sl[i] = malloc16_clear(num_samples_sl * sizeof(c16_t));
|
||||
}
|
||||
|
||||
// ceil(((NB_RB<<1)*3)/32) // 3 RE *2(QPSK)
|
||||
@@ -384,6 +395,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;
|
||||
@@ -403,14 +423,18 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
|
||||
for (int i = 0; i < fp->nb_antennas_tx; i++) {
|
||||
free_and_zero(common_vars->txData[i]);
|
||||
free_and_zero(common_vars->txDataSl[i]);
|
||||
}
|
||||
|
||||
free_and_zero(common_vars->txData);
|
||||
free_and_zero(common_vars->txDataSl);
|
||||
|
||||
for (int i = 0; i < fp->nb_antennas_rx; i++) {
|
||||
free_and_zero(common_vars->rxdata[i]);
|
||||
free_and_zero(common_vars->rxdata_sl[i]);
|
||||
}
|
||||
free_and_zero(common_vars->rxdata);
|
||||
free_and_zero(common_vars->rxdata_sl);
|
||||
|
||||
for (int slot = 0; slot < fp->slots_per_frame; slot++) {
|
||||
for (int symb = 0; symb < fp->symbols_per_slot; symb++)
|
||||
@@ -489,6 +513,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 +566,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 +652,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,9 +663,12 @@ 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 == 1 || ue->sl_mode == 2)) {
|
||||
ue->N_TA_offset = 0;
|
||||
} else {
|
||||
ue->N_TA_offset_sl = 0;
|
||||
}
|
||||
if (fp->frame_type != FDD && (ue->sl_mode == 0 || ue->sl_mode == 1)) {
|
||||
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
|
||||
|
||||
double factor = 1.0;
|
||||
@@ -673,11 +705,11 @@ void init_N_TA_offset(PHY_VARS_NR_UE *ue){
|
||||
}
|
||||
|
||||
void phy_init_nr_top(PHY_VARS_NR_UE *ue) {
|
||||
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
NR_DL_FRAME_PARMS *frame_parms = ue->sl_mode == 2 ? &ue->SL_UE_PHY_PARAMS.sl_frame_params : &ue->frame_parms;
|
||||
crcTableInit();
|
||||
init_scrambling_luts();
|
||||
load_dftslib();
|
||||
init_context_synchro_nr(frame_parms);
|
||||
init_context_synchro_nr(frame_parms, (ue->sl_mode == 2) ? PC5 : UU);
|
||||
generate_ul_reference_signal_sequences(SHRT_MAX);
|
||||
}
|
||||
|
||||
@@ -686,3 +718,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,
|
||||
|
||||
@@ -110,136 +110,133 @@ const char nr_W_4l_4p[5][4][4] = {
|
||||
{{'1', '1', '1', '1'}, {'1', 'n', '1', 'n'}, {'j', 'j', 'o', 'o'}, {'j', 'o', 'o', 'j'}} // pmi 4
|
||||
};
|
||||
|
||||
void nr_modulation(uint32_t *in,
|
||||
uint32_t length,
|
||||
uint16_t mod_order,
|
||||
int16_t *out)
|
||||
void nr_modulation(const uint32_t *in, uint32_t length, uint16_t mod_order, int16_t *out)
|
||||
{
|
||||
uint16_t mask = ((1<<mod_order)-1);
|
||||
int32_t* nr_mod_table32;
|
||||
int32_t* out32 = (int32_t*) out;
|
||||
uint8_t* in_bytes = (uint8_t*) in;
|
||||
uint64_t* in64 = (uint64_t*) in;
|
||||
int64_t* out64 = (int64_t*) out;
|
||||
uint8_t idx;
|
||||
uint32_t i,j;
|
||||
uint32_t bit_cnt;
|
||||
uint64_t x,x1,x2;
|
||||
uint16_t mask = ((1 << mod_order) - 1);
|
||||
int32_t *nr_mod_table32;
|
||||
int32_t *out32 = (int32_t *)out;
|
||||
const uint8_t *in_bytes = (const uint8_t *)in;
|
||||
const uint64_t *in64 = (const uint64_t *)in;
|
||||
int64_t *out64 = (int64_t *)out;
|
||||
uint32_t i = 0;
|
||||
|
||||
#if defined(__SSE2__)
|
||||
__m128i *nr_mod_table128;
|
||||
__m128i *out128;
|
||||
simde__m128i *nr_mod_table128;
|
||||
simde__m128i *out128;
|
||||
#endif
|
||||
|
||||
LOG_D(PHY,"nr_modulation: length %d, mod_order %d\n",length,mod_order);
|
||||
LOG_D(PHY, "nr_modulation: length %d, mod_order %d\n", length, mod_order);
|
||||
|
||||
switch (mod_order) {
|
||||
|
||||
#if defined(__SSE2__)
|
||||
case 2:
|
||||
nr_mod_table128 = (__m128i*) nr_qpsk_byte_mod_table;
|
||||
out128 = (__m128i*) out;
|
||||
for (i=0; i<length/8; i++)
|
||||
out128[i] = nr_mod_table128[in_bytes[i]];
|
||||
// the bits that are left out
|
||||
i = i*8/2;
|
||||
nr_mod_table32 = (int32_t*) nr_qpsk_mod_table;
|
||||
while (i<length/2) {
|
||||
idx = ((in_bytes[(i*2)/8]>>((i*2)&0x7)) & mask);
|
||||
out32[i] = nr_mod_table32[idx];
|
||||
i++;
|
||||
}
|
||||
return;
|
||||
case 2:
|
||||
nr_mod_table128 = (simde__m128i *)nr_qpsk_byte_mod_table;
|
||||
out128 = (simde__m128i *)out;
|
||||
for (i = 0; i < length / 8; i++)
|
||||
out128[i] = nr_mod_table128[in_bytes[i]];
|
||||
// the bits that are left out
|
||||
i = i * 8 / 2;
|
||||
nr_mod_table32 = (int32_t *)nr_qpsk_mod_table;
|
||||
while (i < length / 2) {
|
||||
const int idx = ((in_bytes[(i * 2) / 8] >> ((i * 2) & 0x7)) & mask);
|
||||
out32[i] = nr_mod_table32[idx];
|
||||
i++;
|
||||
}
|
||||
return;
|
||||
#else
|
||||
case 2:
|
||||
nr_mod_table32 = (int32_t*) nr_qpsk_mod_table;
|
||||
for (i=0; i<length/mod_order; i++) {
|
||||
idx = ((in[i*2/32]>>((i*2)&0x1f)) & mask);
|
||||
out32[i] = nr_mod_table32[idx];
|
||||
}
|
||||
return;
|
||||
case 2:
|
||||
nr_mod_table32 = (int32_t *)nr_qpsk_mod_table;
|
||||
for (i = 0; i < length / mod_order; i++) {
|
||||
const int idx = ((in[i * 2 / 32] >> ((i * 2) & 0x1f)) & mask);
|
||||
out32[i] = nr_mod_table32[idx];
|
||||
}
|
||||
return;
|
||||
#endif
|
||||
|
||||
case 4:
|
||||
out64 = (int64_t*) out;
|
||||
for (i=0; i<length/8; i++)
|
||||
out64[i] = nr_16qam_byte_mod_table[in_bytes[i]];
|
||||
// the bits that are left out
|
||||
i = i*8/4;
|
||||
while (i<length/4) {
|
||||
idx = ((in_bytes[(i*4)/8]>>((i*4)&0x7)) & mask);
|
||||
out32[i] = nr_16qam_mod_table[idx];
|
||||
i++;
|
||||
}
|
||||
return;
|
||||
case 4:
|
||||
out64 = (int64_t *)out;
|
||||
for (i = 0; i < length / 8; i++)
|
||||
out64[i] = nr_16qam_byte_mod_table[in_bytes[i]];
|
||||
// the bits that are left out
|
||||
i = i * 8 / 4;
|
||||
while (i < length / 4) {
|
||||
const int idx = ((in_bytes[(i * 4) / 8] >> ((i * 4) & 0x7)) & mask);
|
||||
out32[i] = nr_16qam_mod_table[idx];
|
||||
i++;
|
||||
}
|
||||
return;
|
||||
|
||||
case 6:
|
||||
j = 0;
|
||||
for (i=0; i<length/192; i++) {
|
||||
x = in64[i*3];
|
||||
x1 = x&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x>>12)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x>>24)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x>>36)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x>>48)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x2 = (x>>60);
|
||||
x = in64[i*3+1];
|
||||
x2 |= x<<4;
|
||||
x1 = x2&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x2>>12)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x2>>24)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x2>>36)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x2>>48)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x2 = ((x>>56)&0xf0) | (x2>>60);
|
||||
x = in64[i*3+2];
|
||||
x2 |= x<<8;
|
||||
x1 = x2&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x2>>12)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x2>>24)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x2>>36)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x2>>48)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x2 = ((x>>52)&0xff0) | (x2>>60);
|
||||
out64[j++] = nr_64qam_mod_table[x2];
|
||||
}
|
||||
i *= 24;
|
||||
bit_cnt = i * 8;
|
||||
while (bit_cnt < length) {
|
||||
uint32_t xx;
|
||||
memcpy(&xx, in_bytes+i, sizeof(xx));
|
||||
x1 = xx & 4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (xx >> 12) & 4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
i += 3;
|
||||
bit_cnt += 24;
|
||||
}
|
||||
return;
|
||||
case 6:
|
||||
if (length > (3 * 64))
|
||||
for (i = 0; i < length - 3 * 64; i += 3 * 64) {
|
||||
uint64_t x = *in64++;
|
||||
uint64_t x1 = x & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x >> 12) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x >> 24) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x >> 36) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x >> 48) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
uint64_t x2 = (x >> 60);
|
||||
x = *in64++;
|
||||
x2 |= x << 4;
|
||||
x1 = x2 & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x2 >> 12) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x2 >> 24) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x2 >> 36) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x2 >> 48) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x2 = ((x >> 56) & 0xf0) | (x2 >> 60);
|
||||
x = *in64++;
|
||||
x2 |= x << 8;
|
||||
x1 = x2 & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x2 >> 12) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x2 >> 24) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x2 >> 36) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x2 >> 48) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x2 = ((x >> 52) & 0xff0) | (x2 >> 60);
|
||||
*out64++ = nr_64qam_mod_table[x2];
|
||||
}
|
||||
|
||||
case 8:
|
||||
nr_mod_table32 = (int32_t*) nr_256qam_mod_table;
|
||||
for (i=0; i<length/8; i++)
|
||||
out32[i] = nr_mod_table32[in_bytes[i]];
|
||||
return;
|
||||
while (i + 24 <= length) {
|
||||
uint32_t xx = 0;
|
||||
memcpy(&xx, in_bytes + i / 8, 3);
|
||||
uint64_t x1 = xx & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (xx >> 12) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
i += 24;
|
||||
}
|
||||
if (i != length) {
|
||||
uint32_t xx = 0;
|
||||
memcpy(&xx, in_bytes + i / 8, 2);
|
||||
uint64_t x1 = xx & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
}
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
case 8:
|
||||
nr_mod_table32 = (int32_t *)nr_256qam_mod_table;
|
||||
for (i = 0; i < length / 8; i++)
|
||||
out32[i] = nr_mod_table32[in_bytes[i]];
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
AssertFatal(false,"Invalid or unsupported modulation order %d\n",mod_order);
|
||||
AssertFatal(false, "Invalid or unsupported modulation order %d\n", mod_order);
|
||||
}
|
||||
|
||||
void nr_layer_mapping(int16_t **mod_symbs,
|
||||
@@ -601,7 +598,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 +606,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 +628,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,
|
||||
|
||||
@@ -42,7 +42,7 @@ extern const char nr_W_4l_4p[5][4][4];
|
||||
@param[out] out, complex valued modulated symbols
|
||||
*/
|
||||
|
||||
void nr_modulation(uint32_t *in,
|
||||
void nr_modulation(const uint32_t *in,
|
||||
uint32_t length,
|
||||
uint16_t mod_order,
|
||||
int16_t *out);
|
||||
|
||||
@@ -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_sl[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_sl[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;
|
||||
|
||||
@@ -48,7 +143,8 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
|
||||
unsigned int nb_prefix_samples;
|
||||
unsigned int nb_prefix_samples0;
|
||||
if (ue->is_synchronized) {
|
||||
int is_synchronized = (linktype == link_type_pc5) ? ue->is_synchronized_sl : ue->is_synchronized;
|
||||
if (is_synchronized) {
|
||||
nb_prefix_samples = frame_parms->nb_prefix_samples;
|
||||
nb_prefix_samples0 = frame_parms->nb_prefix_samples0;
|
||||
} else {
|
||||
@@ -69,19 +165,20 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
// use OFDM symbol from within 1/8th of the CP to avoid ISI
|
||||
rx_offset -= (nb_prefix_samples / frame_parms->ofdm_offset_divisor);
|
||||
|
||||
//#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];
|
||||
int16_t *rxdata_ptr = (linktype == link_type_pc5) ? (int16_t *)&common_vars->rxdata_sl[aa][rx_offset] : (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],
|
||||
(linktype == link_type_pc5) ? (void *)&common_vars->rxdata_sl[aa][rx_offset] :
|
||||
(void *)&common_vars->rxdata[aa][rx_offset],
|
||||
frame_parms->ofdm_symbol_size * sizeof(int32_t));
|
||||
|
||||
rxdata_ptr = (int16_t *)tmp_dft_in;
|
||||
@@ -96,18 +193,21 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
|
||||
stop_meas(&ue->rx_dft_stats);
|
||||
|
||||
LOG_D(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);
|
||||
|
||||
}
|
||||
|
||||
#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 = gNB ? (Ns & 3) * gNB->frame_parms.symbols_per_slot * symbolSize : 0;
|
||||
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,
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
#define SYNC_TMP_SIZE (NB_ANTENNAS_RX*SYNCHRO_FFT_SIZE_MAX*IQ_SIZE) /* to be aligned with existing lte synchro */
|
||||
#define SYNCF_TMP_SIZE (SYNCHRO_FFT_SIZE_MAX*IQ_SIZE)
|
||||
|
||||
void init_context_synchro_nr(NR_DL_FRAME_PARMS *frame_parms_ue);
|
||||
void init_context_synchro_nr(NR_DL_FRAME_PARMS *frame_parms_ue, nr_intf_type_t intf_type);
|
||||
void free_context_synchro_nr(void);
|
||||
int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change);
|
||||
int16_t *get_primary_synchro_nr2(const int nid2);
|
||||
|
||||
@@ -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,22 @@ 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,
|
||||
nr_intf_type_t intf_type);
|
||||
#endif
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
#define INDEX_NO_PHASE_DIFFERENCE (3) /* this is for no phase shift case */
|
||||
/************** FUNCTION ******************************************/
|
||||
|
||||
void init_context_sss_nr(int amp);
|
||||
void init_context_sss_nr(int amp, nr_intf_type_t intf_type);
|
||||
void free_context_sss_nr(void);
|
||||
|
||||
void insert_sss_nr(int16_t *sss_time,
|
||||
|
||||
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
|
||||
|
||||
@@ -45,7 +45,8 @@ void nr_group_sequence_hopping(pucch_GroupHopping_t PUCCH_GroupHopping,
|
||||
uint8_t n_hop,
|
||||
int nr_slot_tx,
|
||||
uint8_t *u,
|
||||
uint8_t *v);
|
||||
uint8_t *v,
|
||||
nr_intf_type_t intf_type);
|
||||
|
||||
double nr_cyclic_shift_hopping(uint32_t n_id,
|
||||
uint8_t m0,
|
||||
@@ -59,6 +60,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,21 @@ 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,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
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);
|
||||
uint8_t nb_antennas_tx,
|
||||
nr_intf_type_t intf_type,
|
||||
void (* _nr_ue_csi_rs_procedures)(PHY_VARS_NR_UE *ue, NR_DL_FRAME_PARMS *frame_parms, UE_nr_rxtx_proc_t *proc, c16_t rxdataF[][frame_parms->samples_per_slot_wCP], nr_intf_type_t intf_type),
|
||||
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 +152,22 @@ 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_intf_type_t intf_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,
|
||||
@@ -375,7 +396,8 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t *N_ports,
|
||||
uint8_t *j_cdm,
|
||||
uint8_t *k_overline,
|
||||
uint8_t *l_overline);
|
||||
uint8_t *l_overline,
|
||||
nr_intf_type_t intf_type);
|
||||
|
||||
void free_nr_prach_entry(PHY_VARS_gNB *gNB, int prach_id);
|
||||
|
||||
|
||||
@@ -31,13 +31,15 @@
|
||||
*/
|
||||
|
||||
#include "nr_dci.h"
|
||||
# include "executables/softmodem-common.h"
|
||||
|
||||
void nr_group_sequence_hopping (pucch_GroupHopping_t PUCCH_GroupHopping,
|
||||
uint32_t n_id,
|
||||
uint8_t n_hop,
|
||||
int nr_slot_tx,
|
||||
uint8_t *u,
|
||||
uint8_t *v) {
|
||||
uint8_t *v,
|
||||
nr_intf_type_t intf_type) {
|
||||
/*
|
||||
* Implements TS 38.211 subclause 6.3.2.2.1 Group and sequence hopping
|
||||
* The following variables are set by higher layers:
|
||||
@@ -63,7 +65,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 (intf_type == PC5) {
|
||||
*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 +145,30 @@ 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;
|
||||
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,12 @@ 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,
|
||||
tpool_t *Tpool,
|
||||
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
|
||||
|
||||
@@ -122,7 +125,9 @@ NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL)
|
||||
static void nr_processULSegment(void *arg)
|
||||
{
|
||||
ldpcDecode_t *rdata = (ldpcDecode_t *)arg;
|
||||
#ifdef DEBUG_ULSCH_DECODING
|
||||
PHY_VARS_gNB *phy_vars_gNB = rdata->gNB;
|
||||
#endif
|
||||
NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
|
||||
t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms;
|
||||
int length_dec;
|
||||
@@ -155,9 +160,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 +174,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 +200,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 +226,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 +241,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 +253,31 @@ 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,
|
||||
tpool_t *Tpool,
|
||||
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 +285,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 +399,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 +481,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 +500,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 +508,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 +535,23 @@ 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 : 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, 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,23 @@ 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_intf_type_t intf_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 +332,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 = (intf_type == PC5) ? 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 +349,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 (((intf_type == PC5) && (is_csirs_symbol == 0)) || (intf_type != PC5)) {
|
||||
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, intf_type);
|
||||
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 +424,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 +449,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 +652,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 +1110,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 +1954,253 @@ 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,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
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)
|
||||
uint8_t nb_antennas_tx,
|
||||
nr_intf_type_t intf_type,
|
||||
void (* _nr_ue_csi_rs_procedures)(PHY_VARS_NR_UE *ue, NR_DL_FRAME_PARMS *frame_parms, UE_nr_rxtx_proc_t *proc, c16_t rxdataF[][frame_parms->samples_per_slot_wCP], nr_intf_type_t intf_type),
|
||||
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_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 && is_csi_rs_slot) {
|
||||
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_pc5);
|
||||
_nr_ue_csi_rs_procedures(ue, frame_parms, proc, rxdataF, PC5);
|
||||
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 = nb_antennas_tx > 2 ? 2 : 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, intf_type, frame_parms, csi_params);
|
||||
if (gNB) stop_meas(&gNB->ulsch_rbs_extraction_stats);
|
||||
|
||||
//----------------------------------------------------------
|
||||
//--------------------- Channel Scaling --------------------
|
||||
@@ -2057,8 +2211,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 +2221,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 +2240,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 +2304,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 +2323,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 (pssch_pdu && (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");
|
||||
@@ -2210,8 +2452,10 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
stop_meas(&gNB->ulsch_llr_stats);
|
||||
if (gNB) stop_meas(&gNB->ulsch_llr_stats);
|
||||
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,
|
||||
@@ -224,7 +194,8 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
|
||||
0,
|
||||
slot,
|
||||
&u[0],
|
||||
&v[0]); // calculating u and v value first hop
|
||||
&v[0],
|
||||
UU); // 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) {
|
||||
@@ -233,7 +204,8 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
|
||||
1,
|
||||
slot,
|
||||
&u[1],
|
||||
&v[1]); // calculating u and v value second hop
|
||||
&v[1],
|
||||
UU); // 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;
|
||||
}
|
||||
@@ -649,7 +621,7 @@ void nr_decode_pucch1(c16_t **rxdataF,
|
||||
printf("\t [nr_generate_pucch1] entering function nr_group_sequence_hopping with n_hop=%d, nr_tti_tx=%d\n",
|
||||
n_hop,nr_tti_tx);
|
||||
#endif
|
||||
nr_group_sequence_hopping(pucch_GroupHopping,n_id,n_hop,nr_tti_tx,&u,&v); // calculating u and v value
|
||||
nr_group_sequence_hopping(pucch_GroupHopping,n_id,n_hop,nr_tti_tx,&u,&v, UU); // calculating u and v value
|
||||
alpha = nr_cyclic_shift_hopping(n_id,m0,mcs,l,lprime,nr_tti_tx);
|
||||
|
||||
for (int n=0; n<12; n++) { // generating low papr sequences
|
||||
@@ -1691,7 +1663,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,36 @@ 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,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
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[][frame_parms->samples_per_slot_wCP],
|
||||
int16_t *rsrp_dBm,
|
||||
nr_intf_type_t intf_type)
|
||||
{
|
||||
|
||||
int Ns = proc->nr_slot_rx;
|
||||
@@ -1022,26 +1060,33 @@ 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;
|
||||
ch_offset = frame_parms->ofdm_symbol_size*symbol;
|
||||
|
||||
symbol_offset = ue->frame_parms.ofdm_symbol_size*symbol;
|
||||
symbol_offset = frame_parms->ofdm_symbol_size*symbol;
|
||||
|
||||
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;
|
||||
|
||||
#ifdef DEBUG_PDCCH
|
||||
printf("PDCCH Channel Estimation : gNB_id %d ch_offset %d, OFDM size %d, Ncp=%d, Ns=%d, symbol %d\n",
|
||||
gNB_id,ch_offset,ue->frame_parms.ofdm_symbol_size,ue->frame_parms.Ncp,Ns,symbol);
|
||||
gNB_id, ch_offset, frame_parms->ofdm_symbol_size, frame_parms->Ncp, Ns, symbol);
|
||||
#endif
|
||||
|
||||
#if CH_INTERP
|
||||
@@ -1052,30 +1097,33 @@ 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(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++) {
|
||||
for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
|
||||
|
||||
k = coreset_start_subcarrier;
|
||||
pil = (int16_t *)&pilot[dmrs_ref*3];
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+1)];
|
||||
dl_ch = (int16_t *)&pdcch_dl_ch_estimates[aarx][ch_offset];
|
||||
|
||||
memset(dl_ch,0,4*(ue->frame_parms.ofdm_symbol_size));
|
||||
memset(dl_ch, 0, 4 * (frame_parms->ofdm_symbol_size));
|
||||
|
||||
#ifdef DEBUG_PDCCH
|
||||
printf("pdcch ch est pilot addr %p RB_DL %d\n",&pilot[dmrs_ref*3], ue->frame_parms.N_RB_DL);
|
||||
printf("k %d, first_carrier %d\n",k,ue->frame_parms.first_carrier_offset);
|
||||
printf("pdcch ch est pilot addr %p RB_DL %d\n",&pilot[dmrs_ref*3], frame_parms->N_RB_DL);
|
||||
printf("k %d, first_carrier %d\n", k, frame_parms->first_carrier_offset);
|
||||
printf("rxF addr %p\n", rxF);
|
||||
|
||||
printf("dl_ch addr %p\n",dl_ch);
|
||||
@@ -1097,8 +1145,8 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
rxF += 8;
|
||||
k += 4;
|
||||
|
||||
if (k >= ue->frame_parms.ofdm_symbol_size) {
|
||||
k -= ue->frame_parms.ofdm_symbol_size;
|
||||
if (k >= frame_parms->ofdm_symbol_size) {
|
||||
k -= frame_parms->ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+1)];
|
||||
}
|
||||
|
||||
@@ -1115,8 +1163,8 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
rxF += 8;
|
||||
k += 4;
|
||||
|
||||
if (k >= ue->frame_parms.ofdm_symbol_size) {
|
||||
k -= ue->frame_parms.ofdm_symbol_size;
|
||||
if (k >= frame_parms->ofdm_symbol_size) {
|
||||
k -= frame_parms->ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+1)];
|
||||
}
|
||||
|
||||
@@ -1143,8 +1191,8 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
|
||||
for (pilot_cnt=3; pilot_cnt<(3*nb_rb_coreset); pilot_cnt += 3) {
|
||||
|
||||
if (k >= ue->frame_parms.ofdm_symbol_size) {
|
||||
k -= ue->frame_parms.ofdm_symbol_size;
|
||||
if (k >= frame_parms->ofdm_symbol_size) {
|
||||
k -= frame_parms->ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+1)];
|
||||
}
|
||||
|
||||
@@ -1165,8 +1213,8 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
rxF += 8;
|
||||
k += 4;
|
||||
|
||||
if (k >= ue->frame_parms.ofdm_symbol_size) {
|
||||
k -= ue->frame_parms.ofdm_symbol_size;
|
||||
if (k >= frame_parms->ofdm_symbol_size) {
|
||||
k -= frame_parms->ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+1)];
|
||||
}
|
||||
|
||||
@@ -1183,8 +1231,8 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
rxF += 8;
|
||||
k += 4;
|
||||
|
||||
if (k >= ue->frame_parms.ofdm_symbol_size) {
|
||||
k -= ue->frame_parms.ofdm_symbol_size;
|
||||
if (k >= frame_parms->ofdm_symbol_size) {
|
||||
k -= frame_parms->ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+1)];
|
||||
}
|
||||
|
||||
@@ -1212,19 +1260,27 @@ 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;
|
||||
if (k >= frame_parms->ofdm_symbol_size) {
|
||||
k -= frame_parms->ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+1)];
|
||||
}
|
||||
#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
|
||||
if (intf_type == PC5) {
|
||||
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 +1301,13 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
if (intf_type == PC5) {
|
||||
rsrp = rsrp_sum / meas_count;
|
||||
*rsrp_dBm = dB_fixed(rsrp) + 30 - pow_2_30_dB
|
||||
- ((int)openair0_cfg[ue->rf_map_sl.card].rx_gain[0] - (int)openair0_cfg[ue->rf_map_sl.card].rx_gain_offset[0]) - dB_fixed(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,
|
||||
|
||||
@@ -51,14 +51,18 @@ void peak_estimator(int32_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t
|
||||
\param symbol symbol within slot
|
||||
*/
|
||||
void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
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[][frame_parms->samples_per_slot_wCP],
|
||||
int16_t* rsrp_dBm,
|
||||
nr_intf_type_t intf_type);
|
||||
|
||||
int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
@@ -68,15 +72,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 +148,10 @@ 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(PHY_VARS_NR_UE *ue,
|
||||
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,57 @@ 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(PHY_VARS_NR_UE *ue,
|
||||
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[ue->rf_map_sl.card].rx_gain[0] - (int)openair0_cfg[ue->rf_map_sl.card].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,13 +39,13 @@
|
||||
#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 DEBUG_CSI_PRINTS // To enable CSI SNR debug logs
|
||||
extern short nr_qpsk_mod_table[8];
|
||||
//#define NR_CSIRS_DEBUG
|
||||
//#define NR_CSIIM_DEBUG
|
||||
|
||||
@@ -181,6 +181,7 @@ bool is_csi_rs_in_symbol(const fapi_nr_dl_config_csirs_pdu_rel15_t csirs_config_
|
||||
}
|
||||
|
||||
int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue,
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
|
||||
const nr_csi_info_t *nr_csi_info,
|
||||
@@ -191,12 +192,12 @@ int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue,
|
||||
const uint8_t *j_cdm,
|
||||
const uint8_t *k_overline,
|
||||
const uint8_t *l_overline,
|
||||
int32_t csi_rs_received_signal[][ue->frame_parms.samples_per_slot_wCP],
|
||||
int32_t csi_rs_received_signal[][frame_parms->samples_per_slot_wCP],
|
||||
uint32_t *rsrp,
|
||||
int *rsrp_dBm,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
|
||||
c16_t rxdataF[][frame_parms->samples_per_slot_wCP],
|
||||
nr_intf_type_t intf_type) {
|
||||
|
||||
const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
uint16_t meas_count = 0;
|
||||
uint32_t rsrp_sum = 0;
|
||||
|
||||
@@ -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 && (intf_type == PC5 ? 0 : csirs_config_pdu->freq_density != (rb % 2))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -230,9 +231,9 @@ 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 = intf_type == PC5 ? 0 : proc->nr_slot_rx * 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",
|
||||
@@ -253,9 +254,11 @@ int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
|
||||
|
||||
AssertFatal(meas_count != 0, "Expecting meas_count > 0, but meas_count = 0\n");
|
||||
int card = intf_type == PC5 ? ue->rf_map_sl.card : ue->rf_map.card;
|
||||
*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);
|
||||
- ((int)openair0_cfg[card].rx_gain[0] - (int)openair0_cfg[card].rx_gain_offset[0]) - dB_fixed(frame_parms->ofdm_symbol_size);
|
||||
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
LOG_I(NR_PHY, "RSRP = %i (%i dBm)\n", *rsrp, *rsrp_dBm);
|
||||
@@ -264,13 +267,13 @@ int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue,
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t calc_power_csirs(const uint16_t *x, const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu)
|
||||
uint32_t calc_power_csirs(const uint16_t *x, const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu, nr_intf_type_t intf_type)
|
||||
{
|
||||
uint64_t sum_x = 0;
|
||||
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 && intf_type == PC5 ? 0 : csirs_config_pdu->freq_density != ((rb + csirs_config_pdu->start_rb) % 2)) {
|
||||
continue;
|
||||
}
|
||||
sum_x = sum_x + x[rb];
|
||||
@@ -281,11 +284,12 @@ uint32_t calc_power_csirs(const uint16_t *x, const fapi_nr_dl_config_csirs_pdu_r
|
||||
}
|
||||
|
||||
int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
|
||||
const nr_csi_info_t *nr_csi_info,
|
||||
const int32_t **csi_rs_generated_signal,
|
||||
const int32_t csi_rs_received_signal[][ue->frame_parms.samples_per_slot_wCP],
|
||||
const int32_t csi_rs_received_signal[][frame_parms->samples_per_slot_wCP],
|
||||
const uint8_t N_cdm_groups,
|
||||
const uint8_t CDM_group_size,
|
||||
const uint8_t k_prime,
|
||||
@@ -295,14 +299,13 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
const uint8_t *k_overline,
|
||||
const uint8_t *l_overline,
|
||||
uint8_t mem_offset,
|
||||
int32_t csi_rs_ls_estimated_channel[][N_ports][ue->frame_parms.ofdm_symbol_size],
|
||||
int32_t csi_rs_estimated_channel_freq[][N_ports][ue->frame_parms.ofdm_symbol_size + FILTER_MARGIN],
|
||||
int32_t csi_rs_ls_estimated_channel[][N_ports][frame_parms->ofdm_symbol_size],
|
||||
int32_t csi_rs_estimated_channel_freq[][N_ports][frame_parms->ofdm_symbol_size + FILTER_MARGIN],
|
||||
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;
|
||||
uint32_t *noise_power,
|
||||
nr_intf_type_t intf_type) {
|
||||
const int dataF_offset = intf_type == PC5 ? 0 : proc->nr_slot_rx * frame_parms->samples_per_slot_wCP;
|
||||
*noise_power = 0;
|
||||
int maxh = 0;
|
||||
int count = 0;
|
||||
@@ -318,7 +321,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 && intf_type == PC5 ? 0 : csirs_config_pdu->freq_density != (rb % 2)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -386,7 +389,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 && intf_type == PC5 ? 0 : csirs_config_pdu->freq_density != (rb % 2)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -412,7 +415,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 && intf_type == PC5 ? 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 +428,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, intf_type) + calc_power_csirs(noise_imag[ant_rx][port_tx], csirs_config_pdu, intf_type));
|
||||
}
|
||||
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
@@ -463,24 +467,24 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
|
||||
int nr_csi_rs_ri_estimation(const PHY_VARS_NR_UE *ue,
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
|
||||
const nr_csi_info_t *nr_csi_info,
|
||||
const uint8_t N_ports,
|
||||
uint8_t mem_offset,
|
||||
int32_t csi_rs_estimated_channel_freq[][N_ports][ue->frame_parms.ofdm_symbol_size + FILTER_MARGIN],
|
||||
int32_t csi_rs_estimated_channel_freq[][N_ports][frame_parms->ofdm_symbol_size + FILTER_MARGIN],
|
||||
const int16_t log2_maxh,
|
||||
uint8_t *rank_indicator) {
|
||||
|
||||
const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
const int16_t cond_dB_threshold = 5;
|
||||
int count = 0;
|
||||
*rank_indicator = 0;
|
||||
|
||||
if (ue->frame_parms.nb_antennas_rx == 1 || N_ports == 1) {
|
||||
if (frame_parms->nb_antennas_rx == 1 || N_ports == 1) {
|
||||
return 0;
|
||||
} else if( !(ue->frame_parms.nb_antennas_rx == 2 && N_ports == 2) ) {
|
||||
} else if (!(frame_parms->nb_antennas_rx == 2 && N_ports == 2)) {
|
||||
LOG_W(NR_PHY, "Rank indicator computation is not implemented for %i x %i system\n",
|
||||
ue->frame_parms.nb_antennas_rx, N_ports);
|
||||
frame_parms->nb_antennas_rx, N_ports);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -595,20 +599,21 @@ int nr_csi_rs_ri_estimation(const PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
|
||||
int nr_csi_rs_pmi_estimation(const PHY_VARS_NR_UE *ue,
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
|
||||
const nr_csi_info_t *nr_csi_info,
|
||||
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 int32_t csi_rs_estimated_channel_freq[][N_ports][frame_parms->ofdm_symbol_size + FILTER_MARGIN],
|
||||
const uint32_t interference_plus_noise_power,
|
||||
const uint8_t rank_indicator,
|
||||
const int16_t log2_re,
|
||||
uint8_t *i1,
|
||||
uint8_t *i2,
|
||||
uint32_t *precoded_sinr_dB) {
|
||||
uint32_t *precoded_sinr_dB,
|
||||
nr_intf_type_t intf_type) {
|
||||
|
||||
const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
memset(i1,0,3*sizeof(uint8_t));
|
||||
memset(i1, 0, 3 * sizeof(uint8_t));
|
||||
i2[0] = 0;
|
||||
|
||||
// i1 is a three-element vector in the form of [i11 i12 i13], when CodebookType is specified as 'Type1SinglePanel'.
|
||||
@@ -634,7 +639,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 && intf_type == PC5 ? 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 +702,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 NR_DL_FRAME_PARMS *frame_parms,
|
||||
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][frame_parms->ofdm_symbol_size + FILTER_MARGIN],
|
||||
const uint32_t interference_plus_noise_power,
|
||||
const int16_t log2_re,
|
||||
int32_t *precoded_sinr_dB,
|
||||
nr_intf_type_t intf_type) {
|
||||
|
||||
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 && intf_type == PC5 ? 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 +861,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;
|
||||
@@ -834,15 +926,15 @@ int nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t r
|
||||
return 0;
|
||||
}
|
||||
|
||||
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])
|
||||
void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, NR_DL_FRAME_PARMS *frame_parms, UE_nr_rxtx_proc_t *proc, c16_t rxdataF[][frame_parms->samples_per_slot_wCP], nr_intf_type_t intf_type)
|
||||
{
|
||||
|
||||
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 = intf_type == PC5 ? ue->Mod_id : 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);
|
||||
@@ -866,7 +958,6 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t
|
||||
return;
|
||||
}
|
||||
|
||||
const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
int32_t csi_rs_received_signal[frame_parms->nb_antennas_rx][frame_parms->samples_per_slot_wCP];
|
||||
uint8_t N_cdm_groups = 0;
|
||||
uint8_t CDM_group_size = 0;
|
||||
@@ -883,13 +974,21 @@ 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 = (intf_type == PC5) ? (uint16_t)(AMP * (ceil(sqrt(num_of_layers / frame_parms->nb_antennas_tx)))) & 0xFFFF : AMP;
|
||||
if (intf_type == PC5)
|
||||
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,
|
||||
@@ -900,7 +999,8 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t
|
||||
&N_ports,
|
||||
j_cdm,
|
||||
k_overline,
|
||||
l_overline);
|
||||
l_overline,
|
||||
intf_type);
|
||||
|
||||
int32_t csi_rs_ls_estimated_channel[frame_parms->nb_antennas_rx][N_ports][frame_parms->ofdm_symbol_size];
|
||||
int32_t csi_rs_estimated_channel_freq[frame_parms->nb_antennas_rx][N_ports][frame_parms->ofdm_symbol_size + FILTER_MARGIN];
|
||||
@@ -911,6 +1011,7 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t
|
||||
uint8_t mem_offset = (((32 - ((long)&csi_rs_estimated_channel_freq[0][0][frame_parms->first_carrier_offset])) & 0x1F) >> 2);
|
||||
|
||||
nr_get_csi_rs_signal(ue,
|
||||
frame_parms,
|
||||
proc,
|
||||
csirs_config_pdu,
|
||||
ue->nr_csi_info,
|
||||
@@ -924,12 +1025,14 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t
|
||||
csi_rs_received_signal,
|
||||
&rsrp,
|
||||
&rsrp_dBm,
|
||||
rxdataF);
|
||||
rxdataF,
|
||||
intf_type);
|
||||
|
||||
|
||||
// if we need to measure only RSRP no need to do channel estimation
|
||||
if (csirs_config_pdu->measurement_bitmap > 1)
|
||||
nr_csi_rs_channel_estimation(ue,
|
||||
frame_parms,
|
||||
proc,
|
||||
csirs_config_pdu,
|
||||
ue->nr_csi_info,
|
||||
@@ -948,11 +1051,13 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t
|
||||
csi_rs_estimated_channel_freq,
|
||||
&log2_re,
|
||||
&log2_maxh,
|
||||
&noise_power);
|
||||
&noise_power,
|
||||
intf_type);
|
||||
|
||||
// bit 1 in bitmap to indicate RI measurment
|
||||
if (csirs_config_pdu->measurement_bitmap & 2) {
|
||||
nr_csi_rs_ri_estimation(ue,
|
||||
frame_parms,
|
||||
csirs_config_pdu,
|
||||
ue->nr_csi_info,
|
||||
N_ports,
|
||||
@@ -964,22 +1069,47 @@ 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,
|
||||
frame_parms,
|
||||
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,
|
||||
intf_type);
|
||||
else
|
||||
nr_csi_rs_sinr_estimation(ue,
|
||||
frame_parms,
|
||||
csirs_config_pdu,
|
||||
N_ports,
|
||||
mem_offset,
|
||||
csi_rs_estimated_channel_freq,
|
||||
noise_power,
|
||||
log2_re,
|
||||
&sl_sinr_dB,
|
||||
intf_type);
|
||||
|
||||
// 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 (intf_type == PC5) {
|
||||
nr_csi_rs_cqi_estimation_sl(sl_sinr_dB, &cqi);
|
||||
get_nrUE_params()->snr = sl_sinr_dB;
|
||||
LOG_D(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_D(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 +1121,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;
|
||||
|
||||
@@ -664,21 +671,24 @@ void nr_pdcch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms,
|
||||
}
|
||||
|
||||
int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
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,
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
|
||||
|
||||
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
c16_t rxdataF[][frame_parms->samples_per_slot_wCP]) {
|
||||
|
||||
uint8_t log2_maxh, aarx;
|
||||
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,12 +703,12 @@ 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,
|
||||
nr_pdcch_extract_rbs_single(frame_parms->samples_per_slot_wCP,
|
||||
rxdataF,
|
||||
pdcch_est_size,
|
||||
pdcch_dl_ch_estimates,
|
||||
@@ -707,10 +717,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 +786,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,
|
||||
@@ -795,38 +810,6 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
|
||||
|
||||
|
||||
void nr_pdcch_unscrambling(int16_t *e_rx,
|
||||
uint16_t scrambling_RNTI,
|
||||
uint32_t length,
|
||||
uint16_t pdcch_DMRS_scrambling_id,
|
||||
int16_t *z2) {
|
||||
int i;
|
||||
uint8_t reset;
|
||||
uint32_t x1 = 0, x2 = 0, s = 0;
|
||||
uint16_t n_id; //{0,1,...,65535}
|
||||
uint32_t rnti = (uint32_t) scrambling_RNTI;
|
||||
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
|
||||
|
||||
LOG_D(PHY,"PDCCH Unscrambling x2 %x : scrambling_RNTI %x\n", x2, rnti);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if ((i & 0x1f) == 0) {
|
||||
s = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
}
|
||||
|
||||
if (((s >> (i % 32)) & 1) == 1)
|
||||
z2[i] = -e_rx[i];
|
||||
else
|
||||
z2[i]=e_rx[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* This function compares the received DCI bits with
|
||||
* re-encoded DCI bits and returns the number of mismatched bits
|
||||
*/
|
||||
@@ -840,7 +823,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 +843,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 +869,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 +887,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 +961,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_sl;
|
||||
|
||||
#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_sl[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_sl[ar]))[2*n]);
|
||||
im = ((double)(((short *)UE->common_vars.rxdata_sl[ar]))[2*n+1]);
|
||||
((short *)UE->common_vars.rxdata_sl[ar])[2 * n] = (short)(round(re * cos(n * off_angle) - im * sin(n * off_angle)));
|
||||
((short *)UE->common_vars.rxdata_sl[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(UE, 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
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
266
openair1/PHY/NR_UE_TRANSPORT/nr_pscch_pssch_rx.c
Normal file
266
openair1/PHY/NR_UE_TRANSPORT/nr_pscch_pssch_rx.c
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
* 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 "NR_IF_Module.h"
|
||||
#include "openair1/SCHED_NR_UE/defs.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
|
||||
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_pdcch_unscrambling(int16_t *e_rx,
|
||||
uint16_t scrambling_RNTI,
|
||||
uint32_t length,
|
||||
uint16_t pdcch_DMRS_scrambling_id,
|
||||
int16_t *z2,
|
||||
int sci_flag) {
|
||||
int i;
|
||||
uint8_t reset;
|
||||
uint32_t x1 = 0, x2 = 0, s = 0;
|
||||
uint16_t n_id; //{0,1,...,65535}
|
||||
uint32_t rnti = (uint32_t) scrambling_RNTI;
|
||||
reset = 1;
|
||||
// x1 is set in first call to lte_gold_generic
|
||||
n_id = pdcch_DMRS_scrambling_id;
|
||||
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);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if ((i & 0x1f) == 0) {
|
||||
s = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
}
|
||||
|
||||
if (((s >> (i % 32)) & 1) == 1)
|
||||
z2[i] = -e_rx[i];
|
||||
else
|
||||
z2[i]=e_rx[i];
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
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 %d: Setting ACK for SFN/SF %d.%d (pid %d, ndi %d, status %d, round %d, TBS %d, Max interation "
|
||||
"(all seg) %d)\n",
|
||||
rdata->ulsch_id,
|
||||
proc->frame_rx,
|
||||
proc->nr_slot_rx,
|
||||
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, subchannel_size %d, "
|
||||
"TBS %d) r %d\n",
|
||||
rdata->ulsch_id,
|
||||
proc->frame_rx,
|
||||
proc->nr_slot_rx,
|
||||
rdata->harq_pid,
|
||||
slsch_pdu->ndi,
|
||||
slsch->active,
|
||||
slsch_harq->round,
|
||||
slsch_harq->slsch_pdu ? slsch_harq->slsch_pdu->rv_index : slsch_harq->ulsch_pdu.pusch_data.rv_index,
|
||||
slsch_harq->pssch_pdu->startrb,
|
||||
slsch_harq->pssch_pdu->subchannel_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);
|
||||
#ifdef DEBUG_SLSCH
|
||||
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);
|
||||
|
||||
}
|
||||
#endif
|
||||
slsch->last_iteration_cnt = rdata->decodeIterations;
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,0);
|
||||
}
|
||||
}
|
||||
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, PC5);
|
||||
}
|
||||
@@ -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,
|
||||
const sl_nr_tx_config_pscch_pssch_pdu_t *pscch_pssch_pdu,
|
||||
NR_DL_FRAME_PARMS* frame_parms,
|
||||
uint8_t harq_pid,
|
||||
unsigned int G);
|
||||
@@ -243,7 +247,8 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
const uint8_t slot,
|
||||
const int gNB_id,
|
||||
nr_phy_data_tx_t *phy_data,
|
||||
c16_t **txdataF);
|
||||
c16_t **txdataF,
|
||||
nr_intf_type_t intf_type);
|
||||
|
||||
/** \brief This function does IFFT for PUSCH
|
||||
*/
|
||||
@@ -252,7 +257,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);
|
||||
|
||||
@@ -263,12 +268,14 @@ void nr_dlsch_unscrambling(int16_t* llr,
|
||||
uint32_t n_RNTI);
|
||||
|
||||
int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
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,
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
c16_t rxdataF[][frame_parms->samples_per_slot_wCP]);
|
||||
|
||||
|
||||
/*! \brief Performs detection of SSS to find cell ID and other framing parameters (FDD/TDD, normal/extended prefix)
|
||||
@@ -362,13 +369,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 +419,59 @@ 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 NR_DL_FRAME_PARMS *frame_parms,
|
||||
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][frame_parms->ofdm_symbol_size + FILTER_MARGIN],
|
||||
const uint32_t interference_plus_noise_power,
|
||||
const int16_t log2_re,
|
||||
int32_t *precoded_sinr_dB,
|
||||
nr_intf_type_t intf_type);
|
||||
/**@}*/
|
||||
#endif
|
||||
|
||||
|
||||
@@ -87,8 +87,6 @@ typedef struct {
|
||||
uint8_t n_DMRS2;
|
||||
/// Number of soft channel bits
|
||||
uint32_t G;
|
||||
// Number of modulated symbols carrying data
|
||||
uint32_t num_of_mod_symbols;
|
||||
// Encoder BG
|
||||
uint8_t BG;
|
||||
// LDPC lifting size
|
||||
|
||||
339
openair1/PHY/NR_UE_TRANSPORT/nr_ue_pucch_rx.c
Normal file
339
openair1/PHY/NR_UE_TRANSPORT/nr_ue_pucch_rx.c
Normal file
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
* 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 = &ue->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
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],
|
||||
PC5); // 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],
|
||||
PC5); // 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,
|
||||
const 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 = pscch_pssch_pdu == NULL ? &ue->ul_harq_processes[harq_pid] : &ue->sl_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"
|
||||
@@ -50,6 +51,7 @@
|
||||
#include <openair2/UTIL/OPT/opt.h>
|
||||
|
||||
//#define DEBUG_PUSCH_MAPPING
|
||||
//#define DEBUG_ULSCH_PROCEDURES
|
||||
//#define DEBUG_MAC_PDU
|
||||
//#define DEBUG_DFT_IDFT
|
||||
|
||||
@@ -93,6 +95,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,76 +157,129 @@ 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,
|
||||
const uint8_t slot,
|
||||
const int gNB_id,
|
||||
nr_phy_data_tx_t *phy_data,
|
||||
c16_t **txdataF)
|
||||
c16_t **txdataF,
|
||||
nr_intf_type_t intf_type)
|
||||
{
|
||||
LOG_D(PHY,"nr_ue_ulsch_procedures hard_id %d %d.%d\n",harq_pid,frame,slot);
|
||||
LOG_D(PHY,"nr_ue_ulsch_procedures hard_id %d %d.%d\n", harq_pid, frame, slot);
|
||||
|
||||
int8_t Wf[2], Wt[2];
|
||||
int l_prime[2], delta;
|
||||
uint8_t nb_dmrs_re_per_rb;
|
||||
int i;
|
||||
int sample_offsetF, N_RE_prime;
|
||||
bool is_csi_rs_slot = phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS;
|
||||
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);
|
||||
|
||||
NR_DL_FRAME_PARMS *frame_parms = &UE->frame_parms;
|
||||
|
||||
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];
|
||||
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;
|
||||
const nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &phy_data->ulsch.pusch_pdu;
|
||||
const sl_nr_tx_config_pscch_pssch_pdu_t *pscch_pssch_pdu = &phy_data->nr_sl_pssch_pscch_pdu;
|
||||
bool is_pc5 = intf_type == PC5;
|
||||
if (is_pc5)
|
||||
AssertFatal(pscch_pssch_pdu != NULL, "pscch_pssch_pdu %p is not properly defined for the SL mode 2 PC5 link\n", &pscch_pssch_pdu);
|
||||
if (!is_pc5)
|
||||
AssertFatal(pusch_pdu != NULL, "pusch_pdu %p is not properly defined for the Non-SL mode 2 PC5 link\n", &pusch_pdu);
|
||||
|
||||
NR_DL_FRAME_PARMS *frame_parms = !is_pc5 ? &UE->frame_parms : &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
phy_data->ulsch.Nid_cell = frame_parms->Nid_cell;
|
||||
int start_symbol = !is_pc5 ? pusch_pdu->start_symbol_index : (1 + pscch_pssch_pdu->pssch_startsym);
|
||||
uint16_t ul_dmrs_symb_pos = !is_pc5 ? pusch_pdu->ul_dmrs_symb_pos : pscch_pssch_pdu->dmrs_symbol_position;
|
||||
uint8_t number_of_symbols = !is_pc5 ? pusch_pdu->nr_of_symbols : pscch_pssch_pdu->pssch_numsym;
|
||||
uint8_t dmrs_type = !is_pc5 ? pusch_pdu->dmrs_config_type : pusch_dmrs_type1;
|
||||
uint16_t start_rb = !is_pc5 ? pusch_pdu->rb_start : pscch_pssch_pdu->startrb;
|
||||
uint16_t nb_rb = !is_pc5 ? pusch_pdu->rb_size : pscch_pssch_pdu->l_subch * pscch_pssch_pdu->subchannel_size;
|
||||
uint8_t Nl = !is_pc5 ? pusch_pdu->nrOfLayers : pscch_pssch_pdu->num_layers;
|
||||
uint8_t mod_order = !is_pc5 ? pusch_pdu->qam_mod_order : pscch_pssch_pdu->mod_order;
|
||||
uint16_t rnti = !is_pc5 ? pusch_pdu->rnti : 0;
|
||||
uint8_t cdm_grps_no_data = !is_pc5 ? pusch_pdu->num_dmrs_cdm_grps_no_data : 1;
|
||||
uint16_t start_sc = frame_parms->first_carrier_offset + (start_rb + (!is_pc5 ? pusch_pdu->bwp_start : 0)) * NR_NB_SC_PER_RB;
|
||||
if (start_sc >= frame_parms->ofdm_symbol_size)
|
||||
start_sc -= frame_parms->ofdm_symbol_size;
|
||||
uint16_t Tpmi = !is_pc5 ? pusch_pdu->Tpmi : 0;
|
||||
|
||||
ulsch_ue->Nid_cell = frame_parms->Nid_cell;
|
||||
|
||||
int first_dmrs_symbol = 0;
|
||||
bool is_first_dmrs_symbol = true;
|
||||
uint16_t number_dmrs_symbols = 0;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
nb_dmrs_re_per_rb = ((dmrs_type == pusch_dmrs_type1) ? 6:4)*cdm_grps_no_data;
|
||||
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);
|
||||
uint8_t 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);
|
||||
// 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;
|
||||
harq_process_ul_ue->num_of_mod_symbols = N_RE_prime*nb_rb;
|
||||
#ifdef DEBUG_ULSCH_PROCEDURES
|
||||
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", !is_pc5 ? "PUSCH" : "PSSCH",
|
||||
rnti, start_rb, nb_rb, mod_order, Nl, Tpmi, !is_pc5 ? pusch_pdu->bwp_start : 0, start_sc, start_symbol, number_of_symbols, cdm_grps_no_data, number_dmrs_symbols, nb_dmrs_re_per_rb);
|
||||
#endif
|
||||
|
||||
/////////////////////////ULSCH coding/////////////////////////
|
||||
///////////
|
||||
int sci2_re = !is_pc5 ? 0 : 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,
|
||||
1,
|
||||
pscch_pssch_pdu->mcs_table);
|
||||
#ifdef DEBUG_ULSCH_PROCEDURES
|
||||
if (is_pc5) LOG_I(NR_PHY,"dmrs_symbol_position %x, pscch_numsym %d\n", pscch_pssch_pdu->dmrs_symbol_position, pscch_pssch_pdu->pscch_numsym);
|
||||
#endif
|
||||
if (is_pc5)
|
||||
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 = (!is_pc5) ? 0 : pscch_pssch_pdu->dmrs_symbol_position & dmrs_pscch_mask[pscch_pssch_pdu->pscch_numsym-2];
|
||||
uint16_t sci1_re = (!is_pc5) ? 0 : pscch_pssch_pdu->pscch_numsym * pscch_pssch_pdu->pscch_numrbs * NR_NB_SC_PER_RB;
|
||||
uint16_t num_CSI_REs = csi_params ? get_nRECSI_RS(csi_params->freq_density, csi_params->nr_of_rbs) : 0;
|
||||
unsigned int G = (!is_pc5) ? 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;
|
||||
NR_UL_UE_HARQ_t *harq_process_ue = (is_pc5) ? &UE->sl_harq_processes[harq_pid] : &UE->ul_harq_processes[harq_pid];
|
||||
trace_NRpdu(DIRECTION_UPLINK,
|
||||
harq_process_ul_ue->a,
|
||||
pusch_pdu->pusch_data.tb_size,
|
||||
harq_process_ue->a,
|
||||
!is_pc5 ? 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)
|
||||
// Note, we check for pscch_pssch_pdu == NULL inside of nr_ulsch_encoding
|
||||
if (nr_ulsch_encoding(UE, &phy_data->ulsch, is_pc5 ? pscch_pssch_pdu : NULL, frame_parms, harq_pid, G) == -1)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
uint32_t sci2_encoded_output[sci2_re*2];
|
||||
|
||||
if (is_pc5) {
|
||||
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);
|
||||
}
|
||||
|
||||
///////////
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@@ -184,44 +288,82 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
///////////
|
||||
|
||||
uint32_t available_bits = G;
|
||||
uint32_t scrambled_output[(available_bits>>5)+1];
|
||||
memset(scrambled_output, 0, ((available_bits>>5)+1)*sizeof(uint32_t));
|
||||
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));
|
||||
if (is_pc5)
|
||||
memset(scrambled_output_sci, 0, ((Gsci2 >> 5) + 1)*sizeof(uint32_t));
|
||||
|
||||
nr_pusch_codeword_scrambling(harq_process_ul_ue->f,
|
||||
available_bits,
|
||||
ulsch_ue->Nid_cell,
|
||||
rnti,
|
||||
#ifdef DEBUG_PUSCH
|
||||
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_ue->f[g]);
|
||||
LOG_I(NR_PHY,"Scrambling with Nid %x\n",phy_data->pscch_Nid);
|
||||
#endif
|
||||
nr_pusch_codeword_scrambling(harq_process_ue->f,
|
||||
G,
|
||||
!is_pc5 ? phy_data->ulsch.Nid_cell : phy_data->pscch_Nid,
|
||||
!is_pc5 ? rnti : 1010,
|
||||
false,
|
||||
scrambled_output);
|
||||
|
||||
if (is_pc5 && Nl == 1)
|
||||
nr_pdcch_scrambling(sci2_encoded_output,
|
||||
Gsci2,
|
||||
phy_data->pscch_Nid,
|
||||
1010,
|
||||
scrambled_output_sci,
|
||||
1);
|
||||
else if (is_pc5)
|
||||
nr_pusch_codeword_scrambling_sci_2layer(sci2_encoded_output,
|
||||
Gsci2,
|
||||
phy_data->pscch_Nid,
|
||||
scrambled_output_sci);
|
||||
/////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////ULSCH modulation/////////////////////////
|
||||
///////////
|
||||
|
||||
int max_num_re = Nl*number_of_symbols*nb_rb*NR_NB_SC_PER_RB;
|
||||
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);
|
||||
#ifdef DEBUG_ULSCH_PROCEDURES
|
||||
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 ]);
|
||||
#endif
|
||||
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 (!is_pc5 && 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 = ((!is_pc5 ? 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,16 +377,12 @@ 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 (!is_pc5 && (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;
|
||||
|
||||
L_ptrs = 1 << pusch_pdu->pusch_ptrs.ptrs_time_density;
|
||||
beta_ptrs = 1; // temp value until power control is implemented
|
||||
|
||||
ulsch_ue->ptrs_symbols = 0;
|
||||
|
||||
set_ptrs_symb_idx(&ulsch_ue->ptrs_symbols,
|
||||
phy_data->ulsch.ptrs_symbols = 0;
|
||||
set_ptrs_symb_idx(&phy_data->ulsch.ptrs_symbols,
|
||||
number_of_symbols,
|
||||
start_symbol,
|
||||
L_ptrs,
|
||||
@@ -259,11 +397,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);
|
||||
|
||||
///////////
|
||||
@@ -273,46 +410,35 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
//////////////////////// ULSCH transform precoding ////////////////////////
|
||||
///////////
|
||||
|
||||
l_prime[0] = 0; // single symbol ap 0
|
||||
|
||||
uint16_t index;
|
||||
uint8_t u = 0, v = 0;
|
||||
int16_t *dmrs_seq = NULL;
|
||||
|
||||
/// 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)));
|
||||
int16_t *dmrs_seq = NULL;
|
||||
|
||||
if (pusch_pdu->transform_precoding == transformPrecoder_enabled) {
|
||||
if (!is_pc5 && (pusch_pdu->transform_precoding == transformPrecoder_enabled)) {
|
||||
|
||||
uint32_t nb_re_pusch=nb_rb * NR_NB_SC_PER_RB;
|
||||
uint32_t y_offset = 0;
|
||||
uint16_t num_dmrs_res_per_symbol = nb_rb*(NR_NB_SC_PER_RB/2);
|
||||
|
||||
// Calculate index to dmrs seq array based on number of DMRS Subcarriers on this symbol
|
||||
index = get_index_for_dmrs_lowpapr_seq(num_dmrs_res_per_symbol);
|
||||
u = pusch_pdu->dfts_ofdm.low_papr_group_number;
|
||||
v = pusch_pdu->dfts_ofdm.low_papr_sequence_number;
|
||||
uint16_t index = get_index_for_dmrs_lowpapr_seq(num_dmrs_res_per_symbol);
|
||||
uint8_t u = pusch_pdu->dfts_ofdm.low_papr_group_number;
|
||||
uint8_t v = pusch_pdu->dfts_ofdm.low_papr_sequence_number;
|
||||
dmrs_seq = dmrs_lowpaprtype1_ul_ref_sig[u][v][index];
|
||||
|
||||
AssertFatal(index >= 0, "Num RBs not configured according to 3GPP 38.211 section 6.3.1.4. For PUSCH with transform precoding, num RBs cannot be multiple of any other primenumber other than 2,3,5\n");
|
||||
AssertFatal(dmrs_seq != NULL, "DMRS low PAPR seq not found, check if DMRS sequences are generated");
|
||||
|
||||
LOG_D(PHY,"Transform Precoding params. u: %d, v: %d, index for dmrsseq: %d\n", u, v, index);
|
||||
|
||||
for (int l = start_symbol; l < start_symbol + number_of_symbols; l++) {
|
||||
|
||||
if((ul_dmrs_symb_pos >> l) & 0x01)
|
||||
/* In the symbol with DMRS no data would be transmitted CDM groups is 2*/
|
||||
continue;
|
||||
|
||||
nr_dft(&y[y_offset], &((int32_t*)tx_layers[0])[y_offset], nb_re_pusch);
|
||||
|
||||
y_offset = y_offset + nb_re_pusch;
|
||||
|
||||
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
|
||||
}
|
||||
@@ -321,11 +447,9 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
int32_t debug_symbols[MAX_NUM_NR_RE] __attribute__ ((aligned(16)));
|
||||
int offset = 0;
|
||||
printf("NR_ULSCH_UE: available_bits: %u, mod_order: %d", available_bits,mod_order);
|
||||
|
||||
for (int ll = 0; ll < (available_bits/mod_order); ll++) {
|
||||
debug_symbols[ll] = ulsch_ue->y[ll];
|
||||
debug_symbols[ll] = phy_data->ulsch.y[ll];
|
||||
}
|
||||
|
||||
printf("NR_ULSCH_UE: numSym: %d, num_dmrs_sym: %d", number_of_symbols,number_dmrs_symbols);
|
||||
for (int ll = 0; ll < (number_of_symbols-number_dmrs_symbols); ll++) {
|
||||
nr_idft(&debug_symbols[offset], nb_re_pusch);
|
||||
@@ -354,40 +478,59 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
|
||||
for (int nl=0; nl < Nl; nl++) {
|
||||
uint8_t k_prime = 0;
|
||||
int l_prime[2];
|
||||
uint16_t m = 0;
|
||||
|
||||
int sample_offsetF;
|
||||
|
||||
#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\n", frame_parms->Nid_cell);
|
||||
#endif
|
||||
|
||||
int dmrs_port = get_dmrs_port(nl,pusch_pdu->dmrs_ports);
|
||||
int dmrs_port = get_dmrs_port(nl, is_pc5 ? nl : pusch_pdu->dmrs_ports);
|
||||
if (dmrs_port < 0) return;
|
||||
// DMRS params for this dmrs port
|
||||
int8_t Wf[2], Wt[2];
|
||||
get_Wt(Wt, dmrs_port, dmrs_type);
|
||||
get_Wf(Wf, dmrs_port, dmrs_type);
|
||||
delta = get_delta(dmrs_port, dmrs_type);
|
||||
int delta = get_delta(dmrs_port, dmrs_type);
|
||||
|
||||
for (int l=start_symbol; l<start_symbol+number_of_symbols; l++) {
|
||||
|
||||
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 (is_pc5 && l < (start_symbol + pscch_pssch_pdu->pscch_numsym)) {
|
||||
is_pscch_sym = 1;
|
||||
}
|
||||
|
||||
if (csi_params && 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 (is_pc5 || (pusch_pdu->transform_precoding == transformPrecoder_disabled)){
|
||||
if (dmrs_type == pusch_dmrs_type1)
|
||||
dmrs_idx = (pusch_pdu->bwp_start + start_rb)*6;
|
||||
dmrs_idx = ((!is_pc5 ? pusch_pdu->bwp_start : 0) + start_rb)*6;
|
||||
else
|
||||
dmrs_idx = (pusch_pdu->bwp_start + start_rb)*4;
|
||||
|
||||
dmrs_idx = ((!is_pc5 ? 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 (!is_pc5)
|
||||
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;
|
||||
}
|
||||
@@ -395,16 +538,27 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
|
||||
AssertFatal(pusch_pdu->transform_precoding == transformPrecoder_disabled, "PTRS NOT SUPPORTED IF TRANSFORM PRECODING IS ENABLED\n");
|
||||
|
||||
if(is_ptrs_symbol(l, ulsch_ue->ptrs_symbols)) {
|
||||
if(is_ptrs_symbol(l, phy_data->ulsch.ptrs_symbols)) {
|
||||
is_ptrs_sym = 1;
|
||||
nr_modulation(pusch_dmrs[l][pusch_pdu->scid], nb_rb, DMRS_MOD_ORDER, mod_ptrs);
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i< nb_rb*NR_NB_SC_PER_RB; i++) {
|
||||
for (int 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 +576,27 @@ 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, intf_type);
|
||||
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) {
|
||||
l_prime[0] = 0; // single symbol ap 0
|
||||
if (!is_pc5 && 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 +605,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 +620,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 (is_pc5 || 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 +635,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;
|
||||
@@ -472,9 +650,9 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
|
||||
if (++k >= frame_parms->ofdm_symbol_size)
|
||||
k -= frame_parms->ofdm_symbol_size;
|
||||
} //for (i=0; i< nb_rb*NR_NB_SC_PER_RB; i++)
|
||||
}//for (l=start_symbol; l<start_symbol+number_of_symbols; l++)
|
||||
}//for (nl=0; nl < Nl; nl++)
|
||||
} //for (int i = 0; i < nb_rb*NR_NB_SC_PER_RB; i++)
|
||||
} //for (l = start_symbol; l < start_symbol + number_of_symbols; l++)
|
||||
} //for (nl = 0; nl < Nl; nl++)
|
||||
|
||||
|
||||
|
||||
@@ -489,14 +667,24 @@ 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 (is_pc5 && 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 +695,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 +724,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];
|
||||
@@ -557,9 +745,9 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i=0; i<NR_NB_SC_PER_RB; i++) {
|
||||
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];
|
||||
|
||||
@@ -568,13 +756,11 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
}
|
||||
}
|
||||
}
|
||||
} //RB loop
|
||||
} // RB loop
|
||||
} // symbol loop
|
||||
}// port 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_ue->status = SCH_IDLE;
|
||||
|
||||
for (int nl = 0; nl < Nl; nl++) {
|
||||
free_and_zero(tx_layers[nl]);
|
||||
@@ -591,15 +777,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;
|
||||
c16_t **txdata = (linktype != link_type_pc5) ? UE->common_vars.txData : UE->common_vars.txDataSl;
|
||||
|
||||
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,
|
||||
|
||||
@@ -65,6 +65,7 @@ int16_t *get_primary_synchro_nr2(const int nid2)
|
||||
*
|
||||
* PARAMETERS : N_ID_2 : element 2 of physical layer cell identity
|
||||
* value : { 0, 1, 2}
|
||||
* intf_type : { UU, PC5}
|
||||
*
|
||||
* RETURN : generate binary pss sequence (this is a m-sequence)
|
||||
*
|
||||
@@ -73,7 +74,7 @@ int16_t *get_primary_synchro_nr2(const int nid2)
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
void generate_pss_nr(NR_DL_FRAME_PARMS *fp, int N_ID_2)
|
||||
void generate_pss_nr(NR_DL_FRAME_PARMS *fp, int N_ID_2, nr_intf_type_t intf_type)
|
||||
{
|
||||
AssertFatal(fp->ofdm_symbol_size > 127,"Illegal ofdm_symbol_size %d\n",fp->ofdm_symbol_size);
|
||||
AssertFatal(N_ID_2>=0 && N_ID_2 <=2,"Illegal N_ID_2 %d\n",N_ID_2);
|
||||
@@ -138,7 +139,7 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp, int N_ID_2)
|
||||
* sample 0 is for continuous frequency which is used here
|
||||
*/
|
||||
|
||||
unsigned int subcarrier_start = get_softmodem_params()->sl_mode == 0 ? PSS_SSS_SUB_CARRIER_START : PSS_SSS_SUB_CARRIER_START_SL;
|
||||
unsigned int subcarrier_start = (intf_type == UU) ? PSS_SSS_SUB_CARRIER_START : PSS_SSS_SUB_CARRIER_START_SL;
|
||||
unsigned int k = fp->first_carrier_offset + fp->ssb_start_subcarrier + subcarrier_start;
|
||||
if (k>= fp->ofdm_symbol_size) k-=fp->ofdm_symbol_size;
|
||||
c16_t synchroF_tmp[fp->ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
@@ -234,16 +235,16 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp, int N_ID_2)
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
static void init_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue)
|
||||
static void init_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue, nr_intf_type_t intf_type)
|
||||
{
|
||||
AssertFatal(frame_parms_ue->ofdm_symbol_size > 127, "illegal ofdm_symbol_size %d\n", frame_parms_ue->ofdm_symbol_size);
|
||||
int pss_sequence = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL;
|
||||
int pss_sequence = (intf_type == UU) ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL;
|
||||
for (int i = 0; i < pss_sequence; i++) {
|
||||
primary_synchro_nr2[i] = malloc16_clear(LENGTH_PSS_NR * sizeof(int16_t));
|
||||
AssertFatal(primary_synchro_nr2[i], "Fatal memory allocation problem \n");
|
||||
primary_synchro_time_nr[i] = malloc16_clear(frame_parms_ue->ofdm_symbol_size * sizeof(c16_t));
|
||||
AssertFatal(primary_synchro_time_nr[i], "Fatal memory allocation problem \n");
|
||||
generate_pss_nr(frame_parms_ue,i);
|
||||
generate_pss_nr(frame_parms_ue, i, intf_type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,7 +272,7 @@ static void free_context_pss_nr(void)
|
||||
*
|
||||
* NAME : init_context_synchro_nr
|
||||
*
|
||||
* PARAMETERS : none
|
||||
* PARAMETERS : configuration for UE, nr interface type
|
||||
*
|
||||
* RETURN : generate context for pss and sss
|
||||
*
|
||||
@@ -279,11 +280,11 @@ static void free_context_pss_nr(void)
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
void init_context_synchro_nr(NR_DL_FRAME_PARMS *frame_parms_ue)
|
||||
void init_context_synchro_nr(NR_DL_FRAME_PARMS *frame_parms_ue, nr_intf_type_t intf_type)
|
||||
{
|
||||
/* initialise global buffers for synchronisation */
|
||||
init_context_pss_nr(frame_parms_ue);
|
||||
init_context_sss_nr(AMP);
|
||||
init_context_pss_nr(frame_parms_ue, intf_type);
|
||||
init_context_sss_nr(AMP, intf_type);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@@ -324,7 +325,7 @@ void set_frame_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue, int rate_change
|
||||
free_context_pss_nr();
|
||||
|
||||
/* pss reference have to be rebuild with new parameters ie ofdm symbol size */
|
||||
init_context_synchro_nr(frame_parms_ue);
|
||||
init_context_synchro_nr(frame_parms_ue, UU);
|
||||
|
||||
#ifdef SYNCHRO_DECIMAT
|
||||
set_pss_nr(frame_parms_ue->ofdm_symbol_size);
|
||||
@@ -351,7 +352,7 @@ void restore_frame_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue, int rate_ch
|
||||
free_context_pss_nr();
|
||||
|
||||
/* pss reference have to be rebuild with new parameters ie ofdm symbol size */
|
||||
init_context_synchro_nr(frame_parms_ue);
|
||||
init_context_synchro_nr(frame_parms_ue, UU);
|
||||
#ifdef SYNCHRO_DECIMAT
|
||||
set_pss_nr(frame_parms_ue->ofdm_symbol_size);
|
||||
#endif
|
||||
@@ -584,7 +585,7 @@ static int pss_search_time_nr(c16_t **rxdata, PHY_VARS_NR_UE *ue, int fo_flag, i
|
||||
pss_source = 0;
|
||||
|
||||
int maxval=0;
|
||||
int max_size = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL;
|
||||
int max_size = NUMBER_PSS_SEQUENCE;
|
||||
for (int j = 0; j < max_size; j++)
|
||||
for (int i = 0; i < frame_parms->ofdm_symbol_size; i++) {
|
||||
maxval = max(maxval, abs(primary_synchro_time_nr[j][i].r));
|
||||
@@ -597,7 +598,7 @@ static int pss_search_time_nr(c16_t **rxdata, PHY_VARS_NR_UE *ue, int fo_flag, i
|
||||
/* Correlation computation is based on a a dot product which is realized thank to SIMS extensions */
|
||||
|
||||
uint16_t pss_index_start = 0;
|
||||
uint16_t pss_index_end = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL;
|
||||
uint16_t pss_index_end = NUMBER_PSS_SEQUENCE;
|
||||
if (ue->target_Nid_cell != -1) {
|
||||
pss_index_start = GET_NID2(ue->target_Nid_cell);
|
||||
pss_index_end = pss_index_start + 1;
|
||||
|
||||
@@ -56,17 +56,18 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
const int16_t amp,
|
||||
const int nr_slot_tx,
|
||||
const fapi_nr_ul_config_pucch_pdu *pucch_pdu)
|
||||
const fapi_nr_ul_config_pucch_pdu *pucch_pdu,
|
||||
nr_intf_type_t intf_type)
|
||||
{
|
||||
#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 +92,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,20 +113,20 @@ 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], intf_type); // 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], intf_type); // 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++) {
|
||||
alpha = nr_cyclic_shift_hopping(pucch_pdu->hopping_id,
|
||||
pucch_pdu->initial_cyclic_shift,
|
||||
pucch_pdu->mcs,l,
|
||||
pucch_pdu->mcs, intf_type == PC5 ? 0 : l,
|
||||
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 +135,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 +149,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 +166,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -287,7 +296,7 @@ void nr_generate_pucch1(const PHY_VARS_NR_UE *ue,
|
||||
n_hop,nr_slot_tx);
|
||||
#endif
|
||||
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,n_hop,nr_slot_tx,&u,&v); // calculating u and v value
|
||||
nr_group_sequence_hopping(pucch_GroupHopping, pucch_pdu->hopping_id, n_hop,nr_slot_tx, &u, &v, UU); // calculating u and v value
|
||||
// mcs = 0 except for PUCCH format 0
|
||||
int mcs = 0;
|
||||
double alpha = nr_cyclic_shift_hopping(pucch_pdu->hopping_id, m0, mcs, l, lprime, nr_slot_tx);
|
||||
@@ -645,7 +654,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);
|
||||
@@ -1197,7 +1206,7 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
|
||||
if ((intraSlotFrequencyHopping == 1) && (l >= (int)floor(nrofSymbols/2))) n_hop = 1; // n_hop = 1 for second hop
|
||||
|
||||
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,n_hop,nr_slot_tx,&u,&v); // calculating u and v value
|
||||
nr_group_sequence_hopping(pucch_GroupHopping, pucch_pdu->hopping_id, n_hop, nr_slot_tx, &u, &v, UU); // calculating u and v value
|
||||
|
||||
// Next we proceed to calculate base sequence for DM-RS signal, according to TS 38.211 subclause 6.4.1.33
|
||||
if (nrofPRB >= 3) { // TS 38.211 subclause 5.2.2.1 (Base sequences of length 36 or larger) applies
|
||||
|
||||
@@ -49,7 +49,8 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
const int16_t amp,
|
||||
const int nr_slot_tx,
|
||||
const fapi_nr_ul_config_pucch_pdu *pucch_pdu);
|
||||
const fapi_nr_ul_config_pucch_pdu *pucch_pdu,
|
||||
nr_intf_type_t intf_type);
|
||||
|
||||
void nr_generate_pucch1(const PHY_VARS_NR_UE *ue,
|
||||
c16_t **txdataF,
|
||||
|
||||
@@ -72,13 +72,13 @@ static const int16_t phase_im_nr[PHASE_HYPOTHESIS_NUMBER] // -pi/3 ---- pi/3
|
||||
|
||||
static int16_t d_sss[N_ID_2_NUMBER][N_ID_1_NUMBER][LENGTH_SSS_NR];
|
||||
|
||||
void init_context_sss_nr(int amp)
|
||||
void init_context_sss_nr(int amp, nr_intf_type_t intf_type)
|
||||
{
|
||||
int16_t x0[LENGTH_SSS_NR];
|
||||
int16_t x1[LENGTH_SSS_NR];
|
||||
int16_t dss_current;
|
||||
int m0, m1;
|
||||
int nid_2_num = get_softmodem_params()->sl_mode == 0 ? N_ID_2_NUMBER : N_ID_2_NUMBER_SL;
|
||||
int nid_2_num = (intf_type == UU) ? N_ID_2_NUMBER : N_ID_2_NUMBER_SL;
|
||||
|
||||
const int x0_initial[INITIAL_SSS_NR] = { 1, 0, 0, 0, 0, 0, 0 };
|
||||
const int x1_initial[INITIAL_SSS_NR] = { 1, 0, 0, 0, 0, 0, 0 };
|
||||
@@ -270,9 +270,7 @@ static int do_pss_sss_extract_nr(
|
||||
|
||||
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
|
||||
int pss_symbol = 0;
|
||||
int sss_symbol = get_softmodem_params()->sl_mode == 0 ?
|
||||
(SSS_SYMBOL_NB - PSS_SYMBOL_NB) :
|
||||
(SSS0_SL_SYMBOL_NB - PSS0_SL_SYMBOL_NB) ;
|
||||
int sss_symbol = SSS_SYMBOL_NB - PSS_SYMBOL_NB;
|
||||
unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size;
|
||||
|
||||
c16_t *pss_rxF = rxdataF[aarx] + pss_symbol * ofdm_symbol_size;
|
||||
@@ -283,9 +281,7 @@ static int do_pss_sss_extract_nr(
|
||||
|
||||
unsigned int k = frame_parms->first_carrier_offset +
|
||||
frame_parms->ssb_start_subcarrier +
|
||||
((get_softmodem_params()->sl_mode == 0) ?
|
||||
PSS_SSS_SUB_CARRIER_START :
|
||||
PSS_SSS_SUB_CARRIER_START_SL);
|
||||
PSS_SSS_SUB_CARRIER_START;
|
||||
|
||||
if (k>= frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size;
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -222,12 +235,14 @@ typedef struct {
|
||||
/// - first index: tx antenna [0..nb_antennas_tx[
|
||||
/// - second index: sample [0..FRAME_LENGTH_COMPLEX_SAMPLES[
|
||||
c16_t **txData;
|
||||
c16_t **txDataSl;
|
||||
|
||||
/// \brief Holds the received data in time domain.
|
||||
/// Should point to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER.
|
||||
/// - first index: rx antenna [0..nb_antennas_rx[
|
||||
/// - second index: sample [0..2*FRAME_LENGTH_COMPLEX_SAMPLES+2048[
|
||||
c16_t **rxdata;
|
||||
c16_t **rxdata_sl;
|
||||
|
||||
/// estimated frequency offset (in radians) for all subcarriers
|
||||
int32_t freq_offset;
|
||||
@@ -309,7 +324,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,13 +377,15 @@ 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
|
||||
uint8_t CC_id;
|
||||
/// \brief Mapping of CC_id antennas to cards
|
||||
openair0_rf_map rf_map;
|
||||
/// \brief Mapping of Sidelink CC_id antennas to cards
|
||||
openair0_rf_map rf_map_sl;
|
||||
/// \brief Indicator that UE should perform band scanning
|
||||
int UE_scan;
|
||||
/// \brief Indicator that UE should perform coarse scanning around carrier
|
||||
@@ -435,7 +452,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;
|
||||
@@ -524,12 +541,15 @@ typedef struct {
|
||||
int rx_offset_diff; /// Timing adjustment for ofdm symbol0 on HW USRP
|
||||
int64_t max_pos_fil; /// Timing offset IIR filter
|
||||
bool apply_timing_offset; /// Do time sync for current frame
|
||||
bool apply_timing_offset_sl; /// Do time sync for current frame
|
||||
int time_sync_cell;
|
||||
|
||||
/// Timing Advance updates variables
|
||||
/// Timing advance update computed from the TA command signalled from gNB
|
||||
int timing_advance;
|
||||
int N_TA_offset; ///timing offset used in TDD
|
||||
int timing_advance_sl;
|
||||
int N_TA_offset_sl; ///timing offset used in TDD
|
||||
int ta_frame;
|
||||
int ta_slot;
|
||||
int ta_command;
|
||||
@@ -629,6 +649,7 @@ typedef struct {
|
||||
|
||||
/// RF and Interface devices per CC
|
||||
openair0_device rfdevice;
|
||||
openair0_device rfdevice_sl;
|
||||
|
||||
#if ENABLE_RAL
|
||||
hash_table_t *ral_thresholds_timed;
|
||||
@@ -649,6 +670,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 +710,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
|
||||
@@ -686,6 +742,7 @@ typedef struct nr_rxtx_thread_data_s {
|
||||
notifiedFIFO_t txFifo;
|
||||
nr_phy_data_t phy_data;
|
||||
int tx_wait_for_dlsch;
|
||||
nr_intf_type_t intf_type;
|
||||
} nr_rxtx_thread_data_t;
|
||||
|
||||
typedef struct LDPCDecode_ue_s {
|
||||
|
||||
@@ -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,14 +98,16 @@ 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 */
|
||||
|
||||
enum nr_Link {
|
||||
typedef enum {
|
||||
link_type_dl,
|
||||
link_type_ul,
|
||||
link_type_sl,
|
||||
};
|
||||
link_type_pc5,
|
||||
} nr_link_type_t;
|
||||
|
||||
typedef enum {
|
||||
ms0p5 = 500, /* duration is given in microsecond */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user