mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
Compare commits
531 Commits
RTT_based_
...
sl-eurecom
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
149034887c | ||
|
|
5917f0f2b8 | ||
|
|
6832959b0b | ||
|
|
e7b42f419b | ||
|
|
d629498b98 | ||
|
|
1c01343d49 | ||
|
|
f633fc8d96 | ||
|
|
5e28985954 | ||
|
|
af662183f4 | ||
|
|
efccb416cc | ||
|
|
4232baec52 | ||
|
|
2f19c2de4d | ||
|
|
b17e862742 | ||
|
|
d680bb83b2 | ||
|
|
50923c7f80 | ||
|
|
90e5db3728 | ||
|
|
c9bc86312f | ||
|
|
7221a5f736 | ||
|
|
629b2c9fe3 | ||
|
|
9f91dbd9bb | ||
|
|
a354ce01cf | ||
|
|
93d32eca45 | ||
|
|
053d8d938f | ||
|
|
cf4a22b58a | ||
|
|
75e9db0633 | ||
|
|
24bf0d8046 | ||
|
|
d8627c91f3 | ||
|
|
ad8da84671 | ||
|
|
f0f1121e9c | ||
|
|
9b8eae2256 | ||
|
|
e9e347043e | ||
|
|
28741ed967 | ||
|
|
608aa3ebc4 | ||
|
|
a6e18fe06a | ||
|
|
aa6468f95e | ||
|
|
f09fffdb2b | ||
|
|
376a9beb80 | ||
|
|
0b892acef3 | ||
|
|
73907e5ee2 | ||
|
|
703047eca9 | ||
|
|
5cbad19d19 | ||
|
|
d1e1f56199 | ||
|
|
61435e9066 | ||
|
|
ee8af9dcfb | ||
|
|
b7f47aa70a | ||
|
|
066de7c3c5 | ||
|
|
fec2a15bdf | ||
|
|
8cbe4bb1d1 | ||
|
|
a54ca2c6e3 | ||
|
|
e79756d7ab | ||
|
|
39b73391d4 | ||
|
|
784be9d241 | ||
|
|
5d378b6416 | ||
|
|
b6e5b3594c | ||
|
|
f79ab7e087 | ||
|
|
c6c004b8aa | ||
|
|
2b193cded0 | ||
|
|
a07d4376d6 | ||
|
|
2f23bf1ea4 | ||
|
|
d8e92e93b3 | ||
|
|
6db9c37e47 | ||
|
|
f596c6907a | ||
|
|
d22d11d003 | ||
|
|
8bf5a0acf6 | ||
|
|
95fc447472 | ||
|
|
5a61145948 | ||
|
|
751f06b15e | ||
|
|
98d5c1691c | ||
|
|
678e3f9a01 | ||
|
|
ec1d5ead6a | ||
|
|
7cbfbd6c92 | ||
|
|
9338925b93 | ||
|
|
64b65cb5d9 | ||
|
|
7b2d0dbf39 | ||
|
|
ac4c4defd3 | ||
|
|
816532d86c | ||
|
|
a96d727409 | ||
|
|
624fc5353e | ||
|
|
d609f3f5ae | ||
|
|
bb525dc0ee | ||
|
|
1f432be612 | ||
|
|
b47cb76977 | ||
|
|
528e1d99d2 | ||
|
|
aba645dc93 | ||
|
|
468e7330de | ||
|
|
e7d04ec14f | ||
|
|
600399aa63 | ||
|
|
56b87424db | ||
|
|
7a1928dfd0 | ||
|
|
6c8112581b | ||
|
|
7e473ca971 | ||
|
|
7f40b90ceb | ||
|
|
7feb6ed41f | ||
|
|
6fbb4df0a3 | ||
|
|
89f11abe68 | ||
|
|
3362fa991f | ||
|
|
3614c221c4 | ||
|
|
298d822bd1 | ||
|
|
6775b577fd | ||
|
|
1283065946 | ||
|
|
50f4890faa | ||
|
|
03b75ed679 | ||
|
|
a91839e69c | ||
|
|
2e34ab0190 | ||
|
|
e6abb12fb1 | ||
|
|
a93da4a886 | ||
|
|
27e14a06c2 | ||
|
|
028f92a3e2 | ||
|
|
bf6b8442f1 | ||
|
|
0f90a7c24c | ||
|
|
0e84775e29 | ||
|
|
0e0fc7eab4 | ||
|
|
323f52aeb1 | ||
|
|
334fbb8879 | ||
|
|
39d54215bd | ||
|
|
bb580fae58 | ||
|
|
783e3d0da6 | ||
|
|
3fc1825e44 | ||
|
|
c0bf78efa0 | ||
|
|
c4f4a5d793 | ||
|
|
b6247b075b | ||
|
|
cfdfe6aaa7 | ||
|
|
709efd5da5 | ||
|
|
d9e487359d | ||
|
|
500069fcf0 | ||
|
|
99fb046474 | ||
|
|
c8ace3b540 | ||
|
|
6fc62b0184 | ||
|
|
085e84dc38 | ||
|
|
b1407040b6 | ||
|
|
88accf144e | ||
|
|
a7c5a0bb29 | ||
|
|
2949d00083 | ||
|
|
8378127c2c | ||
|
|
e1d9d15b2c | ||
|
|
53eb37e674 | ||
|
|
682b1be022 | ||
|
|
f4047b7aa4 | ||
|
|
34d80d4754 | ||
|
|
5dc3663f16 | ||
|
|
de54ec5b8b | ||
|
|
ce07b567d0 | ||
|
|
4ee9a6d8c6 | ||
|
|
39726e3274 | ||
|
|
0d5dcbbccb | ||
|
|
684f762fd9 | ||
|
|
b95722b670 | ||
|
|
b431e042fc | ||
|
|
43e8dcd7b6 | ||
|
|
5ea2e6d029 | ||
|
|
7cdf6847f1 | ||
|
|
1483d53e28 | ||
|
|
8727d12d18 | ||
|
|
6f6a314ab6 | ||
|
|
77f069c1af | ||
|
|
6a2f5664b8 | ||
|
|
6d51179357 | ||
|
|
720b2669fd | ||
|
|
9ffe2b7851 | ||
|
|
6befa6b3b0 | ||
|
|
d497806c6c | ||
|
|
475f99195e | ||
|
|
e1c152fbcf | ||
|
|
0db28d4f5a | ||
|
|
e344d531f9 | ||
|
|
433f3d1507 | ||
|
|
7e7b00e58b | ||
|
|
9b03282972 | ||
|
|
b5a2dab4e9 | ||
|
|
0f22e2a2d8 | ||
|
|
9fe8a273f2 | ||
|
|
e95d6e28fc | ||
|
|
71f52d180f | ||
|
|
0c048b28bd | ||
|
|
0a38dbb7be | ||
|
|
40a2ee85aa | ||
|
|
c61ab7fb7e | ||
|
|
9591a5bef5 | ||
|
|
f95c3f92ed | ||
|
|
0a6e7eb898 | ||
|
|
26a52906df | ||
|
|
0f8bb964a4 | ||
|
|
937c7119ae | ||
|
|
3e028a43b5 | ||
|
|
c501e448ca | ||
|
|
8313896093 | ||
|
|
87436a1884 | ||
|
|
34d508ae23 | ||
|
|
ffb6ca5934 | ||
|
|
682721cf57 | ||
|
|
1a627782dd | ||
|
|
28688065e2 | ||
|
|
21b766912b | ||
|
|
774b8ef6e9 | ||
|
|
aefe918f9f | ||
|
|
1dbe99316a | ||
|
|
b0ca489e60 | ||
|
|
5d270d63ac | ||
|
|
22063a35ec | ||
|
|
d39997d8b0 | ||
|
|
74998221e8 | ||
|
|
c468bd519b | ||
|
|
385243f521 | ||
|
|
0453ef25dd | ||
|
|
a909589185 | ||
|
|
064b05aee8 | ||
|
|
4f34b5f97a | ||
|
|
9c2c8067ef | ||
|
|
ca86a8a5ac | ||
|
|
4708a7d81c | ||
|
|
1d730cd8e2 | ||
|
|
e20bd2edaa | ||
|
|
fc236e4bd3 | ||
|
|
2ebef66785 | ||
|
|
4cd71874c0 | ||
|
|
c19ffff075 | ||
|
|
1c50671296 | ||
|
|
611c98f6f1 | ||
|
|
a66d7fcafc | ||
|
|
c6a972f65e | ||
|
|
28290c792d | ||
|
|
aa2e0319d0 | ||
|
|
0cce63fae9 | ||
|
|
f4bd344b9b | ||
|
|
565f6e13b0 | ||
|
|
30e6cc01c6 | ||
|
|
f9f8e21b55 | ||
|
|
bb1699e4d6 | ||
|
|
853f2737a4 | ||
|
|
7f3242a2b4 | ||
|
|
f2e678375b | ||
|
|
6444ee9aee | ||
|
|
5fc0e53cc8 | ||
|
|
147b5af7fe | ||
|
|
fa5fb4e49b | ||
|
|
d98f09825f | ||
|
|
74c075a751 | ||
|
|
f6815c381a | ||
|
|
7268877512 | ||
|
|
9114cd36cd | ||
|
|
530a5a3f01 | ||
|
|
1a9148ae2f | ||
|
|
e74d9c8aea | ||
|
|
662d453bf5 | ||
|
|
00885ccfd6 | ||
|
|
2e17b65004 | ||
|
|
df3a7bab95 | ||
|
|
c96851dc0d | ||
|
|
8c528798ad | ||
|
|
c065dc89bb | ||
|
|
f339b8b1e7 | ||
|
|
24cec4d5ba | ||
|
|
0d769760fd | ||
|
|
8fb5f5a350 | ||
|
|
9ffc7359b4 | ||
|
|
e6d200befe | ||
|
|
e079c43485 | ||
|
|
5f200844a4 | ||
|
|
6a4aa58c2e | ||
|
|
679bcc4365 | ||
|
|
9f056450d6 | ||
|
|
27994e444d | ||
|
|
9d11486431 | ||
|
|
e6ed641079 | ||
|
|
99bdc94279 | ||
|
|
a86559bdce | ||
|
|
971bb3bfc0 | ||
|
|
c387aa0f0d | ||
|
|
10ec942d67 | ||
|
|
91338a7439 | ||
|
|
a5ff057b69 | ||
|
|
d04291d66d | ||
|
|
4b9bc61748 | ||
|
|
a0a0e32f68 | ||
|
|
8167d64bcb | ||
|
|
e6b101d7da | ||
|
|
3689def55f | ||
|
|
a8c79ebf3b | ||
|
|
12f240c7e5 | ||
|
|
e1fc0a4d6b | ||
|
|
1c602f0e92 | ||
|
|
f5ad65cd2e | ||
|
|
4fe865a30f | ||
|
|
4ba390adfc | ||
|
|
ebfa50dce4 | ||
|
|
3d1631a673 | ||
|
|
7ea1501058 | ||
|
|
6fe163f4c4 | ||
|
|
38cccc73f0 | ||
|
|
75d0b6116e | ||
|
|
acb3a50768 | ||
|
|
e51ce1d232 | ||
|
|
e23e81425c | ||
|
|
14234e9eca | ||
|
|
5dd561743e | ||
|
|
264ab2ddd2 | ||
|
|
1e3932fbe1 | ||
|
|
51b8271ee9 | ||
|
|
c6d13e8d73 | ||
|
|
8a8c5275b0 | ||
|
|
a884e37625 | ||
|
|
dc84deafea | ||
|
|
23adfc132a | ||
|
|
be8bed3602 | ||
|
|
a8cb993e56 | ||
|
|
43da8296cf | ||
|
|
3462053a08 | ||
|
|
5e21c904ae | ||
|
|
26395fa2c2 | ||
|
|
f62ea2b3e0 | ||
|
|
f70097d9c9 | ||
|
|
47c400da03 | ||
|
|
a01a5f06ed | ||
|
|
d8a53795fe | ||
|
|
42991ff0ca | ||
|
|
087318f333 | ||
|
|
c2c574f153 | ||
|
|
96b7930292 | ||
|
|
789b639bbe | ||
|
|
7b5eb7e1b7 | ||
|
|
04d35e8d7e | ||
|
|
bef8362087 | ||
|
|
d80ba9b649 | ||
|
|
fdd75c4a36 | ||
|
|
31beafbd04 | ||
|
|
b203c79d87 | ||
|
|
18188b6f39 | ||
|
|
3e8ad6e26c | ||
|
|
6ef808cae1 | ||
|
|
bc2fe3db05 | ||
|
|
400447825a | ||
|
|
75f52cef4a | ||
|
|
4bec2f496d | ||
|
|
39c6b07820 | ||
|
|
f2cf9f0bd1 | ||
|
|
38b1b41682 | ||
|
|
68638ae67c | ||
|
|
9000f91f7e | ||
|
|
46b1cf6dc9 | ||
|
|
a74d7fa54f | ||
|
|
cdec2dd204 | ||
|
|
f98be66eda | ||
|
|
af5c062638 | ||
|
|
6ca28a9931 | ||
|
|
ce10596a13 | ||
|
|
d9a8108a15 | ||
|
|
1b5005277c | ||
|
|
ee9b35bec7 | ||
|
|
d82ab58c24 | ||
|
|
dbcc558f04 | ||
|
|
54f8add2de | ||
|
|
6e11362b75 | ||
|
|
59310feb4b | ||
|
|
8017cb16f3 | ||
|
|
be32f71b1a | ||
|
|
193720a376 | ||
|
|
865dd7984d | ||
|
|
d31d050dd5 | ||
|
|
3ae4e95775 | ||
|
|
1450ffd015 | ||
|
|
0ff5045410 | ||
|
|
e6a68d8cf2 | ||
|
|
a093745aa1 | ||
|
|
0af95f24fc | ||
|
|
6d1462712c | ||
|
|
048782bbec | ||
|
|
7397fca459 | ||
|
|
3dfb02e876 | ||
|
|
7e31ec9994 | ||
|
|
594811b9e6 | ||
|
|
c18da15703 | ||
|
|
c7c30d26b5 | ||
|
|
b2cf3f5270 | ||
|
|
1ebc4643e9 | ||
|
|
e77818daf8 | ||
|
|
eb6068cc1f | ||
|
|
fbec6c1261 | ||
|
|
2b05e90a57 | ||
|
|
028166428d | ||
|
|
fccae8a158 | ||
|
|
9e8f3f8c67 | ||
|
|
5886bb2b6a | ||
|
|
a999ce41ce | ||
|
|
d911c83c56 | ||
|
|
471df37f73 | ||
|
|
fab708d74e | ||
|
|
96583ee109 | ||
|
|
d3dd8af4cc | ||
|
|
f9642228af | ||
|
|
7a30b607e5 | ||
|
|
042b9e3c85 | ||
|
|
e57d62184e | ||
|
|
0139c38786 | ||
|
|
81c5c06414 | ||
|
|
8e702ad0d0 | ||
|
|
8a06717f95 | ||
|
|
123bf7e339 | ||
|
|
0bfaeac94b | ||
|
|
81a2d3854b | ||
|
|
e6bcd4e559 | ||
|
|
0d78000ca3 | ||
|
|
175579f8e2 | ||
|
|
05d2c538ea | ||
|
|
28a78f02a8 | ||
|
|
9de72b2e7e | ||
|
|
c6a892c15d | ||
|
|
618ea544c2 | ||
|
|
4ed69e515e | ||
|
|
124715d93e | ||
|
|
26553dfdad | ||
|
|
844d683915 | ||
|
|
47c429e8c3 | ||
|
|
33d9f68cda | ||
|
|
8618b6ad60 | ||
|
|
893ca2a4cb | ||
|
|
ef09160447 | ||
|
|
1ab09a6fa8 | ||
|
|
0134d8c914 | ||
|
|
ac0ec7b314 | ||
|
|
9350e05ad6 | ||
|
|
76797a5e86 | ||
|
|
6163143cfe | ||
|
|
60bcbb230f | ||
|
|
57824f4f02 | ||
|
|
9642337729 | ||
|
|
c265a6ec6a | ||
|
|
0558d55259 | ||
|
|
c2328793a3 | ||
|
|
e1300914da | ||
|
|
713f6632f9 | ||
|
|
9e8bd87501 | ||
|
|
b508ea71f8 | ||
|
|
be5a93b29a | ||
|
|
972256cd6e | ||
|
|
b5c2634151 | ||
|
|
992aa392a9 | ||
|
|
6b751b2874 | ||
|
|
034b64c895 | ||
|
|
61a93c2374 | ||
|
|
73c8012b52 | ||
|
|
eca4415287 | ||
|
|
a5c67fac57 | ||
|
|
b0d1b9d44f | ||
|
|
4d7958414e | ||
|
|
4d122d5d7c | ||
|
|
5228c18981 | ||
|
|
7b39aa61a9 | ||
|
|
d785a95a5f | ||
|
|
ff43319fdb | ||
|
|
4167066f04 | ||
|
|
61232c4557 | ||
|
|
5f8b20761b | ||
|
|
4ad9d66a3c | ||
|
|
5d4ad105b7 | ||
|
|
fa8bc0b57c | ||
|
|
1341cc35b9 | ||
|
|
173b4722fc | ||
|
|
515093ca29 | ||
|
|
013e70d22d | ||
|
|
640ce7beed | ||
|
|
d704dbec15 | ||
|
|
33989c3551 | ||
|
|
6470165730 | ||
|
|
fc33a75f22 | ||
|
|
0645690f3d | ||
|
|
e9a541a096 | ||
|
|
ec253251bc | ||
|
|
ae72632b85 | ||
|
|
b69a4aaa9b | ||
|
|
fc56972a35 | ||
|
|
f898a1724c | ||
|
|
ef37bcf170 | ||
|
|
31437e3185 | ||
|
|
fb98755a48 | ||
|
|
b2c07b620d | ||
|
|
d3cda4816d | ||
|
|
8aaa384193 | ||
|
|
2eed6f18e4 | ||
|
|
c79b681480 | ||
|
|
15b6259dcc | ||
|
|
d3e96c6769 | ||
|
|
eef2fb907b | ||
|
|
29a68836fa | ||
|
|
4b5cf91125 | ||
|
|
e66640f5ab | ||
|
|
01921cf9f0 | ||
|
|
d30b232aeb | ||
|
|
f9d93403d0 | ||
|
|
2c84fdbea3 | ||
|
|
61ebbc3403 | ||
|
|
4d8615c4fa | ||
|
|
55eb112ab0 | ||
|
|
9fa16cd5b9 | ||
|
|
6101792f4a | ||
|
|
b931c1b008 | ||
|
|
6aa1ad83a6 | ||
|
|
634f7dc1e6 | ||
|
|
80420d7cba | ||
|
|
b62d2fcf08 | ||
|
|
e5f851b01e | ||
|
|
12cecf668a | ||
|
|
f92a972aa5 | ||
|
|
756ff02fb7 | ||
|
|
1acb2fe894 | ||
|
|
4694664470 | ||
|
|
10c992bb27 | ||
|
|
5c443ee7a5 | ||
|
|
2785c83a90 | ||
|
|
a7f35bba02 | ||
|
|
cb5f8919e4 | ||
|
|
16371a8f5d | ||
|
|
98ac49f1bb | ||
|
|
5006fd48d8 | ||
|
|
a389eb8fd6 | ||
|
|
c68640f6f7 | ||
|
|
2695df5f31 | ||
|
|
fd4dbbfb35 | ||
|
|
5902aaf138 | ||
|
|
fc2ba4f4bd | ||
|
|
d50dae5005 | ||
|
|
e883528dd1 | ||
|
|
b1f721503e | ||
|
|
c0e71341a5 | ||
|
|
f2b9d369bd | ||
|
|
b1a1d1d0dd | ||
|
|
51e56f74d8 | ||
|
|
a34ce559a4 | ||
|
|
8bf7e77b0e | ||
|
|
7b633b141f | ||
|
|
95dbe3089e | ||
|
|
ee2f7c8a5c |
@@ -1203,10 +1203,15 @@ set(PHY_SRC_UE
|
||||
${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_nr.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/pss_nr.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/sss_nr.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/pss_nr_sl.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/sss_nr_sl.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_generate_psbch_dmrs_sl.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/psbch_nr_sl.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_ue_rf_helpers.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_pbch.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_psbch.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
|
||||
@@ -2436,7 +2441,19 @@ target_link_libraries(nr_pbchsim PRIVATE
|
||||
target_link_libraries(nr_pbchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
|
||||
|
||||
|
||||
#PUCCH ---> Prashanth
|
||||
add_executable(nr_psbchsim
|
||||
${OPENAIR1_DIR}/SIMULATION/NR_PHY/psbchsim.c
|
||||
${OPENAIR_DIR}/common/utils/nr/nr_common.c
|
||||
${T_SOURCE}
|
||||
${SHLIB_LOADER_SOURCES}
|
||||
)
|
||||
target_link_libraries(nr_psbchsim PRIVATE
|
||||
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group
|
||||
m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl
|
||||
)
|
||||
target_link_libraries(nr_psbchsim PRIVATE asn1_nr_rrc asn1_lte_rrc)
|
||||
|
||||
|
||||
add_executable(nr_pucchsim
|
||||
${OPENAIR1_DIR}/SIMULATION/NR_PHY/pucchsim.c
|
||||
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
|
||||
@@ -2567,7 +2584,7 @@ if (${T_TRACER})
|
||||
lte-softmodem lte-uesoftmodem nr-softmodem
|
||||
nr-uesoftmodem dlsim dlsim_tm4 dlsim_tm7
|
||||
ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim
|
||||
syncsim nr_ulsim nr_dlsim nr_dlschsim nr_pbchsim nr_pucchsim
|
||||
syncsim nr_ulsim nr_dlsim nr_dlschsim nr_pbchsim nr_psbchsim nr_pucchsim
|
||||
nr_ulschsim ldpctest polartest smallblocktest cu_test du_test
|
||||
#all "add_library" definitions
|
||||
ITTI lte_rrc nr_rrc s1ap x2ap m2ap m3ap f1ap
|
||||
|
||||
341
ci-scripts/run_sl_test.py
Executable file
341
ci-scripts/run_sl_test.py
Executable file
@@ -0,0 +1,341 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Automated tests for running 5G NR Sidelink SyncRef UE and/or Nearby UE.
|
||||
# The following is an example to run remote machine (nearby) three times.
|
||||
# The syncref UE is launched on the current machine, and a single
|
||||
# nearby UE is launched on the machine specified by the --host and
|
||||
# --user flags. The -r will enable this simulation to be repeated
|
||||
# three times.
|
||||
#
|
||||
# python3 run_sl_test.py --user account --host 10.1.1.68 -r 3
|
||||
#
|
||||
# The following is an example to run just a Sidelink Nearby UE.
|
||||
# By specifying -l nearby, only the nearby UE will be launched
|
||||
# on the machine specified by the --host and --user flags.
|
||||
# The -r will enable this simulation to be repeated two times.
|
||||
#
|
||||
# python3 run_sl_test.py -l nearby --user account --host 10.1.1.68 -r 2
|
||||
#
|
||||
# See `--help` for more information.
|
||||
#
|
||||
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
import time
|
||||
import re
|
||||
import glob
|
||||
import subprocess
|
||||
from subprocess import Popen
|
||||
import threading
|
||||
from typing import Dict
|
||||
from queue import *
|
||||
from sl_check_log import LogChecker
|
||||
|
||||
HOME_DIR = os.path.expanduser( '~' )
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Command line argument parsing
|
||||
|
||||
parser = argparse.ArgumentParser(description="""
|
||||
Automated tests for 5G NR Sidelink simulations
|
||||
""")
|
||||
|
||||
parser.add_argument('--launch', '-l', default='both', choices='syncref nearby both'.split(), help="""
|
||||
Sidelink UE type to launch test scenario (default: %(default)s)
|
||||
""")
|
||||
|
||||
parser.add_argument('--host', default='10.1.1.80', type=str, help="""
|
||||
Nearby Host IP (default: %(default)s)
|
||||
""")
|
||||
|
||||
parser.add_argument('--user', '-u', default='zaid', type=str, help="""
|
||||
User id in Nearby Host (default: %(default)s)
|
||||
""")
|
||||
|
||||
parser.add_argument('--repeat', '-r', default=1, type=int, help="""
|
||||
The number of repeated test iterations (default: %(default)s)
|
||||
""")
|
||||
|
||||
parser.add_argument('--basic', '-b', action='store_true', help="""
|
||||
Basic test with basic shell commands
|
||||
""")
|
||||
|
||||
parser.add_argument('--commands', default='sl_cmds.txt', help="""
|
||||
The USRP Commands .txt file (default: %(default)s)
|
||||
""")
|
||||
|
||||
parser.add_argument('--duration', '-d', metavar='SECONDS', type=int, default=30, help="""
|
||||
How long to run the test before stopping to examine the logs
|
||||
""")
|
||||
|
||||
parser.add_argument('--nid1', type=int, default=10, help="""
|
||||
Nid1 value
|
||||
""")
|
||||
|
||||
parser.add_argument('--nid2', type=int, default=1, help="""
|
||||
Nid2 value
|
||||
""")
|
||||
|
||||
parser.add_argument('--log-dir', default=HOME_DIR, help="""
|
||||
Where to store log files
|
||||
""")
|
||||
|
||||
parser.add_argument('--compress', action='store_true', help="""
|
||||
Compress the log files in the --log-dir
|
||||
""")
|
||||
|
||||
parser.add_argument('--no-run', '-n', action='store_true', help="""
|
||||
Don't run the test, only examine the logs in the --log-dir
|
||||
directory from a previous run of the test
|
||||
""")
|
||||
|
||||
parser.add_argument('--debug', action='store_true', help="""
|
||||
Enable debug logging (for this script only)
|
||||
""")
|
||||
|
||||
parser.add_argument('--test', '-t', default='usrp', choices='psbchsim rfsim usrp'.split(), help="""
|
||||
The kind of test scenario to run. The options include psbchsim, rfsim, or usrp. (default: %(default)s)
|
||||
""")
|
||||
|
||||
OPTS = parser.parse_args()
|
||||
del parser
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG if OPTS.debug else logging.INFO,
|
||||
format='>>> %(name)s: %(levelname)s: %(message)s')
|
||||
LOGGER = logging.getLogger(os.path.basename(sys.argv[0]))
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
def redirect_output(cmd: str, filename: str) -> str:
|
||||
cmd += ' >{} 2>&1'.format(filename)
|
||||
return cmd
|
||||
|
||||
def thread_delay(thread_name: str, delay: int) -> None:
|
||||
count = 0
|
||||
while count < 1:
|
||||
time.sleep(delay)
|
||||
count += 1
|
||||
|
||||
class Command:
|
||||
"""
|
||||
Parsing USRP commands file
|
||||
"""
|
||||
def __init__(self, filename) -> None:
|
||||
self.check_user()
|
||||
self.filename = self.check_file(filename)
|
||||
self.parse_commands()
|
||||
|
||||
def check_user(self) -> None:
|
||||
if OPTS.test != 'usrp': return
|
||||
if OPTS.launch != 'syncref' and OPTS.user == '':
|
||||
LOGGER.error("--user followed by [user id] is mandatory to connect to remote machine")
|
||||
sys.exit(1)
|
||||
|
||||
def check_file(self, filename) -> str:
|
||||
data_file = glob.glob(filename)
|
||||
if data_file:
|
||||
return filename
|
||||
else:
|
||||
LOGGER.error(f'The file {filename} does not exist!')
|
||||
sys.exit(1)
|
||||
|
||||
def parse_commands(self) -> None:
|
||||
"""
|
||||
Scan the provided commands file.
|
||||
"""
|
||||
self.launch_cmds: Dict[str, str] = {}
|
||||
if OPTS.test == 'usrp':
|
||||
launch_cmds_re = re.compile(r'^\s*(\S*)usrp\S*\s*=\s*((\S+\s*)*)')
|
||||
elif OPTS.test == 'rfsim':
|
||||
launch_cmds_re = re.compile(r'^\s*(\S*)rfsim\S*\s*=\s*((\S+\s*)*)')
|
||||
elif OPTS.test == 'psbchsim':
|
||||
launch_cmds_re = re.compile(r'^\s*(\S*)psbchsim\S*\s*=\s*((\S+\s*)*)')
|
||||
else:
|
||||
LOGGER.error("Provided test option not valid! %s", OPTS.test)
|
||||
exit(1)
|
||||
|
||||
with open(self.filename, 'rt') as fh:
|
||||
nearby_cmd_continued = False
|
||||
syncref_cmd_continued = False
|
||||
for line in fh:
|
||||
if line == '\n': continue
|
||||
match = launch_cmds_re.match(line)
|
||||
if match:
|
||||
host_role = match.group(1)
|
||||
launch_cmds = match.group(2)
|
||||
if host_role.lower().startswith('nearby'):
|
||||
nearby_cmd_continued = True
|
||||
continue
|
||||
if host_role.lower().startswith('syncref'):
|
||||
syncref_cmd_continued = True
|
||||
continue
|
||||
elif nearby_cmd_continued:
|
||||
launch_cmds += line
|
||||
if not line.strip().endswith('\\'):
|
||||
self.launch_cmds['nearby'] = launch_cmds
|
||||
LOGGER.debug('Nearby cmd is %s', launch_cmds)
|
||||
nearby_cmd_continued = False
|
||||
continue
|
||||
elif syncref_cmd_continued:
|
||||
launch_cmds += line
|
||||
if not line.strip().endswith('\\'):
|
||||
self.launch_cmds['syncref'] = launch_cmds
|
||||
LOGGER.debug('Syncref cmd is %s', launch_cmds)
|
||||
syncref_cmd_continued = False
|
||||
continue
|
||||
else:
|
||||
LOGGER.debug('Unmatched line %r', line)
|
||||
continue
|
||||
if self.launch_cmds == {}:
|
||||
LOGGER.error(f'usrp commands are not found in file: {self.filename} ')
|
||||
exit()
|
||||
|
||||
class TestThread(threading.Thread):
|
||||
"""
|
||||
Represents TestThread
|
||||
"""
|
||||
def __init__(self, queue, commands, passed, log_agent):
|
||||
threading.Thread.__init__(self)
|
||||
self.queue = queue
|
||||
self.commands = commands
|
||||
self.passed = passed
|
||||
self.delay = 0
|
||||
self.log_file = log_agent.txlog_file_path
|
||||
self.log_agent = log_agent
|
||||
|
||||
def run(self):
|
||||
if self.queue.empty() == True:
|
||||
LOGGER.error("Queue is empty!")
|
||||
sys.exit(1)
|
||||
try:
|
||||
while not self.queue.empty():
|
||||
job = self.queue.get()
|
||||
if "nearby" == job:
|
||||
thread_delay(job, delay = 0)
|
||||
self.launch_nearby(job)
|
||||
if "syncref" == job and not OPTS.no_run:
|
||||
thread_delay(job, delay = self.delay)
|
||||
self.launch_syncref(job)
|
||||
self.queue.task_done()
|
||||
except Exception as inst:
|
||||
LOGGER.info(f"Failed to operate on job with type {type(inst)} and args {inst.args}")
|
||||
|
||||
def launch_syncref(self, job) -> Popen:
|
||||
LOGGER.info('Launching SyncRef UE')
|
||||
if OPTS.basic: cmd = redirect_output('uname -a', self.log_file)
|
||||
else: cmd = self.commands.launch_cmds[job]
|
||||
proc = Popen(cmd, shell=True)
|
||||
LOGGER.info(f"syncref_proc = {proc}")
|
||||
if not OPTS.basic and not OPTS.no_run:
|
||||
LOGGER.info(f"Process running... {job}")
|
||||
time.sleep(OPTS.duration)
|
||||
self.kill_process("syncref", proc)
|
||||
|
||||
def launch_nearby(self, job, host=OPTS.host, user=OPTS.user) -> Popen:
|
||||
LOGGER.info('#' * 42)
|
||||
LOGGER.info('Launching Nearby UE')
|
||||
if OPTS.basic: cmd = redirect_output('uname -a', self.log_file)
|
||||
else: cmd = self.commands.launch_cmds[job]
|
||||
if OPTS.test == 'usrp':
|
||||
cmd = cmd[:-1] + f' -d {OPTS.duration} --nid1 {OPTS.nid1} --nid2 {OPTS.nid2}'
|
||||
proc = Popen(["ssh", f"{user}@{host}", cmd],
|
||||
shell=False,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
LOGGER.info(f"nearby_proc = {proc}")
|
||||
remote_output = proc.stdout.readlines()
|
||||
if remote_output == []:
|
||||
nearby_result = proc.stderr.readlines()
|
||||
else:
|
||||
nearby_result = remote_output
|
||||
self.kill_process("nearby", proc)
|
||||
if nearby_result:
|
||||
self.find_nearby_result_metric(nearby_result)
|
||||
else:
|
||||
proc = Popen(cmd, shell=True)
|
||||
LOGGER.info(f"nearby_proc = {proc}")
|
||||
if not OPTS.basic and not OPTS.no_run:
|
||||
LOGGER.info(f"Process running... {job}")
|
||||
time.sleep(OPTS.duration)
|
||||
self.kill_process("nearby", proc)
|
||||
nearby_result = self.log_agent.analyze_nearby_logs(OPTS.nid1, OPTS.nid2)
|
||||
if nearby_result:
|
||||
self.find_nearby_result_metric(nearby_result)
|
||||
|
||||
def find_nearby_result_metric(self, remote_log):
|
||||
result_metric = None
|
||||
for line in remote_log:
|
||||
if type(line) is not str:
|
||||
line = line.decode()
|
||||
if OPTS.test == 'usrp':
|
||||
LOGGER.info(line.strip())
|
||||
# 'SyncRef UE found. RSRP: -100 dBm/RE. It took {delta_time_s} seconds'
|
||||
if 'SyncRef UE found' in line:
|
||||
fields = line.split(maxsplit=12)
|
||||
if len(fields) > 6:
|
||||
ssb_rsrp = float(fields[-6])
|
||||
sync_duration = float(fields[-2])
|
||||
counting_duration = sync_duration - self.delay
|
||||
result_metric = (ssb_rsrp, sync_duration, counting_duration)
|
||||
self.passed += [result_metric]
|
||||
return
|
||||
|
||||
def kill_process(self, job: str, proc: Popen) -> None:
|
||||
# Wait for the processes to end
|
||||
LOGGER.info(f'kill main simulation processes... {job}')
|
||||
cmd = ['sudo', 'killall']
|
||||
cmd.append('-KILL')
|
||||
if proc:
|
||||
cmd.append('nr-uesoftmodem')
|
||||
if "syncref" == job:
|
||||
subprocess.run(cmd)
|
||||
LOGGER.info(f'Waiting for PID proc.pid for {job}')
|
||||
proc.kill()
|
||||
proc.wait()
|
||||
LOGGER.info(f'kill main simulation processes...done for {job}')
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
def main() -> int:
|
||||
commands = Command(OPTS.commands)
|
||||
log_agent = LogChecker(OPTS, LOGGER)
|
||||
LOGGER.debug(f'Number of iterations {OPTS.repeat}')
|
||||
if commands.launch_cmds is not None:
|
||||
for role, cmd in commands.launch_cmds.items():
|
||||
LOGGER.debug(f'{role} UE: {cmd}')
|
||||
jobs = ['nearby', 'syncref'] if OPTS.launch == 'both' else [OPTS.launch]
|
||||
passed_metric = []
|
||||
num_tx_ssb = []
|
||||
num_passed = 0
|
||||
for i in range(OPTS.repeat):
|
||||
threads = []
|
||||
queue = Queue()
|
||||
for job in jobs:
|
||||
queue.put(job)
|
||||
th = TestThread(queue, commands, passed_metric, log_agent)
|
||||
th.setDaemon(True)
|
||||
th.start()
|
||||
threads.append(th)
|
||||
for th in threads:
|
||||
th.join()
|
||||
if num_passed != len(passed_metric):
|
||||
# Examine the logs to determine if the test passed
|
||||
(ssb_rsrp, sync_duration, counting_duration) = passed_metric[-1]
|
||||
num_ssb = log_agent.analyze_syncref_logs(counting_duration)
|
||||
num_tx_ssb += [num_ssb]
|
||||
LOGGER.info(f"Trial {i+1}/{OPTS.repeat} PASSED. {num_ssb} SSB(s) were generated. Measured {ssb_rsrp} RSRP (dbm/RE)")
|
||||
else:
|
||||
LOGGER.info(f"Failure detected during {i+1}/{OPTS.repeat} trial(s).")
|
||||
num_passed = len(passed_metric)
|
||||
|
||||
LOGGER.info('#' * 42)
|
||||
LOGGER.info(f"Number of passed = {len(passed_metric)}/{OPTS.repeat}")
|
||||
if len(num_tx_ssb) > 0:
|
||||
LOGGER.info(f"Avg number of SSB = {sum(num_tx_ssb) / len(num_tx_ssb)} ({num_tx_ssb})")
|
||||
if len(passed_metric) > 0:
|
||||
LOGGER.info(f"Avg SSB RSRP = {sum([result[0] for result in passed_metric]) / len(passed_metric)}")
|
||||
LOGGER.info(f"Avg Sync duration (seconds) = {sum([result[1] for result in passed_metric]) / len(passed_metric)}")
|
||||
return 0
|
||||
|
||||
sys.exit(main())
|
||||
112
ci-scripts/sl_check_log.py
Executable file
112
ci-scripts/sl_check_log.py
Executable file
@@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import bz2
|
||||
import logging
|
||||
from typing import Optional, List, Generator
|
||||
|
||||
class LogChecker():
|
||||
def __init__(self, OPTS, LOGGER):
|
||||
self.OPTS = OPTS
|
||||
self.LOGGER = LOGGER
|
||||
self.rxlog_file_path = os.path.join(OPTS.log_dir, 'rx.log')
|
||||
self.txlog_file_path = os.path.join(OPTS.log_dir, 'tx.log')
|
||||
|
||||
def get_lines(self, filename: str) -> Generator[str, None, None]:
|
||||
"""
|
||||
Yield each line of the given log file (.bz2 compressed log file if -c flag is used.)
|
||||
"""
|
||||
fh = bz2.open(filename, 'rb') if self.OPTS.compress else open(filename, 'rb')
|
||||
for line_bytes in fh:
|
||||
line = line_bytes.decode('utf-8', 'backslashreplace')
|
||||
line = line.rstrip('\r\n')
|
||||
yield line
|
||||
|
||||
def get_analysis_messages_nearby(self, filename: str) -> Generator[str, None, None]:
|
||||
"""
|
||||
Finding all logs in the log file with X fields for log parsing optimization
|
||||
"""
|
||||
self.LOGGER.info('Scanning %s', filename)
|
||||
for line in self.get_lines(filename):
|
||||
#796821.854505 [NR_PHY] SyncRef UE found with Nid1 10 and Nid2 1 SS-RSRP 100 dBm/RE
|
||||
#796811.532881 [NR_PHY] nrUE configured
|
||||
fields = line.split(maxsplit=10)
|
||||
if len(fields) == 11 or len(fields) == 4:
|
||||
yield line
|
||||
|
||||
def analyze_nearby_logs(self, exp_nid1: int, exp_nid2: int) -> bool:
|
||||
found = set()
|
||||
est_nid1, est_nid2, time_start_s, time_end_s = -1, -1, -1, -1
|
||||
ssb_rsrp = 0
|
||||
log_file = self.rxlog_file_path
|
||||
result = None
|
||||
|
||||
if self.OPTS.compress:
|
||||
log_file = f'{log_file}.bz2'
|
||||
for line in self.get_analysis_messages_nearby(log_file):
|
||||
#796821.854505 [NR_PHY] SyncRef UE found with Nid1 10 and Nid2 1 SS-RSRP -100 dBm/RE
|
||||
#796811.532881 [NR_PHY] nrUE configured
|
||||
if 'SyncRef UE found' in line and 'Nid1' in line and 'Nid2' in line:
|
||||
num_split = 13 if 'RSRP' in line else 10
|
||||
fields = line.split(maxsplit=num_split)
|
||||
est_nid1 = int(fields[7])
|
||||
est_nid2 = int(fields[10])
|
||||
if 'RSRP' in line:
|
||||
ssb_rsrp = int(fields[12])
|
||||
found.add('found')
|
||||
time_end_s = float(fields[0])
|
||||
break
|
||||
if time_start_s == -1 and 'nrUE configured' in line:
|
||||
fields = line.split(maxsplit=3)
|
||||
time_start_s = float(fields[0])
|
||||
|
||||
|
||||
self.LOGGER.debug('found: %r', found)
|
||||
if len(found) != 1:
|
||||
self.LOGGER.error(f'Failed -- No SyncRef UE found.')
|
||||
return
|
||||
elif exp_nid1 != est_nid1 or exp_nid2 != est_nid2:
|
||||
self.LOGGER.error(f'Failed -- found SyncRef UE Nid1 {est_nid1}, Ni2 {est_nid2}, expecting Nid1 {exp_nid1}, Nid2 {exp_nid2}')
|
||||
return
|
||||
if time_start_s == -1:
|
||||
self.LOGGER.error(f'Failed -- No start time found! Fix log and re-run!')
|
||||
return
|
||||
|
||||
delta_time_s = time_end_s - time_start_s
|
||||
result = f'SyncRef UE found. RSRP: {ssb_rsrp} dBm/RE. It took {delta_time_s} seconds'
|
||||
self.LOGGER.info(result)
|
||||
return [result]
|
||||
|
||||
|
||||
def get_analysis_messages_syncref(self, filename: str) -> Generator[str, None, None]:
|
||||
"""
|
||||
Finding all logs in the log file with X fields for log parsing optimization
|
||||
"""
|
||||
self.LOGGER.info('Scanning %s', filename)
|
||||
for line in self.get_lines(filename):
|
||||
#796811.532881 [NR_PHY] nrUE configured
|
||||
#796821.854505 [NR_PHY] PSBCH SL generation started
|
||||
fields = line.split(maxsplit=5)
|
||||
if len(fields) == 4 or len(fields) == 6 :
|
||||
yield line
|
||||
|
||||
def analyze_syncref_logs(self, counting_delta: float) -> int:
|
||||
time_start_s, time_end_s = -1, -1
|
||||
log_file = self.txlog_file_path
|
||||
sum_ssb = 0
|
||||
|
||||
if self.OPTS.compress:
|
||||
tx_log_file = f'{log_file}.bz2'
|
||||
for line in self.get_analysis_messages_syncref(log_file):
|
||||
#796811.532881 [NR_PHY] nrUE configured
|
||||
#796821.854505 [NR_PHY] PSBCH SL generation started
|
||||
if time_start_s == -1 and 'nrUE configured' in line:
|
||||
fields = line.split(maxsplit=2)
|
||||
time_start_s = float(fields[0])
|
||||
time_end_s = time_start_s + counting_delta
|
||||
if 'PSBCH SL generation started' in line:
|
||||
fields = line.split(maxsplit=2)
|
||||
time_st = float(''.join([ch for ch in fields[0] if ch.isnumeric() or ch =='.']))
|
||||
if time_st < time_end_s:
|
||||
sum_ssb += 1
|
||||
return sum_ssb
|
||||
45
ci-scripts/sl_cmds.txt
Normal file
45
ci-scripts/sl_cmds.txt
Normal file
@@ -0,0 +1,45 @@
|
||||
# The lines containing 'usrp' and starts with 'syncref' or 'nearby' will be valid until it does not contain backspace.
|
||||
|
||||
####################
|
||||
#### USRP ####
|
||||
####################
|
||||
|
||||
### RX Nearby UE ###
|
||||
nearby_usrp_cmd = cd $HOME/openairinterface5g/ci-scripts; \
|
||||
python3 sl_rx_agent.py --cmd \
|
||||
'sudo -E LD_LIBRARY_PATH=$HOME/openairinterface5g/cmake_targets/ran_build/build:$LD_LIBRARY_PATH \
|
||||
$HOME/openairinterface5g/cmake_targets/ran_build/build/nr-uesoftmodem \
|
||||
--sl-mode 2 -r 106 --numerology 1 --band 38 --SLC 2600000000 --ue-rxgain 90 \
|
||||
--usrp-args "type=n3xx,addr=192.168.20.2,subdev=A:0,master_clock_rate=122.88e6" \
|
||||
--log_config.global_log_options time,nocolor \
|
||||
> ~/rx.log 2>&1'
|
||||
|
||||
### TX SyncRef UE ###
|
||||
|
||||
syncref_usrp_cmd = \
|
||||
sudo -E LD_LIBRARY_PATH=$HOME/openairinterface5g/cmake_targets/ran_build/build:$LD_LIBRARY_PATH \
|
||||
$HOME/openairinterface5g/cmake_targets/ran_build/build/nr-uesoftmodem \
|
||||
--sl-mode 2 --sync-ref -r 106 --numerology 1 --band 38 --SLC 2600000000 --ue-txgain 8 \
|
||||
--usrp-args "type=n3xx,addr=192.168.10.2,subdev=A:0,master_clock_rate=122.88e6" \
|
||||
--log_config.global_log_options time,nocolor\
|
||||
> ~/tx.log 2>&1
|
||||
|
||||
####################
|
||||
#### RFSIM ####
|
||||
####################
|
||||
|
||||
### RX Nearby UE ###
|
||||
nearby_rfsim_cmd = \
|
||||
sudo -E RFSIMULATOR=127.0.0.1 \
|
||||
$HOME/openairinterface5g/cmake_targets/ran_build/build/nr-uesoftmodem \
|
||||
--rfsim --sl-mode 2 --rfsimulator.serverport 4048 \
|
||||
--log_config.global_log_options time,nocolor \
|
||||
> ~/rx.log 2>&1
|
||||
|
||||
### TX SyncRef UE ###
|
||||
syncref_rfsim_cmd = \
|
||||
sudo -E RFSIMULATOR=server \
|
||||
$HOME/openairinterface5g/cmake_targets/ran_build/build/nr-uesoftmodem \
|
||||
--sync-ref --rfsim --sl-mode 2 --rfsimulator.serverport 4048 \
|
||||
--log_config.global_log_options time,nocolor \
|
||||
> ~/tx.log 2>&1
|
||||
218
ci-scripts/sl_rx_agent.py
Executable file
218
ci-scripts/sl_rx_agent.py
Executable file
@@ -0,0 +1,218 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Automated tests for running 5G NR Sidelink Nearby UE.
|
||||
# The following is an example to run this script.
|
||||
#
|
||||
# python3 sl_rx_agent.py \
|
||||
# --cmd 'sudo -E LD_LIBRARY_PATH=$HOME/openairinterface5g/cmake_targets/ran_build/build:$LD_LIBRARY_PATH \
|
||||
# $HOME/openairinterface5g/cmake_targets/ran_build/build/nr-uesoftmodem \
|
||||
# --sl-mode 2 -r 106 --numerology 1 --band 38 -C 2600000000 --ue-rxgain 90 \
|
||||
# --usrp-args "type=n3xx,addr=192.168.20.2,subdev=A:0,master_clock_rate=122.88e6" \
|
||||
# > ~/rx.log 2>&1' \
|
||||
# --nid1 10 --nid2 1
|
||||
#
|
||||
# See `--help` for more information.
|
||||
#
|
||||
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
import time
|
||||
import glob
|
||||
import bz2
|
||||
import subprocess
|
||||
from subprocess import Popen
|
||||
from typing import Optional, List
|
||||
from sl_check_log import LogChecker
|
||||
|
||||
HOME_DIR = os.path.expanduser( '~' )
|
||||
# ----------------------------------------------------------------------------
|
||||
# Command line argument parsing
|
||||
|
||||
parser = argparse.ArgumentParser(description="""
|
||||
Automated tests for 5G NR Sidelink Rx simulations
|
||||
""")
|
||||
|
||||
parser.add_argument('--duration', '-d', metavar='SECONDS', type=int, default=30, help="""
|
||||
How long to run the test before stopping to examine the logs
|
||||
""")
|
||||
|
||||
parser.add_argument('--cmd', type=str, default='', help="""
|
||||
Commands
|
||||
""")
|
||||
|
||||
parser.add_argument('--nid1', type=int, default=10, help="""
|
||||
Nid1 value
|
||||
""")
|
||||
|
||||
parser.add_argument('--nid2', type=int, default=1, help="""
|
||||
Nid2 value
|
||||
""")
|
||||
|
||||
parser.add_argument('--log-dir', default=HOME_DIR, help="""
|
||||
Where to store log files
|
||||
""")
|
||||
|
||||
parser.add_argument('--compress', '-c', action='store_true', help="""
|
||||
Compress the log files in the --log-dir
|
||||
""")
|
||||
|
||||
parser.add_argument('--no-run', '-n', action='store_true', help="""
|
||||
Don't run the test, only examine the logs in the --log-dir
|
||||
directory from a previous run of the test
|
||||
""")
|
||||
|
||||
parser.add_argument('--debug', action='store_true', help="""
|
||||
Enable debug logging (for this script only)
|
||||
""")
|
||||
|
||||
OPTS = parser.parse_args()
|
||||
del parser
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG if OPTS.debug else logging.INFO,
|
||||
format='>>> %(name)s: %(levelname)s: %(message)s')
|
||||
LOGGER = logging.getLogger(os.path.basename(sys.argv[0]))
|
||||
|
||||
log_file_path = os.path.join(OPTS.log_dir, 'rx.log')
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
def compress(from_name: str, to_name: Optional[str]=None, remove_original: bool=False) -> None:
|
||||
"""
|
||||
Compress the file `from_name` and store it as `to_name`.
|
||||
`to_name` defaults to `from_name` with `.bz2` appended.
|
||||
If `remove_original` is True, removes `from_name` when the compress finishes.
|
||||
"""
|
||||
if to_name is None:
|
||||
to_name = from_name
|
||||
if not to_name.endswith('.bz2'):
|
||||
to_name += '.bz2'
|
||||
LOGGER.info('Compress %s to %s', from_name, to_name)
|
||||
with bz2.open(to_name, 'w') as outh, \
|
||||
open(from_name, 'rb') as inh:
|
||||
while True:
|
||||
data = inh.read(10240)
|
||||
if not data:
|
||||
break
|
||||
outh.write(data)
|
||||
if remove_original:
|
||||
LOGGER.debug('Remove %s', from_name)
|
||||
os.remove(from_name)
|
||||
|
||||
|
||||
class CompressJobs:
|
||||
"""
|
||||
Allow multiple invocations of `compress` to run in parallel
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.kids: List[int] = []
|
||||
|
||||
def compress(self, from_name: str, to_name: Optional[str]=None, remove_original: bool=False) -> None:
|
||||
if not os.path.exists(from_name):
|
||||
# It's not necessarily an error if the log file does not exist.
|
||||
# For example, if nfapi_trace never gets invoked (e.g., because
|
||||
# NFAPI_TRACE_LEVEL is set to none), then the log file nfapi.log
|
||||
# will not get created.
|
||||
LOGGER.warning('No file: %s', from_name)
|
||||
return
|
||||
kid = os.fork()
|
||||
if kid != 0:
|
||||
self.kids.append(kid)
|
||||
else:
|
||||
LOGGER.debug('in pid %d compress %s...', os.getpid(), from_name)
|
||||
compress(from_name, to_name, remove_original)
|
||||
LOGGER.debug('in pid %d compress %s...done', os.getpid(), from_name)
|
||||
sys.exit()
|
||||
|
||||
def wait(self) -> None:
|
||||
LOGGER.debug('wait %s...', self.kids)
|
||||
failed = []
|
||||
for kid in self.kids:
|
||||
LOGGER.debug('waitpid %d', kid)
|
||||
_pid, status = os.waitpid(kid, 0)
|
||||
if status != 0:
|
||||
failed.append(kid)
|
||||
if failed:
|
||||
raise Exception('compression failed: %s', failed)
|
||||
LOGGER.debug('wait...done')
|
||||
|
||||
|
||||
class TestNearby():
|
||||
"""
|
||||
Represents TestNearby
|
||||
"""
|
||||
def __init__(self):
|
||||
self.cmd = None
|
||||
self.delay = 0 # seconds
|
||||
|
||||
def run(self, cmd: str) -> bool:
|
||||
self.cmd = cmd
|
||||
job = "nearby"
|
||||
time.sleep(self.delay)
|
||||
proc = self.launch_nearby(job)
|
||||
LOGGER.info(f"nearby_proc = {proc}")
|
||||
LOGGER.info(f"Process running... {job}")
|
||||
time.sleep(OPTS.duration)
|
||||
passed = self.kill_process("nearby", proc)
|
||||
if OPTS.compress:
|
||||
self.compress_log_file(proc)
|
||||
return passed
|
||||
|
||||
def launch_nearby(self, job) -> Popen:
|
||||
LOGGER.info('Launching Nearby UE: %s', log_file_path)
|
||||
cmd = self.cmd
|
||||
proc = Popen(cmd, shell=True)
|
||||
time.sleep(1)
|
||||
return proc
|
||||
|
||||
def kill_process(self, job: str, proc: Popen) -> bool:
|
||||
passed = True
|
||||
if proc:
|
||||
status = proc.poll()
|
||||
if status is None:
|
||||
LOGGER.info('process is still running, which is good')
|
||||
else:
|
||||
#passed = False
|
||||
LOGGER.info('process ended early: %r', status)
|
||||
LOGGER.info(f'kill main simulation processes... {job}')
|
||||
cmd = ['sudo', 'killall']
|
||||
cmd.append('-KILL')
|
||||
if proc:
|
||||
cmd.append('nr-uesoftmodem')
|
||||
if "nearby" == job:
|
||||
subprocess.run(cmd)
|
||||
LOGGER.info(f'Waiting for PID proc.pid for {job}')
|
||||
proc.kill()
|
||||
proc.wait()
|
||||
LOGGER.info(f'kill main simulation processes...done for {job}')
|
||||
return passed
|
||||
|
||||
def compress_log_file(self, proc: Popen):
|
||||
jobs = CompressJobs()
|
||||
jobs.compress(log_file_path)
|
||||
jobs.wait()
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
def main(argv) -> int:
|
||||
test_agent = TestNearby()
|
||||
log_agent = LogChecker(OPTS, LOGGER)
|
||||
|
||||
passed = True
|
||||
if not OPTS.no_run:
|
||||
passed = test_agent.run(OPTS.cmd)
|
||||
|
||||
# Examine the logs to determine if the test passed
|
||||
if not log_agent.analyze_nearby_logs(exp_nid1=OPTS.nid1, exp_nid2=OPTS.nid2):
|
||||
passed = False
|
||||
|
||||
if not passed:
|
||||
LOGGER.critical('FAILED')
|
||||
return 1
|
||||
|
||||
LOGGER.info('PASSED')
|
||||
return 0
|
||||
|
||||
sys.exit(main(sys.argv))
|
||||
@@ -147,6 +147,18 @@
|
||||
<nruns>3</nruns>
|
||||
</testCase>
|
||||
|
||||
<testCase id="nr_psbchsim.106rb">
|
||||
<desc>nr_psbchsim Test cases. (Test1: PSBCH and synchronization, 106PBR),
|
||||
(Test2: PSBCH and synchronization, 106PBR, SSB SC OFFSET 6)</desc>
|
||||
<main_exec>nr_psbchsim</main_exec>
|
||||
<main_exec_args>-s-11 -S2 -n1 -I -R106
|
||||
-s-11 -S2 -n1 -I -R106 -O6</main_exec_args>
|
||||
<tags>test1 test2 test3</tags>
|
||||
<search_expr_true>PSBCH test OK</search_expr_true>
|
||||
<search_expr_false>segmentation fault|assertion|exiting|fatal</search_expr_false>
|
||||
<nruns>3</nruns>
|
||||
</testCase>
|
||||
|
||||
<testCase id="nr_dlsim.basic">
|
||||
<desc>nr_dlsim Test cases. (Test1: 106 PRB),
|
||||
(Test2: 217 PRB),
|
||||
|
||||
@@ -508,7 +508,7 @@ function main() {
|
||||
[[ "$UE" == 1 ]] && execlist="$execlist lte-uesoftmodem"
|
||||
[[ "$nrUE" == 1 ]] && execlist="$execlist nr-uesoftmodem"
|
||||
# TODO: fix: dlsim_tm4 pucchsim prachsim pdcchsim pbchsim mbmssim
|
||||
[[ "$SIMUS_PHY" == "1" ]] && execlist="$execlist dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim"
|
||||
[[ "$SIMUS_PHY" == "1" ]] && execlist="$execlist dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_psbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim"
|
||||
[[ "$BUILD_OPTLIB" != "" ]] && execlist="$execlist $BUILD_OPTLIB"
|
||||
[[ "$execlist" != "" ]] && execlist="$execlist params_libconfig coding rfsimulator"
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ The main oai binaries, which are tested by the Continuous Integration process ar
|
||||
- The 5G gNodeB: `nr-softmodem`
|
||||
- The 5G CU-UP: `nr-cuup`
|
||||
- The LTE PHY simulators: `dlsim` and `ulsim`
|
||||
- The 5G PHY simulators: `nr_dlschsim`, `nr_dlsim`, `nr_pbchsim`, `nr_pucchsim`, `nr_ulschsim`, `nr_ulsim`, `polartest`, `smallblocktest`, `nr _ulsim`, `ldpctest`
|
||||
- The 5G PHY simulators: `nr_dlschsim`, `nr_dlsim`, `nr_pbchsim`, `nr_psbchsim`, `nr_pucchsim`, `nr_ulschsim`, `nr_ulsim`, `polartest`, `smallblocktest`, `nr _ulsim`, `ldpctest`
|
||||
|
||||
Running the [build_oai](../cmake_targets/build_oai) script also generates some utilities required to build and/or run the oai softmodem binaries:
|
||||
|
||||
|
||||
@@ -195,7 +195,8 @@ void rx_func(void *param)
|
||||
gNB->common_vars.rxdataF[aa],
|
||||
slot_rx,
|
||||
0,
|
||||
gNB->frame_parms.Ncp==EXTENDED?12:14);
|
||||
gNB->frame_parms.Ncp==EXTENDED?12:14,
|
||||
NR_LINK_TYPE_UL);
|
||||
}
|
||||
phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,13 @@
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
|
||||
#include "radio/COMMON/common_lib.h"
|
||||
#include "LAYER2/nr_pdcp/nr_pdcp_entity.h"
|
||||
#include "SCHED_NR_UE/pucch_uci_ue_nr.h"
|
||||
#include "openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h"
|
||||
#include "openair1/PHY/NR_REFSIG/sss_nr.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
//#define DEBUG_PHY_SL_PROC
|
||||
#include "pdcp.h"
|
||||
#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
|
||||
|
||||
/*
|
||||
@@ -99,7 +106,8 @@
|
||||
typedef enum {
|
||||
pss = 0,
|
||||
pbch = 1,
|
||||
si = 2
|
||||
si = 2,
|
||||
psbch = 3,
|
||||
} sync_mode_t;
|
||||
|
||||
static void *NRUE_phy_stub_standalone_pnf_task(void *arg);
|
||||
@@ -160,12 +168,13 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue,
|
||||
|
||||
// initialize all signal buffers
|
||||
init_nr_ue_signal(ue, nb_connected_gNB);
|
||||
if (get_softmodem_params()->sl_mode != 2) {
|
||||
// intialize transport
|
||||
init_nr_ue_transport(ue);
|
||||
|
||||
// intialize transport
|
||||
init_nr_ue_transport(ue);
|
||||
|
||||
// init N_TA offset
|
||||
init_N_TA_offset(ue);
|
||||
// init N_TA offset
|
||||
init_N_TA_offset(ue);
|
||||
}
|
||||
}
|
||||
|
||||
void init_nrUE_standalone_thread(int ue_idx)
|
||||
@@ -376,7 +385,12 @@ static void UE_synch(void *arg) {
|
||||
sync_mode_t sync_mode = pbch;
|
||||
//int CC_id = UE->CC_id;
|
||||
static int freq_offset=0;
|
||||
UE->is_synchronized = 0;
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
UE->is_synchronized_sl = 0;
|
||||
sync_mode = psbch;
|
||||
} else {
|
||||
UE->is_synchronized = 0;
|
||||
}
|
||||
|
||||
if (UE->UE_scan == 0) {
|
||||
|
||||
@@ -392,7 +406,6 @@ static void UE_synch(void *arg) {
|
||||
|
||||
}
|
||||
|
||||
sync_mode = pbch;
|
||||
} else {
|
||||
LOG_E(PHY,"Fixme!\n");
|
||||
/*
|
||||
@@ -492,9 +505,44 @@ static void UE_synch(void *arg) {
|
||||
break;
|
||||
|
||||
case si:
|
||||
|
||||
case psbch: {
|
||||
int initial_synch_sl = nr_sl_initial_sync(&syncD->proc, UE, 2);
|
||||
if (initial_synch_sl >= 0) { // gNB will work as SyncRef UE in simulation.
|
||||
|
||||
// rerun with new cell parameters and frequency-offset
|
||||
freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync
|
||||
nr_sl_rf_card_config_freq(UE, &openair0_cfg[UE->rf_map.card], freq_offset);
|
||||
UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0]);
|
||||
|
||||
if (UE->UE_scan_carrier == 1) {
|
||||
UE->UE_scan_carrier = 0;
|
||||
} else {
|
||||
if (initial_synch_sl == 0) {
|
||||
UE->is_synchronized_sl = 1;
|
||||
LOG_I(NR_PHY, "SyncRef UE found with Nid1 %d and Nid2 %d SSS-RSRP %d dBm/RE\n",
|
||||
GET_NID1_SL(UE->frame_parms.Nid_SL), GET_NID2_SL(UE->frame_parms.Nid_SL),
|
||||
UE->measurements.ssb_rsrp_dBm[0]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG_I(NR_PHY, "No SyncRef UE found\n");
|
||||
if (UE->UE_scan_carrier == 1) {
|
||||
LOG_I(PHY, "Initial sync failed: trying carrier off %d Hz\n", freq_offset);
|
||||
|
||||
if (freq_offset >= 0)
|
||||
freq_offset += 100;
|
||||
freq_offset *= -1;
|
||||
nr_sl_rf_card_config_freq(UE, &openair0_cfg[UE->rf_map.card], freq_offset);
|
||||
UE->rfdevice.trx_set_freq_func(&UE->rfdevice, &openair0_cfg[0]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -561,6 +609,8 @@ void processSlotTX(void *arg) {
|
||||
nr_phy_data_tx_t phy_data = {0};
|
||||
|
||||
LOG_D(PHY,"%d.%d => slot type %d\n", proc->frame_tx, proc->nr_slot_tx, proc->tx_slot_type);
|
||||
if (UE->sync_ref && get_softmodem_params()->sl_mode != 0)
|
||||
proc->tx_slot_type = NR_UPLINK_SLOT;
|
||||
if (proc->tx_slot_type == NR_UPLINK_SLOT || proc->tx_slot_type == NR_MIXED_SLOT){
|
||||
|
||||
// wait for rx slots to send indication (if any) that DLSCH decoding is finished
|
||||
@@ -571,7 +621,7 @@ void processSlotTX(void *arg) {
|
||||
|
||||
// trigger L2 to run ue_scheduler thru IF module
|
||||
// [TODO] mapping right after NR initial sync
|
||||
if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) {
|
||||
if (get_softmodem_params()->sl_mode != 2 && UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) {
|
||||
start_meas(&UE->ue_ul_indication_stats);
|
||||
nr_uplink_indication_t ul_indication;
|
||||
memset((void*)&ul_indication, 0, sizeof(ul_indication));
|
||||
@@ -589,10 +639,20 @@ void processSlotTX(void *arg) {
|
||||
stop_meas(&UE->ue_ul_indication_stats);
|
||||
}
|
||||
|
||||
phy_procedures_nrUE_TX(UE, proc, &phy_data);
|
||||
if (get_softmodem_params()->sl_mode == 0) {
|
||||
phy_procedures_nrUE_TX(UE, proc, &phy_data);
|
||||
} else {
|
||||
phy_procedures_nrUE_SL_TX(UE, proc, 0);
|
||||
}
|
||||
}
|
||||
if (get_softmodem_params()->sl_mode == 0) {
|
||||
RU_write(rxtxD);
|
||||
}
|
||||
}
|
||||
|
||||
RU_write(rxtxD);
|
||||
void processSlotRX_SL(void *arg) {
|
||||
nr_rxtx_thread_data_t *rxtxD = (nr_rxtx_thread_data_t *) arg;
|
||||
processSlotTX(rxtxD);
|
||||
}
|
||||
|
||||
nr_phy_data_t UE_dl_preprocessing(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
|
||||
@@ -703,11 +763,11 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash)
|
||||
|
||||
void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) {
|
||||
|
||||
LOG_I(PHY,"Resynchronizing RX by %d samples\n",UE->rx_offset);
|
||||
int rx_offset = (get_softmodem_params()->sl_mode != 0) ? UE->rx_offset_sl : UE->rx_offset;
|
||||
|
||||
if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) {
|
||||
// Resynchonize by slot (will work with numerology 1 only)
|
||||
for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe/2 ) {
|
||||
for (int size = rx_offset; size > 0; size -= UE->frame_parms.samples_per_subframe / 2) {
|
||||
int unitTransfer=size>UE->frame_parms.samples_per_subframe/2 ? UE->frame_parms.samples_per_subframe/2 : size ;
|
||||
AssertFatal(unitTransfer ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
@@ -718,11 +778,11 @@ void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) {
|
||||
}
|
||||
} else {
|
||||
*timestamp += UE->frame_parms.get_samples_per_slot(1,&UE->frame_parms);
|
||||
for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe ) {
|
||||
for (int size = rx_offset; size > 0; size -= UE->frame_parms.samples_per_subframe) {
|
||||
int unitTransfer=size>UE->frame_parms.samples_per_subframe ? UE->frame_parms.samples_per_subframe : size ;
|
||||
// we write before read because gNB waits for UE to write and both executions halt
|
||||
// this happens here as the read size is samples_per_subframe which is very much larger than samp_per_slot
|
||||
if (IS_SOFTMODEM_RFSIM) dummyWrite(UE,*timestamp, unitTransfer);
|
||||
if (IS_SOFTMODEM_RFSIM) dummyWrite(UE,*timestamp, unitTransfer);
|
||||
AssertFatal(unitTransfer ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
timestamp,
|
||||
@@ -738,28 +798,305 @@ int computeSamplesShift(PHY_VARS_NR_UE *UE) {
|
||||
int samples_shift = -(UE->rx_offset>>1);
|
||||
if (samples_shift != 0) {
|
||||
LOG_I(NR_PHY,"Adjusting frame in time by %i samples\n", samples_shift);
|
||||
UE->rx_offset = 0; // reset so that it is not applied falsely in case of SSB being only in every second frame
|
||||
if (get_softmodem_params()->sl_mode == 0) {
|
||||
UE->rx_offset = 0; // reset so that it is not applied falsely in case of SSB being only in every second frame
|
||||
} else {
|
||||
UE->rx_offset_sl = 0; // reset so that it is not applied falsely in case of SSB being only in every second frame
|
||||
}
|
||||
UE->max_pos_fil += samples_shift << 15; // reset IIR filter when sample shift is applied
|
||||
}
|
||||
return samples_shift;
|
||||
}
|
||||
|
||||
static inline int get_firstSymSamp(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
|
||||
static inline int get_firstSymSamp(uint16_t slot, NR_DL_FRAME_PARMS *fp, bool sync) {
|
||||
uint16_t nb_prefix_samples0 = fp->nb_prefix_samples0;
|
||||
if (get_softmodem_params()->sl_mode != 0) {
|
||||
nb_prefix_samples0 = sync ? fp->nb_prefix_samples0 : fp->nb_prefix_samples;
|
||||
}
|
||||
if (fp->numerology_index == 0)
|
||||
return fp->nb_prefix_samples0 + fp->ofdm_symbol_size;
|
||||
int num_samples = (slot%(fp->slots_per_subframe/2)) ? fp->nb_prefix_samples : fp->nb_prefix_samples0;
|
||||
int num_samples = (slot % (fp->slots_per_subframe / 2)) ? fp->nb_prefix_samples : nb_prefix_samples0;
|
||||
num_samples += fp->ofdm_symbol_size;
|
||||
return num_samples;
|
||||
}
|
||||
|
||||
static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
|
||||
int rem_samples = fp->get_samples_per_slot(slot, fp) - get_firstSymSamp(slot, fp);
|
||||
static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp, bool sync) {
|
||||
int rem_samples = fp->get_samples_per_slot(slot, fp) - get_firstSymSamp(slot, fp, sync);
|
||||
int next_slot_first_symbol = 0;
|
||||
if (slot < (fp->slots_per_frame-1))
|
||||
next_slot_first_symbol = get_firstSymSamp(slot+1, fp);
|
||||
next_slot_first_symbol = get_firstSymSamp(slot+1, fp, sync);
|
||||
return rem_samples + next_slot_first_symbol;
|
||||
}
|
||||
|
||||
int slot_to_flag_sl(uint8_t tdd_period, int slot, uint16_t slot_config, uint16_t num_slot_frame) {
|
||||
int flag, isUL, isULnext, isULbefore;
|
||||
int num_period_slot = get_nb_periods_per_frame(tdd_period);
|
||||
slot = slot % (num_slot_frame / num_period_slot);
|
||||
isUL = (slot_config >> slot) & 0x1;// indicator to show if the slot is UL or DL
|
||||
|
||||
if (slot > 0) {
|
||||
//checking if previous slot is UL
|
||||
isULbefore = (slot_config >> (slot - 1)) & 0x1;
|
||||
} else {
|
||||
isULbefore = 0;
|
||||
}
|
||||
if (slot < (num_slot_frame / num_period_slot) - 1) {
|
||||
// checking if next slot is UL
|
||||
isULnext = (slot_config >> (slot+1)) & 0x1;
|
||||
} else {
|
||||
isULnext = 0;
|
||||
}
|
||||
|
||||
if (isUL) {
|
||||
if (slot == 0 || !isULbefore) {
|
||||
flag = 2; // first slot should start transmission
|
||||
} else if (slot == (num_slot_frame / num_period_slot) - 1 || !isULnext) {
|
||||
flag = 3; // last slot that should stop transmission
|
||||
} else {
|
||||
flag = 1; // it is niether first nor last slot.
|
||||
}
|
||||
} else {
|
||||
flag = 0; // don't transmit at all
|
||||
}
|
||||
LOG_D(NR_PHY, "### slot(%d), UL(%d), flag(%d)\n", slot, isUL, flag);
|
||||
return flag;
|
||||
}
|
||||
|
||||
void *UE_thread_SL(void *arg) {
|
||||
PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg;
|
||||
openair0_timestamp timestamp, writeTimestamp;
|
||||
void *rxp[NB_ANTENNAS_RX], *txp[NB_ANTENNAS_TX];
|
||||
AssertFatal(0 == openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]), "");
|
||||
UE->rfdevice.host_type = RAU_HOST;
|
||||
AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n");
|
||||
|
||||
notifiedFIFO_t nf;
|
||||
initNotifiedFIFO(&nf);
|
||||
notifiedFIFO_t freeBlocks;
|
||||
initNotifiedFIFO_nothreadSafe(&freeBlocks);
|
||||
int nbSlotProcessing = 0;
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(0);
|
||||
int timing_advance = UE->timing_advance;
|
||||
|
||||
UE->lost_sync_sl = 0;
|
||||
UE->is_synchronized_sl = 0;
|
||||
UE->sync_ref = get_softmodem_params()->sync_ref;
|
||||
bool sync_running_sl = false;
|
||||
const int nb_slot_frame = UE->frame_parms.slots_per_frame;
|
||||
int absolute_slot = 0, decoded_frame_rx = INT_MAX, trashed_frames = 0, start_rx_stream = 0;
|
||||
|
||||
for (int i = 0; i < NR_RX_NB_TH + 1; i++) {// NR_RX_NB_TH working + 1 we are making to be pushed
|
||||
notifiedFIFO_elt_t *newElt = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), RX_JOB_ID, &nf, processSlotRX_SL);
|
||||
nr_rxtx_thread_data_t *curMsg=(nr_rxtx_thread_data_t *)NotifiedFifoData(newElt);
|
||||
initNotifiedFIFO(&curMsg->txFifo);
|
||||
pushNotifiedFIFO_nothreadSafe(&freeBlocks, newElt);
|
||||
}
|
||||
|
||||
while (!oai_exit) {
|
||||
if (UE->lost_sync_sl && UE->sync_ref == 0) {
|
||||
LOG_I(NR_PHY, "Sync UE: lost_sync status\n");
|
||||
int nb = abortTpoolJob(&(get_nrUE_params()->Tpool),RX_JOB_ID);
|
||||
nb += abortNotifiedFIFOJob(&nf, RX_JOB_ID);
|
||||
LOG_I(PHY,"Number of aborted slots %d\n",nb);
|
||||
for (int i=0; i<nb; i++)
|
||||
pushNotifiedFIFO_nothreadSafe(&freeBlocks, newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), RX_JOB_ID, &nf, processSlotRX_SL));
|
||||
nbSlotProcessing = 0;
|
||||
UE->is_synchronized_sl = 0;
|
||||
UE->lost_sync_sl = 0;
|
||||
}
|
||||
|
||||
if (sync_running_sl && UE->sync_ref == 0) {
|
||||
LOG_I(NR_PHY, "Nearby UE: sync_running status.\n");
|
||||
notifiedFIFO_elt_t *res=tryPullTpool(&nf,&(get_nrUE_params()->Tpool));
|
||||
if (res) {
|
||||
sync_running_sl = false;
|
||||
LOG_I(NR_PHY, "Nearby UE: sync_running was set to false due to valid res.\n");
|
||||
syncData_t *tmp=(syncData_t *)NotifiedFifoData(res);
|
||||
LOG_I(NR_PHY, "Nearby UE: UE->is_synchronized_sl = %d\n", UE->is_synchronized_sl);
|
||||
if (UE->is_synchronized_sl && get_softmodem_params()->sl_mode < 2) {
|
||||
decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx);
|
||||
// shift the frame index with all the frames we trashed meanwhile we perform the synch search
|
||||
decoded_frame_rx=(decoded_frame_rx + UE->init_sync_frame + trashed_frames) % MAX_FRAME_NUMBER;
|
||||
}
|
||||
delNotifiedFIFO_elt(res);
|
||||
start_rx_stream = 0;
|
||||
} else {
|
||||
LOG_I(PHY, "Nearby UE: sync_running_sl still in readFrame due to INVALID res.\n");
|
||||
readFrame(UE, ×tamp, true);
|
||||
trashed_frames += 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
AssertFatal(!sync_running_sl, "At this point synchronization can't be running\n");
|
||||
|
||||
if (UE->is_synchronized_sl == 0 && UE->sync_ref == 0) {
|
||||
LOG_I(NR_PHY, "Sync UE: UE->is_synchronized_sl == 0 && UE->sync_ref == 0)\n");
|
||||
readFrame(UE, ×tamp, false);
|
||||
notifiedFIFO_elt_t *Msg=newNotifiedFIFO_elt(sizeof(syncData_t), 0, &nf, UE_synch);
|
||||
syncData_t *syncMsg = (syncData_t *)NotifiedFifoData(Msg);
|
||||
syncMsg->UE = UE;
|
||||
memset(&syncMsg->proc, 0, sizeof(syncMsg->proc));
|
||||
pushTpool(&(get_nrUE_params()->Tpool), Msg);
|
||||
trashed_frames=0;
|
||||
sync_running_sl =true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (start_rx_stream == 0 && UE->sync_ref == 0) {
|
||||
start_rx_stream = 1;
|
||||
syncInFrame(UE, ×tamp);
|
||||
LOG_I(NR_PHY, "Sync UE: rx_stream = 1 and timestamp %ld\n", timestamp);
|
||||
UE->rx_offset_sl = 0;
|
||||
UE->time_sync_cell = 0;
|
||||
uint16_t nb_prefix_samples0 = UE->is_synchronized_sl ? UE->frame_parms.nb_prefix_samples0 :
|
||||
UE->frame_parms.nb_prefix_samples;
|
||||
AssertFatal (UE->frame_parms.ofdm_symbol_size + nb_prefix_samples0 ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
×tamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
UE->frame_parms.ofdm_symbol_size + nb_prefix_samples0,
|
||||
UE->frame_parms.nb_antennas_rx), "Could not read in first symbol");
|
||||
// we have the decoded frame index in the return of the synch process
|
||||
// and we shifted above to the first slot of next frame
|
||||
decoded_frame_rx++;
|
||||
// we do ++ first in the regular processing, so it will be begin of frame;
|
||||
absolute_slot = decoded_frame_rx * nb_slot_frame - 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
absolute_slot++;
|
||||
// Fix me: will be wrong when slot 1 is slow, as slot 2 finishes
|
||||
// Slot 3 will overlap if NR_RX_NB_TH is 2
|
||||
// this is general failure in UE !!
|
||||
int slot_nr = absolute_slot % nb_slot_frame;
|
||||
|
||||
notifiedFIFO_elt_t *msgToPush;
|
||||
AssertFatal((msgToPush=pullNotifiedFIFO_nothreadSafe(&freeBlocks)) != NULL,"chained list failure");
|
||||
nr_rxtx_thread_data_t *curMsg=(nr_rxtx_thread_data_t *)NotifiedFifoData(msgToPush);
|
||||
curMsg->UE = UE;
|
||||
// update thread index for received subframe
|
||||
curMsg->proc.CC_id = UE->CC_id;
|
||||
curMsg->proc.nr_slot_rx = slot_nr;
|
||||
curMsg->proc.nr_slot_tx = (absolute_slot + DURATION_RX_TO_TX) % nb_slot_frame;
|
||||
curMsg->proc.frame_rx = (absolute_slot/nb_slot_frame) % MAX_FRAME_NUMBER;
|
||||
curMsg->proc.frame_tx = ((absolute_slot+DURATION_RX_TO_TX)/nb_slot_frame) % MAX_FRAME_NUMBER;
|
||||
curMsg->proc.decoded_frame_rx=-1;
|
||||
LOG_D(NR_PHY, "Process slot %d total gain %d\n", slot_nr, UE->rx_total_gain_dB);
|
||||
|
||||
int firstSymSamp = get_firstSymSamp(slot_nr, &UE->frame_parms, UE->is_synchronized_sl);
|
||||
uint64_t write_time_stamp = UE->frame_parms.get_samples_slot_timestamp(slot_nr, &UE->frame_parms, 0);
|
||||
uint64_t read_time_stamp = UE->frame_parms.get_samples_slot_timestamp(slot_nr, &UE->frame_parms, 0);
|
||||
for (int i = 0; i<UE->frame_parms.nb_antennas_rx; i++)
|
||||
rxp[i] = (void *)&UE->common_vars.rxdata[i][read_time_stamp];
|
||||
for (int i = 0; i < UE->frame_parms.nb_antennas_tx; i++)
|
||||
txp[i] = (void *)&UE->common_vars.txdata[i][write_time_stamp];
|
||||
|
||||
int readBlockSize, writeBlockSize;
|
||||
if (slot_nr < (nb_slot_frame - 1)) {
|
||||
readBlockSize = get_readBlockSize(slot_nr, &UE->frame_parms, UE->is_synchronized_sl);
|
||||
writeBlockSize = UE->frame_parms.get_samples_per_slot(slot_nr, &UE->frame_parms);
|
||||
} else {
|
||||
UE->rx_offset_diff = computeSamplesShift(UE);
|
||||
readBlockSize = get_readBlockSize(slot_nr, &UE->frame_parms, UE->is_synchronized_sl) - UE->rx_offset_diff;
|
||||
writeBlockSize = UE->frame_parms.get_samples_per_slot(slot_nr, &UE->frame_parms) - UE->rx_offset_diff;
|
||||
}
|
||||
|
||||
AssertFatal(readBlockSize ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
×tamp,
|
||||
rxp,
|
||||
readBlockSize,
|
||||
UE->frame_parms.nb_antennas_rx), "");
|
||||
|
||||
if (slot_nr == (nb_slot_frame - 1)) {
|
||||
// read in first symbol of next frame and adjust for timing drift
|
||||
uint16_t nb_prefix_samples0 = UE->is_synchronized_sl ? UE->frame_parms.nb_prefix_samples0 :
|
||||
UE->frame_parms.nb_prefix_samples;
|
||||
int first_symbols = UE->frame_parms.ofdm_symbol_size + nb_prefix_samples0;
|
||||
if (first_symbols > 0) {
|
||||
openair0_timestamp ignore_timestamp;
|
||||
AssertFatal(first_symbols ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
&ignore_timestamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
first_symbols,
|
||||
UE->frame_parms.nb_antennas_rx),"");
|
||||
} else {
|
||||
LOG_E(NR_PHY, "Can't compensate: diff =%d\n", first_symbols);
|
||||
}
|
||||
}
|
||||
|
||||
curMsg->proc.timestamp_tx = timestamp +
|
||||
UE->frame_parms.get_samples_slot_timestamp(slot_nr, &UE->frame_parms, DURATION_RX_TO_TX) -
|
||||
firstSymSamp;
|
||||
|
||||
while (nbSlotProcessing >= NR_RX_NB_TH) {
|
||||
notifiedFIFO_elt_t *res = pullTpool(&nf, &(get_nrUE_params()->Tpool));
|
||||
if (res == NULL)
|
||||
break; // Tpool has been stopped
|
||||
nbSlotProcessing--;
|
||||
nr_rxtx_thread_data_t *tmp = (nr_rxtx_thread_data_t *)res->msgData;
|
||||
if (tmp->proc.decoded_frame_rx != -1)
|
||||
decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >>
|
||||
mac->mib->systemFrameNumber.bits_unused) << 4) |
|
||||
tmp->proc.decoded_frame_rx);
|
||||
else
|
||||
decoded_frame_rx=-1;
|
||||
pushNotifiedFIFO_nothreadSafe(&freeBlocks,res);
|
||||
}
|
||||
|
||||
if (UE->sync_ref == 0 && decoded_frame_rx > 0 && decoded_frame_rx != curMsg->proc.frame_rx)
|
||||
LOG_E(NR_PHY, "Sync UE: Decoded frame index (%d) is not compatible with current context (%d), "
|
||||
"UE should go back to synch mode\n", decoded_frame_rx, curMsg->proc.frame_rx);
|
||||
|
||||
// use previous timing_advance value to compute writeTimestamp
|
||||
writeTimestamp = timestamp +
|
||||
UE->frame_parms.get_samples_slot_timestamp(slot_nr, &UE->frame_parms, DURATION_RX_TO_TX - NR_RX_NB_TH) -
|
||||
firstSymSamp - openair0_cfg[0].tx_sample_advance - UE->N_TA_offset - timing_advance;
|
||||
|
||||
// but use current UE->timing_advance value to compute writeBlockSize
|
||||
if (UE->timing_advance != timing_advance) {
|
||||
writeBlockSize -= UE->timing_advance - timing_advance;
|
||||
timing_advance = UE->timing_advance;
|
||||
}
|
||||
|
||||
int flags = 1;
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
flags = slot_to_flag_sl(fp->tdd_period, slot_nr, fp->tdd_slot_config, fp->slots_per_frame);
|
||||
|
||||
if (flags || IS_SOFTMODEM_RFSIM) {
|
||||
LOG_D(NR_PHY, "current slot goring to write USRP: %d\n", slot_nr);
|
||||
AssertFatal(writeBlockSize ==
|
||||
UE->rfdevice.trx_write_func(&UE->rfdevice,
|
||||
writeTimestamp,
|
||||
txp,
|
||||
writeBlockSize,
|
||||
UE->frame_parms.nb_antennas_tx,
|
||||
flags), "");
|
||||
}
|
||||
#ifdef DEBUG_PHY_SL_PROC
|
||||
char buffer[UE->frame_parms.ofdm_symbol_size];
|
||||
for (int i = 0; i < 13; i++) {
|
||||
bzero(buffer, sizeof(buffer));
|
||||
LOG_I(NR_PHY, "Transmitted SSB %d = %s\n",
|
||||
i, hexdump(&txp[0][UE->frame_parms.ofdm_symbol_size*i],
|
||||
UE->frame_parms.ofdm_symbol_size, buffer, sizeof(buffer)));
|
||||
}
|
||||
#endif
|
||||
for (int i = 0; i < UE->frame_parms.nb_antennas_tx; i++) {
|
||||
memset(txp[i], 0, writeBlockSize);
|
||||
}
|
||||
nbSlotProcessing++;
|
||||
LOG_D(NR_PHY, "Number of slots being processed at the moment: %d\n", nbSlotProcessing);
|
||||
pushTpool(&(get_nrUE_params()->Tpool), msgToPush);
|
||||
} // while !oai_exit
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *UE_thread(void *arg) {
|
||||
//this thread should be over the processing thread to keep in real time
|
||||
PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg;
|
||||
@@ -897,7 +1234,7 @@ void *UE_thread(void *arg) {
|
||||
}*/
|
||||
#endif
|
||||
|
||||
int firstSymSamp = get_firstSymSamp(slot_nr, &UE->frame_parms);
|
||||
int firstSymSamp = get_firstSymSamp(slot_nr, &UE->frame_parms, UE->is_synchronized);
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
|
||||
rxp[i] = (void *)&UE->common_vars.rxdata[i][firstSymSamp+
|
||||
UE->frame_parms.get_samples_slot_timestamp(slot_nr,&UE->frame_parms,0)];
|
||||
@@ -905,11 +1242,11 @@ void *UE_thread(void *arg) {
|
||||
int readBlockSize, writeBlockSize;
|
||||
|
||||
if (slot_nr<(nb_slot_frame - 1)) {
|
||||
readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms);
|
||||
readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms, UE->is_synchronized);
|
||||
writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX) % nb_slot_frame, &UE->frame_parms);
|
||||
} else {
|
||||
UE->rx_offset_diff = computeSamplesShift(UE);
|
||||
readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms) -
|
||||
readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms, UE->is_synchronized) -
|
||||
UE->rx_offset_diff;
|
||||
writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX) % nb_slot_frame, &UE->frame_parms)- UE->rx_offset_diff;
|
||||
}
|
||||
@@ -1004,18 +1341,27 @@ void init_NR_UE(int nb_inst,
|
||||
}
|
||||
|
||||
void init_NR_UE_threads(int nb_inst) {
|
||||
int inst;
|
||||
|
||||
pthread_t threads[nb_inst];
|
||||
pthread_t threadsSL[nb_inst];
|
||||
|
||||
for (inst=0; inst < nb_inst; inst++) {
|
||||
for (int inst = 0; inst < nb_inst; inst++) {
|
||||
PHY_VARS_NR_UE *UE = PHY_vars_UE_g[inst][0];
|
||||
|
||||
LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]);
|
||||
threadCreate(&threads[inst], UE_thread, (void *)UE, "UEthread", -1, OAI_PRIORITY_RT_MAX);
|
||||
if (!IS_SOFTMODEM_NOSTATS_BIT) {
|
||||
pthread_t stat_pthread;
|
||||
threadCreate(&stat_pthread, nrL1_UE_stats_thread, UE, "L1_UE_stats", -1, OAI_PRIORITY_RT_LOW);
|
||||
if (get_softmodem_params()->sl_mode == 0) {
|
||||
LOG_I(NR_PHY, "Intializing UE Threads for instance %d (%p,%p)...\n", inst, PHY_vars_UE_g[inst], PHY_vars_UE_g[inst][0]);
|
||||
threadCreate(&threads[inst], UE_thread, (void *)UE, "UEthread", -1, OAI_PRIORITY_RT_MAX);
|
||||
if (!IS_SOFTMODEM_NOSTATS_BIT) {
|
||||
pthread_t stat_pthread;
|
||||
threadCreate(&stat_pthread, nrL1_UE_stats_thread, UE, "L1_UE_stats", -1, OAI_PRIORITY_RT_LOW);
|
||||
}
|
||||
}
|
||||
else if (get_softmodem_params()->sl_mode == 2) {
|
||||
LOG_I(NR_PHY, "Intializing Sidelink UE Threads for instance %d (%p,%p)...\n", inst, PHY_vars_UE_g[inst], PHY_vars_UE_g[inst][0]);
|
||||
threadCreate(&threadsSL[inst], UE_thread_SL, (void *)UE, "UEthreadSL", -1, OAI_PRIORITY_RT_MAX);
|
||||
}
|
||||
else {
|
||||
LOG_I(NR_PHY,"Need implementation...\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ unsigned short config_frames[4] = {2,9,11,13};
|
||||
#include "nr_nas_msg_sim.h"
|
||||
#include <openair1/PHY/MODULATION/nr_modulation.h>
|
||||
#include "openair2/GNB_APP/gnb_paramdef.h"
|
||||
#include <openair1/PHY/NR_REFSIG/sss_nr.h>
|
||||
|
||||
extern const char *duplex_mode[];
|
||||
THREAD_STRUCT thread_struct;
|
||||
@@ -128,6 +129,7 @@ int dumpframe = 0;
|
||||
|
||||
uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
uint64_t sidelink_frequency[MAX_NUM_CCs][4];
|
||||
int rx_input_level_dBm;
|
||||
|
||||
#if MAX_NUM_CCs == 1
|
||||
@@ -143,7 +145,6 @@ double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}};
|
||||
// UE and OAI config variables
|
||||
|
||||
openair0_config_t openair0_cfg[MAX_CARDS];
|
||||
int16_t node_synch_ref[MAX_NUM_CCs];
|
||||
int otg_enabled;
|
||||
double cpuf;
|
||||
|
||||
@@ -163,6 +164,7 @@ uint32_t N_RB_DL = 106;
|
||||
uint8_t abstraction_flag=0;
|
||||
|
||||
nr_bler_struct nr_bler_data[NR_NUM_MCS];
|
||||
nr_bler_struct nr_mimo_bler_data[NR_NUM_MCS];
|
||||
|
||||
static void init_bler_table(char*);
|
||||
|
||||
@@ -259,6 +261,81 @@ nrUE_params_t *get_nrUE_params(void) {
|
||||
return &nrUE_params;
|
||||
}
|
||||
|
||||
static void nr_phy_config_request_sl(PHY_VARS_NR_UE *ue,
|
||||
int N_RB_DL,
|
||||
int N_RB_UL,
|
||||
int CC_id)
|
||||
{
|
||||
uint64_t rev_burst = 0;
|
||||
uint64_t SSB_positions = 0x01;
|
||||
int mu = 1;
|
||||
uint8_t n_tx = 1;
|
||||
uint8_t n_rx = 1;
|
||||
uint16_t Nid_cell = 0;
|
||||
int ssb_subcarrier_offset = 0;
|
||||
for (int i = 0; i < 64; i++)
|
||||
rev_burst |= (((SSB_positions >> (63-i))&0x01) << i);
|
||||
|
||||
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
fapi_nr_config_request_t *nrUE_config = &ue->nrUE_config;
|
||||
nrUE_config->cell_config.phy_cell_id = get_softmodem_params()->nid1 + get_softmodem_params()->nid2 * NUMBER_SSS_SEQUENCE;
|
||||
nrUE_config->ssb_config.scs_common = mu;
|
||||
nrUE_config->ssb_table.ssb_subcarrier_offset = 0;
|
||||
nrUE_config->ssb_table.ssb_offset_point_a = 0;
|
||||
nrUE_config->ssb_table.ssb_mask_list[1].ssb_mask = (rev_burst)&(0xFFFFFFFF);
|
||||
nrUE_config->ssb_table.ssb_mask_list[0].ssb_mask = (rev_burst>>32)&(0xFFFFFFFF);
|
||||
nrUE_config->cell_config.frame_duplex_type = TDD;
|
||||
nrUE_config->ssb_table.ssb_period = 1; //10ms
|
||||
nrUE_config->carrier_config.dl_grid_size[mu] = N_RB_DL;
|
||||
nrUE_config->carrier_config.ul_grid_size[mu] = N_RB_UL;
|
||||
nrUE_config->carrier_config.num_tx_ant = fp->nb_antennas_tx;
|
||||
nrUE_config->carrier_config.num_rx_ant = fp->nb_antennas_rx;
|
||||
nrUE_config->tdd_table.tdd_period = 0;
|
||||
nrUE_config->carrier_config.dl_frequency = downlink_frequency[CC_id][0] / 1000;
|
||||
nrUE_config->carrier_config.uplink_frequency = downlink_frequency[CC_id][0] / 1000;
|
||||
nrUE_config->carrier_config.sl_frequency = sidelink_frequency[CC_id][0] / 1000;
|
||||
LOG_D(NR_PHY, "SL Frequency %u\n", nrUE_config->carrier_config.sl_frequency);
|
||||
fp->tdd_period = 6; // 6 indicates 5ms (see get_nb_periods_per_frame())
|
||||
fp->tdd_slot_config = 0b0000111111; // 1 -> UL, 0-> DL for each slot , LSB is the slot 0
|
||||
fp->dl_CarrierFreq = 2600000000;
|
||||
fp->ul_CarrierFreq = 2600000000;
|
||||
fp->nb_antennas_tx = n_tx;
|
||||
fp->nb_antennas_rx = n_rx;
|
||||
fp->nb_antenna_ports_gNB = n_tx;
|
||||
fp->N_RB_DL = N_RB_DL;
|
||||
fp->Nid_cell = Nid_cell;
|
||||
fp->Nid_SL = get_softmodem_params()->nid1 + get_softmodem_params()->nid2 * NUMBER_SSS_SEQUENCE;;
|
||||
fp->nushift = 0; //No nushift in SL
|
||||
fp->ssb_type = nr_ssb_type_C; //Note: case c for NR SL???
|
||||
fp->freq_range = mu < 2 ? nr_FR1 : nr_FR2;
|
||||
fp->nr_band = get_softmodem_params()->band; //Note: NR SL uses for n38 and n47
|
||||
fp->threequarter_fs = 0;
|
||||
fp->ofdm_offset_divisor = UINT_MAX;
|
||||
fp->first_carrier_offset = 0;
|
||||
fp->ssb_start_subcarrier = 12 * ue->nrUE_config.ssb_table.ssb_offset_point_a + ssb_subcarrier_offset;
|
||||
int bw_index = get_supported_band_index(mu, fp->nr_band, N_RB_DL);
|
||||
nrUE_config->carrier_config.dl_bandwidth = get_supported_bw_mhz(fp->nr_band > 256 ? FR2 : FR1, bw_index);
|
||||
|
||||
ue->slss = calloc(1, sizeof(*ue->slss));
|
||||
int len = sizeof(ue->slss->sl_mib) / sizeof(ue->slss->sl_mib[0]);
|
||||
for (int i = 0; i < len; i++) {
|
||||
ue->slss->sl_mib[i] = 0;
|
||||
}
|
||||
ue->slss->sl_mib_length = 32;
|
||||
ue->slss->sl_numssb_withinperiod_r16 = 16;
|
||||
ue->slss->sl_timeinterval_r16 = 20;
|
||||
ue->slss->sl_timeoffsetssb_r16 = 0;
|
||||
ue->slss->sl_numssb_withinperiod_r16_copy = 16;
|
||||
ue->slss->sl_timeinterval_r16_copy = 20;
|
||||
ue->slss->sl_timeoffsetssb_r16_copy = 0;
|
||||
ue->slss->slss_id = get_softmodem_params()->nid1 + get_softmodem_params()->nid2 * NUMBER_SSS_SEQUENCE;;
|
||||
ue->is_synchronized_sl = 0;
|
||||
ue->UE_fo_compensation = 0;
|
||||
ue->sync_ref = get_softmodem_params()->sync_ref;
|
||||
LOG_I(NR_PHY, "nrUE configured\n");
|
||||
}
|
||||
|
||||
|
||||
static void get_options(void) {
|
||||
|
||||
paramdef_t cmdline_params[] =CMDLINE_NRUEPARAMS_DESC ;
|
||||
@@ -321,7 +398,7 @@ void init_openair0(void) {
|
||||
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;
|
||||
uint64_t dl_carrier, ul_carrier, sl_carrier;
|
||||
openair0_cfg[card].configFilename = NULL;
|
||||
openair0_cfg[card].threequarter_fs = frame_parms->threequarter_fs;
|
||||
openair0_cfg[card].sample_rate = frame_parms->samples_per_subframe * 1e3;
|
||||
@@ -348,8 +425,15 @@ void init_openair0(void) {
|
||||
duplex_mode[openair0_cfg[card].duplex_mode]);
|
||||
|
||||
nr_get_carrier_frequencies(PHY_vars_UE_g[0][0], &dl_carrier, &ul_carrier);
|
||||
|
||||
LOG_I(NR_PHY,"Configuring SL carrier for %llu Hz \n",sl_carrier);
|
||||
nr_rf_card_config_freq(&openair0_cfg[card], ul_carrier, dl_carrier, freq_off);
|
||||
|
||||
if (get_softmodem_params()->sl_mode != 0) {
|
||||
nr_get_carrier_frequencies_sl(PHY_vars_UE_g[0][0], &sl_carrier);
|
||||
LOG_I(NR_PHY,"Configuring SL carrier for %llu Hz \n",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;
|
||||
@@ -508,8 +592,14 @@ int main( int argc, char **argv ) {
|
||||
|
||||
set_options(CC_id, UE[CC_id]);
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(0);
|
||||
|
||||
if (get_softmodem_params()->sa) { // set frame config to initial values from command line and assume that the SSB is centered on the grid
|
||||
if (get_softmodem_params()->sl_mode != 0) {
|
||||
uint16_t nr_band = get_band(sidelink_frequency[CC_id][0],0);
|
||||
mac->if_module = NULL;
|
||||
LOG_I(HW, "Setting mac->if_module = NULL b/c we config PHY in nr_phy_config_request_sl (for now - TODO)\n");
|
||||
nr_phy_config_request_sl(UE[CC_id], N_RB_DL, N_RB_DL, CC_id);
|
||||
nr_init_frame_parms_ue_sl(&UE[CC_id]->frame_parms,sidelink_frequency[CC_id][0],nr_band);
|
||||
}
|
||||
if (get_softmodem_params()->sa) {
|
||||
uint16_t nr_band = get_band(downlink_frequency[CC_id][0],uplink_frequency_offset[CC_id][0]);
|
||||
mac->nr_band = nr_band;
|
||||
nr_init_frame_parms_ue_sa(&UE[CC_id]->frame_parms,
|
||||
@@ -517,15 +607,15 @@ int main( int argc, char **argv ) {
|
||||
uplink_frequency_offset[CC_id][0],
|
||||
get_softmodem_params()->numerology,
|
||||
nr_band);
|
||||
}
|
||||
else{
|
||||
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;
|
||||
fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config;
|
||||
|
||||
nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config,
|
||||
*mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]);
|
||||
} else {
|
||||
if (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;
|
||||
}
|
||||
nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, &UE[CC_id]->nrUE_config,
|
||||
((get_softmodem_params()->sl_mode == 0) ?
|
||||
*mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0] :
|
||||
UE[CC_id]->frame_parms.nr_band));
|
||||
}
|
||||
|
||||
init_nr_ue_vars(UE[CC_id], 0, abstraction_flag);
|
||||
@@ -636,3 +726,56 @@ static void init_bler_table(char *env_string) {
|
||||
fclose(pFile);
|
||||
}
|
||||
}
|
||||
|
||||
// Read in each MCS file and build BLER-SINR-TB table
|
||||
static void init_mimo_bler_table(void) {
|
||||
memset(nr_mimo_bler_data, 0, sizeof(nr_mimo_bler_data));
|
||||
|
||||
const char *awgn_results_dir = getenv("NR_MIMO2x2_AWGN_RESULTS_DIR");
|
||||
if (!awgn_results_dir) {
|
||||
LOG_W(NR_MAC, "No $NR_MIMO2x2_AWGN_RESULTS_DIR\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < NR_NUM_MCS; i++) {
|
||||
char fName[1024];
|
||||
snprintf(fName, sizeof(fName), "%s/mcs%d_cdlc_mimo2x2_dl.csv", awgn_results_dir, i);
|
||||
FILE *pFile = fopen(fName, "r");
|
||||
if (!pFile) {
|
||||
LOG_E(NR_MAC, "open %s: %s\n", fName, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
size_t bufSize = 1024;
|
||||
char * line = NULL;
|
||||
char * token;
|
||||
char * temp = NULL;
|
||||
int nlines = 0;
|
||||
while (getline(&line, &bufSize, pFile) > 0) {
|
||||
if (!strncmp(line, "SNR", 3)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nlines > NR_NUM_SINR) {
|
||||
LOG_E(NR_MAC, "BLER FILE ERROR - num lines greater than expected - file: %s\n", fName);
|
||||
abort();
|
||||
}
|
||||
|
||||
token = strtok_r(line, ";", &temp);
|
||||
int ncols = 0;
|
||||
while (token != NULL) {
|
||||
if (ncols > NUM_BLER_COL) {
|
||||
LOG_E(NR_MAC, "BLER FILE ERROR - num of cols greater than expected\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
nr_mimo_bler_data[i].bler_table[nlines][ncols] = strtof(token, NULL);
|
||||
ncols++;
|
||||
|
||||
token = strtok_r(NULL, ";", &temp);
|
||||
}
|
||||
nlines++;
|
||||
}
|
||||
nr_mimo_bler_data[i].length = nlines;
|
||||
fclose(pFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
{"uecap_file", CONFIG_HLP_UECAP_FILE, 0, .strptr=&uecap_file, .defstrval="./uecap_ports1.xml", TYPE_STRING, 0}, \
|
||||
{"rrc_config_path", CONFIG_HLP_RRC_CFG_PATH, 0, .strptr=&rrc_config_path, .defstrval="./", TYPE_STRING, 0}, \
|
||||
{"ue-idx-standalone", NULL, 0, .u16ptr=&ue_idx_standalone, .defuintval=0xFFFF, TYPE_UINT16, 0}, \
|
||||
{"SLC", CONFIG_HLP_SLF, 0, .u64ptr=&(sidelink_frequency[0][0]), .defuintval=2600000000, TYPE_UINT64, 0}, \
|
||||
{"ue-rxgain", CONFIG_HLP_UERXG, 0, .dblptr=&(rx_gain[0][0]), .defdblval=110, TYPE_DOUBLE, 0}, \
|
||||
{"ue-rxgain-off", CONFIG_HLP_UERXGOFF, 0, .dblptr=&rx_gain_off, .defdblval=0, TYPE_DOUBLE, 0}, \
|
||||
{"ue-txgain", CONFIG_HLP_UETXG, 0, .dblptr=&(tx_gain[0][0]), .defdblval=0, TYPE_DOUBLE, 0}, \
|
||||
|
||||
@@ -55,8 +55,10 @@ extern "C"
|
||||
|
||||
#define CONFIG_HLP_DUMPFRAME "dump UE received frame to rxsig_frame0.dat and exit\n"
|
||||
#define CONFIG_HLP_PHYTST "test UE phy layer, mac disabled\n"
|
||||
#define CONFIG_HLP_SL_PHYTST "test SL UE phy layer, mac disabled\n"
|
||||
#define CONFIG_HLP_DORA "test gNB and UE with RA procedures\n"
|
||||
#define CONFIG_HLP_SA "run gNB in standalone mode\n"
|
||||
#define CONFIG_HLP_SL_MODE "sets the NR sidelink mode (0: not in sidelink mode, 1: in-coverage/gNB, 2: out-of-coverage/no gNB)"
|
||||
#define CONFIG_HLP_EXTS "tells hardware to use an external timing reference\n"
|
||||
#define CONFIG_HLP_DMRSSYNC "tells RU to insert DMRS in subframe 1 slot 0"
|
||||
#define CONFIG_HLP_CLK "tells hardware to use a clock reference (0:internal, 1:external, 2:gpsdo)\n"
|
||||
@@ -66,6 +68,7 @@ extern "C"
|
||||
#define CONFIG_HLP_NOSNGLT "Disables single-thread mode in lte-softmodem\n"
|
||||
#define CONFIG_HLP_DLF "Set the downlink frequency for all component carriers\n"
|
||||
#define CONFIG_HLP_ULF "Set the uplink frequency offset for all component carriers\n"
|
||||
#define CONFIG_HLP_SLF "Set the sidelink frequency for all component carriers\n"
|
||||
#define CONFIG_HLP_CHOFF "Channel id offset\n"
|
||||
#define CONFIG_HLP_SOFTS "Enable soft scope and L1 and L2 stats (Xforms)\n"
|
||||
#define CONFIG_HLP_SOFTS_QT "Enable soft scope and L1 and L2 stats (QT)\n"
|
||||
@@ -103,6 +106,9 @@ extern "C"
|
||||
#define CONFIG_L1_EMULATOR "Run in L1 emulated mode (disable PHY layer)\n"
|
||||
#define CONFIG_HLP_CONTINUOUS_TX "perform continuous transmission, even in TDD mode (to work around USRP issues)\n"
|
||||
#define CONFIG_HLP_STATS_DISABLE "disable globally the stats generation and persistence"
|
||||
#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"
|
||||
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* command line parameters common to eNodeB and UE */
|
||||
@@ -111,8 +117,10 @@ extern "C"
|
||||
#define RF_CONFIG_FILE softmodem_params.rf_config_file
|
||||
#define TP_CONFIG softmodem_params.threadPoolConfig
|
||||
#define PHY_TEST softmodem_params.phy_test
|
||||
#define SL_PHY_TEST softmodem_params.sl_phy_test
|
||||
#define DO_RA softmodem_params.do_ra
|
||||
#define SA softmodem_params.sa
|
||||
#define SL_MODE softmodem_params.sl_mode
|
||||
#define WAIT_FOR_SYNC softmodem_params.wait_for_sync
|
||||
#define SINGLE_THREAD_FLAG softmodem_params.single_thread_flag
|
||||
#define CHAIN_OFFSET softmodem_params.chain_offset
|
||||
@@ -132,6 +140,9 @@ extern "C"
|
||||
#define NON_STOP softmodem_params.non_stop
|
||||
#define EMULATE_L1 softmodem_params.emulate_l1
|
||||
#define CONTINUOUS_TX softmodem_params.continuous_tx
|
||||
#define SYNC_REF softmodem_params.sync_ref
|
||||
#define NID1 softmodem_params.nid1
|
||||
#define NID2 softmodem_params.nid2
|
||||
|
||||
#define DEFAULT_RFCONFIG_FILE "/usr/local/etc/syriq/ue.band7.tm1.PRB100.NR40.dat";
|
||||
|
||||
@@ -143,6 +154,8 @@ extern int usrp_tx_thread;
|
||||
{"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, .iptr=&PHY_TEST, .defintval=0, TYPE_INT, 0}, \
|
||||
{"do-ra", CONFIG_HLP_DORA, PARAMFLAG_BOOL, .iptr=&DO_RA, .defintval=0, TYPE_INT, 0}, \
|
||||
{"sa", CONFIG_HLP_SA, PARAMFLAG_BOOL, .iptr=&SA, .defintval=0, TYPE_INT, 0}, \
|
||||
{"sl-mode", CONFIG_HLP_SL_MODE, 0, .u8ptr=&SL_MODE, .defintval=0, TYPE_UINT8, 0}, \
|
||||
{"sync-ref", CONFIG_HLP_SYNC_REF, PARAMFLAG_BOOL, .iptr=&SYNC_REF, .defintval=0, TYPE_INT, 0}, \
|
||||
{"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, .u8ptr=&USIM_TEST, .defintval=0, TYPE_UINT8, 0}, \
|
||||
{"clock-source", CONFIG_HLP_CLK, 0, .uptr=&CLOCK_SOURCE, .defintval=0, TYPE_UINT, 0}, \
|
||||
{"time-source", CONFIG_HLP_TME, 0, .uptr=&TIMING_SOURCE, .defintval=0, TYPE_UINT, 0}, \
|
||||
@@ -174,6 +187,8 @@ extern int usrp_tx_thread;
|
||||
{"emulate-l1", CONFIG_L1_EMULATOR, PARAMFLAG_BOOL, .iptr=&EMULATE_L1, .defintval=0, TYPE_INT, 0}, \
|
||||
{"continuous-tx", CONFIG_HLP_CONTINUOUS_TX, PARAMFLAG_BOOL, .iptr=&CONTINUOUS_TX, .defintval=0, TYPE_INT, 0}, \
|
||||
{"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}, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
@@ -210,6 +225,8 @@ extern int usrp_tx_thread;
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s3a = { config_checkstr_assign_integer, \
|
||||
{"MONOLITHIC", "PNF", "VNF","UE_STUB_PNF","UE_STUB_OFFNET","STANDALONE_PNF"}, \
|
||||
{NFAPI_MONOLITHIC, NFAPI_MODE_PNF, NFAPI_MODE_VNF,NFAPI_UE_STUB_PNF,NFAPI_UE_STUB_OFFNET,NFAPI_MODE_STANDALONE_PNF}, \
|
||||
@@ -218,6 +235,8 @@ extern int usrp_tx_thread;
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
@@ -301,8 +320,10 @@ typedef struct {
|
||||
char *rf_config_file;
|
||||
char *threadPoolConfig;
|
||||
int phy_test;
|
||||
int sl_phy_test;
|
||||
int do_ra;
|
||||
int sa;
|
||||
uint8_t sl_mode;
|
||||
uint8_t usim_test;
|
||||
int emulate_rf;
|
||||
int wait_for_sync; //eNodeB only
|
||||
@@ -324,6 +345,9 @@ typedef struct {
|
||||
int non_stop;
|
||||
int emulate_l1;
|
||||
int continuous_tx;
|
||||
int sync_ref;
|
||||
int nid1;
|
||||
int nid2;
|
||||
} softmodem_params_t;
|
||||
|
||||
extern uint64_t get_softmodem_optmask(void);
|
||||
|
||||
@@ -559,7 +559,9 @@ typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
uint16_t dl_bandwidth;//Carrier bandwidth for DL in MHz [38.104, sec 5.3.2] Values: 5, 10, 15, 20, 25, 30, 40,50, 60, 70, 80,90,100,200,400
|
||||
uint16_t sl_bandwidth; //Carrier bandwidth for SL in MHz [38.101, sec 5.3.5] Values: 10, 20, 30, and 40
|
||||
uint32_t dl_frequency; //Absolute frequency of DL point A in KHz [38.104, sec5.2 and 38.211 sec 4.4.4.2] Value: 450000 -> 52600000
|
||||
uint32_t sl_frequency; //Absolute frequency of SL point A in KHz [38.331, sec6.3.5 and 38.211 sec 8.2.7]
|
||||
uint16_t dl_k0[5];//𝑘_{0}^{𝜇} for each of the numerologies [38.211, sec 5.3.1] Value: 0 ->23699
|
||||
uint16_t dl_grid_size[5];//Grid size 𝑁_{𝑔𝑟𝑖𝑑}^{𝑠𝑖𝑧𝑒,𝜇} for each of the numerologies [38.211, sec 4.4.2] Value: 0->275 0 = this numerology not used
|
||||
uint16_t num_tx_ant;//Number of Tx antennas
|
||||
|
||||
@@ -351,9 +351,17 @@ void applyGtoright(const t_nrPolar_params *pp,decoder_node_t *node) {
|
||||
((__m64 *)alpha_r)[0] = _mm_subs_pi16(((__m64 *)alpha_v)[1],_mm_sign_pi16(((__m64 *)alpha_v)[0],((__m64 *)betal)[0]));
|
||||
}
|
||||
else
|
||||
{// equivalent scalar code to above, activated only on non x86/ARM architectures or Nv=1,2
|
||||
for (int i=0;i<node->Nv/2;i++) {
|
||||
alpha_r[i] = alpha_v[i+(node->Nv/2)] - (betal[i]*alpha_v[i]);
|
||||
{
|
||||
int temp_alpha_r;
|
||||
for (int i = 0; i < node->Nv / 2; i++) {
|
||||
temp_alpha_r = alpha_v[i + (node->Nv / 2)] - (betal[i] * alpha_v[i]);
|
||||
if (temp_alpha_r > SHRT_MAX) {
|
||||
alpha_r[i] = SHRT_MAX;
|
||||
} else if (temp_alpha_r < -SHRT_MAX) {
|
||||
alpha_r[i] = -SHRT_MAX;
|
||||
} else {
|
||||
alpha_r[i] = temp_alpha_r;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node->Nv == 2) { // apply hard decision on right node
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_dci_defs.h"
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_uci_defs.h"
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h"
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h"
|
||||
#include "PHY/CODING/coding_defs.h"
|
||||
//#include "SIMULATION/TOOLS/sim.h"
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#define NR_POLAR_PBCH_AGGREGATION_LEVEL 0 //uint8_t
|
||||
#define NR_POLAR_PBCH_MESSAGE_TYPE 0 //int8_t
|
||||
#define NR_POLAR_PSBCH_MESSAGE_TYPE 3 //int8_t
|
||||
#define NR_POLAR_PBCH_PAYLOAD_BITS 32 //uint16_t
|
||||
#define NR_POLAR_PBCH_CRC_PARITY_BITS 24
|
||||
#define NR_POLAR_PBCH_CRC_ERROR_CORRECTION_BITS 3
|
||||
@@ -52,6 +53,8 @@
|
||||
#define NR_POLAR_PBCH_I_BIL 0 //uint8_t
|
||||
#define NR_POLAR_PBCH_E 864 //uint16_t
|
||||
#define NR_POLAR_PBCH_E_DWORD 27 // NR_POLAR_PBCH_E/32
|
||||
#define NR_POLAR_PSBCH_E 1792 //uint16_t
|
||||
#define NR_POLAR_PSBCH_E_DWORD 56 // NR_POLAR_PSBCH_E/32
|
||||
|
||||
/*
|
||||
* TEST CODE
|
||||
|
||||
70
openair1/PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h
Normal file
70
openair1/PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h
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/CODING/nrPolar_tools/nr_polar_psbch_defs.h
|
||||
* \brief Defines the constant variables for polar coding of the PSBCH from 38-212, V15.1.1 2018-04.
|
||||
* \author Turker Yilmaz
|
||||
* \date 2018
|
||||
* \version 0.1
|
||||
* \company EURECOM
|
||||
* \email turker.yilmaz@eurecom.fr
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#ifndef __NR_POLAR_PSBCH_DEFS__H__
|
||||
#define __NR_POLAR_PSBCH_DEFS__H__
|
||||
|
||||
#define NR_POLAR_PSBCH_AGGREGATION_LEVEL 0 //uint8_t
|
||||
#define NR_POLAR_PSBCH_MESSAGE_TYPE 3 //int8_t
|
||||
#define NR_POLAR_PSBCH_PAYLOAD_BITS 32 //uint16_t
|
||||
#define NR_POLAR_PSBCH_CRC_PARITY_BITS 24
|
||||
#define NR_POLAR_PSBCH_CRC_ERROR_CORRECTION_BITS 3
|
||||
//Assumed 3 by 3GPP when NR_POLAR_PSBCH_L>8 to meet false alarm rate requirements.
|
||||
|
||||
//Sec. 7.1.4: Channel Coding
|
||||
#define NR_POLAR_PSBCH_N_MAX 9 //uint8_t
|
||||
#define NR_POLAR_PSBCH_I_IL 1 //uint8_t
|
||||
#define NR_POLAR_PSBCH_I_SEG 0 //uint8_t
|
||||
#define NR_POLAR_PSBCH_N_PC 0 //uint8_t
|
||||
#define NR_POLAR_PSBCH_N_PC_WM 0 //uint8_t
|
||||
//#define NR_POLAR_PSBCH_N 512 //uint16_t
|
||||
|
||||
//Sec. 7.1.5: Rate Matching
|
||||
#define NR_POLAR_PSBCH_I_BIL 0 //uint8_t
|
||||
#define NR_POLAR_PSBCH_E 1792 //uint16_t
|
||||
#define NR_POLAR_PSBCH_E_DWORD 56 // NR_POLAR_PSBCH_E/32
|
||||
|
||||
/*
|
||||
* TEST CODE
|
||||
*/
|
||||
//#define DEBUG_POLAR
|
||||
// Usage in code:
|
||||
//#ifdef DEBUG_POLAR
|
||||
//...
|
||||
//#endif
|
||||
|
||||
//unsigned int testPayload0=0x00000000, testPayload1=0xffffffff; //payload1=~payload0;
|
||||
//unsigned int testPayload2=0xa5a5a5a5; //testPayload3=0xb3f02c82;
|
||||
|
||||
//double testReceivedPayload3[NR_POLAR_PSBCH_E] = {-1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1};
|
||||
|
||||
#endif
|
||||
@@ -193,7 +193,18 @@ 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 == 3) { // PSBCH
|
||||
newPolarInitNode->n_max = NR_POLAR_PSBCH_N_MAX;
|
||||
newPolarInitNode->i_il = NR_POLAR_PSBCH_I_IL;
|
||||
newPolarInitNode->i_seg = NR_POLAR_PSBCH_I_SEG;
|
||||
newPolarInitNode->n_pc = NR_POLAR_PSBCH_N_PC;
|
||||
newPolarInitNode->n_pc_wm = NR_POLAR_PSBCH_N_PC_WM;
|
||||
newPolarInitNode->i_bil = NR_POLAR_PSBCH_I_BIL;
|
||||
newPolarInitNode->crcParityBits = NR_POLAR_PSBCH_CRC_PARITY_BITS;
|
||||
newPolarInitNode->payloadBits = NR_POLAR_PSBCH_PAYLOAD_BITS;
|
||||
newPolarInitNode->encoderLength = NR_POLAR_PSBCH_E;
|
||||
newPolarInitNode->crcCorrectionBits = NR_POLAR_PSBCH_CRC_ERROR_CORRECTION_BITS;
|
||||
newPolarInitNode->crc_generator_matrix = crc24c_generator_matrix(newPolarInitNode->payloadBits);//G_P
|
||||
} else {
|
||||
AssertFatal(1 == 0, "[nr_polar_init] Incorrect Message Type(%d)", messageType);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "PHY/NR_REFSIG/nr_refsig.h"
|
||||
#include "PHY/INIT/nr_phy_init.h"
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h"
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
#include "openair1/PHY/MODULATION/nr_modulation.h"
|
||||
@@ -38,7 +39,7 @@
|
||||
#include "PHY/NR_REFSIG/nr_refsig.h"
|
||||
#include "SCHED_NR/fapi_nr_l1.h"
|
||||
#include "nfapi_nr_interface.h"
|
||||
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
|
||||
|
||||
|
||||
|
||||
@@ -35,6 +35,9 @@
|
||||
#include "PHY/MODULATION/nr_modulation.h"
|
||||
#include "openair2/COMMON/prs_nr_paramdef.h"
|
||||
#include "SCHED_NR_UE/harq_nr.h"
|
||||
#include <nr-uesoftmodem.h>
|
||||
|
||||
|
||||
|
||||
void RCconfig_nrUE_prs(void *cfg)
|
||||
{
|
||||
@@ -199,6 +202,7 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
// create shortcuts
|
||||
NR_DL_FRAME_PARMS *const fp = &ue->frame_parms;
|
||||
NR_UE_COMMON *const common_vars = &ue->common_vars;
|
||||
NR_UE_PSBCH **const psbch_vars = ue->psbch_vars;
|
||||
NR_UE_PRACH **const prach_vars = ue->prach_vars;
|
||||
NR_UE_CSI_IM **const csiim_vars = ue->csiim_vars;
|
||||
NR_UE_CSI_RS **const csirs_vars = ue->csirs_vars;
|
||||
@@ -350,6 +354,7 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
// DLSCH
|
||||
for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) {
|
||||
prach_vars[gNB_id] = (NR_UE_PRACH *)malloc16_clear(sizeof(NR_UE_PRACH));
|
||||
psbch_vars[gNB_id] = (NR_UE_PSBCH *)malloc16_clear(sizeof(NR_UE_PSBCH));
|
||||
csiim_vars[gNB_id] = (NR_UE_CSI_IM *)malloc16_clear(sizeof(NR_UE_CSI_IM));
|
||||
csirs_vars[gNB_id] = (NR_UE_CSI_RS *)malloc16_clear(sizeof(NR_UE_CSI_RS));
|
||||
srs_vars[gNB_id] = (NR_UE_SRS *)malloc16_clear(sizeof(NR_UE_SRS));
|
||||
@@ -468,6 +473,7 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
free_and_zero(ue->csirs_vars[gNB_id]);
|
||||
free_and_zero(ue->srs_vars[gNB_id]);
|
||||
|
||||
free_and_zero(ue->psbch_vars[gNB_id]);
|
||||
free_and_zero(ue->prach_vars[gNB_id]);
|
||||
}
|
||||
|
||||
@@ -697,7 +703,12 @@ void phy_init_nr_top(PHY_VARS_NR_UE *ue) {
|
||||
crcTableInit();
|
||||
init_scrambling_luts();
|
||||
load_dftslib();
|
||||
frame_parms->Nid_SL = 0;
|
||||
init_context_synchro_nr(frame_parms);
|
||||
if (get_softmodem_params()->sl_mode>0) {
|
||||
frame_parms->Nid_SL = 336;
|
||||
init_context_synchro_nr(frame_parms);
|
||||
}
|
||||
generate_ul_reference_signal_sequences(SHRT_MAX);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "nr_phy_init.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "executables/softmodem-common.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};
|
||||
@@ -41,6 +42,11 @@ 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) {
|
||||
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))
|
||||
@@ -150,7 +156,10 @@ void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, int N_RB_DL)
|
||||
while(fp->ofdm_symbol_size < N_RB_DL * 12)
|
||||
fp->ofdm_symbol_size <<= 1;
|
||||
|
||||
fp->first_carrier_offset = fp->ofdm_symbol_size - (N_RB_DL * 12 / 2);
|
||||
if (get_softmodem_params()->sl_mode == 2)
|
||||
fp->first_carrier_offset = 0;
|
||||
else
|
||||
fp->first_carrier_offset = fp->ofdm_symbol_size - (N_RB_DL * 12 / 2);
|
||||
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",
|
||||
@@ -283,6 +292,10 @@ 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 != 0) {
|
||||
fp->sl_CarrierFreq = ((dl_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 ;
|
||||
|
||||
@@ -332,6 +345,9 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
|
||||
}
|
||||
|
||||
fp->ssb_start_subcarrier = (12 * config->ssb_table.ssb_offset_point_a + sco);
|
||||
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;
|
||||
@@ -381,6 +397,11 @@ 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)
|
||||
{
|
||||
|
||||
@@ -29,6 +29,7 @@ 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 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);
|
||||
@@ -55,5 +56,5 @@ 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 init_dfts(void);
|
||||
#endif
|
||||
|
||||
@@ -51,7 +51,7 @@ void PHY_ofdm_mod(int *input,
|
||||
void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRAME_PARMS *frame_parms);
|
||||
void nr_normal_prefix_mod(c16_t *txdataF, c16_t *txdata, uint8_t nsymb, NR_DL_FRAME_PARMS *frame_parms, uint32_t slot);
|
||||
|
||||
void do_OFDM_mod(int32_t **txdataF, int32_t **txdata, uint32_t frame,uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms);
|
||||
void do_OFDM_mod(c16_t **txdataF, c16_t **txdata, uint32_t frame,uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms);
|
||||
|
||||
|
||||
/** @}*/
|
||||
|
||||
@@ -599,7 +599,8 @@ void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) {
|
||||
|
||||
uint64_t dl_CarrierFreq = fp->dl_CarrierFreq;
|
||||
uint64_t ul_CarrierFreq = fp->ul_CarrierFreq;
|
||||
double f[2] = {(double)dl_CarrierFreq, (double)ul_CarrierFreq};
|
||||
uint64_t sl_CarrierFreq = fp->sl_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);
|
||||
@@ -607,10 +608,10 @@ 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 < sizeof(f)/sizeof(f[0]); ll++){
|
||||
|
||||
double f0 = f[ll];
|
||||
LOG_D(PHY, "Doing symbol rotation calculation for gNB TX/RX, f0 %f Hz, Nsymb %d\n", f0, nsymb);
|
||||
LOG_I(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];
|
||||
|
||||
double tl = 0.0;
|
||||
|
||||
@@ -112,7 +112,8 @@ void apply_nr_rotation(NR_DL_FRAME_PARMS *fp,
|
||||
c16_t* txdata,
|
||||
int slot,
|
||||
int first_symbol,
|
||||
int nsymb);
|
||||
int nsymb,
|
||||
int link_type);
|
||||
|
||||
void init_symbol_rotation(NR_DL_FRAME_PARMS *fp);
|
||||
|
||||
@@ -122,7 +123,8 @@ void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms,
|
||||
c16_t *rxdataF,
|
||||
int slot,
|
||||
int first_symbol,
|
||||
int nsymb);
|
||||
int nsymb,
|
||||
int link_type);
|
||||
|
||||
/*! \brief Perform NR precoding. TS 38.211 V15.4.0 subclause 6.3.1.5
|
||||
@param[in] datatx_F_precoding, Pointer to n_layers*re data array
|
||||
|
||||
@@ -37,6 +37,7 @@ This section deals with basic functions for OFDM Modulation.
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "modulation_common.h"
|
||||
#include "PHY/LTE_TRANSPORT/transport_common_proto.h"
|
||||
#include "../executables/softmodem-common.h"
|
||||
//#define DEBUG_OFDM_MOD
|
||||
|
||||
|
||||
@@ -45,15 +46,15 @@ void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRA
|
||||
|
||||
|
||||
|
||||
PHY_ofdm_mod(txdataF, // input
|
||||
txdata, // output
|
||||
PHY_ofdm_mod((int *)txdataF, // input
|
||||
(int *)txdata, // output
|
||||
frame_parms->ofdm_symbol_size,
|
||||
|
||||
1, // number of symbols
|
||||
frame_parms->nb_prefix_samples0, // number of prefix samples
|
||||
CYCLIC_PREFIX);
|
||||
PHY_ofdm_mod(txdataF+frame_parms->ofdm_symbol_size, // input
|
||||
txdata+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0, // output
|
||||
PHY_ofdm_mod((int *)txdataF+frame_parms->ofdm_symbol_size, // input
|
||||
(int *)txdata+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0, // output
|
||||
frame_parms->ofdm_symbol_size,
|
||||
nsymb-1,
|
||||
frame_parms->nb_prefix_samples, // number of prefix samples
|
||||
@@ -280,7 +281,7 @@ void PHY_ofdm_mod(int *input, /// pointer to complex input
|
||||
}
|
||||
|
||||
|
||||
void do_OFDM_mod(int32_t **txdataF, int32_t **txdata, uint32_t frame,uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms)
|
||||
void do_OFDM_mod(c16_t **txdataF, c16_t **txdata, uint32_t frame,uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms)
|
||||
{
|
||||
|
||||
int aa, slot_offset, slot_offset_F;
|
||||
@@ -292,39 +293,39 @@ void do_OFDM_mod(int32_t **txdataF, int32_t **txdata, uint32_t frame,uint16_t ne
|
||||
if (is_pmch_subframe(frame,next_slot>>1,frame_parms)) {
|
||||
if ((next_slot%2)==0) {
|
||||
LOG_D(PHY,"Frame %d, subframe %d: Doing MBSFN modulation (slot_offset %d)\n",frame,next_slot>>1,slot_offset);
|
||||
PHY_ofdm_mod(&txdataF[aa][slot_offset_F], // input
|
||||
&txdata[aa][slot_offset], // output
|
||||
PHY_ofdm_mod((int *)&txdataF[aa][slot_offset_F], // input
|
||||
(int *)&txdata[aa][slot_offset], // output
|
||||
frame_parms->ofdm_symbol_size,
|
||||
12, // number of symbols
|
||||
frame_parms->ofdm_symbol_size>>2, // number of prefix samples
|
||||
CYCLIC_PREFIX);
|
||||
|
||||
if (frame_parms->Ncp == EXTENDED)
|
||||
PHY_ofdm_mod(&txdataF[aa][slot_offset_F], // input
|
||||
&txdata[aa][slot_offset], // output
|
||||
PHY_ofdm_mod((int *)&txdataF[aa][slot_offset_F], // input
|
||||
(int *)&txdata[aa][slot_offset], // output
|
||||
frame_parms->ofdm_symbol_size,
|
||||
2, // number of symbols
|
||||
frame_parms->nb_prefix_samples, // number of prefix samples
|
||||
CYCLIC_PREFIX);
|
||||
else {
|
||||
LOG_D(PHY,"Frame %d, subframe %d: Doing PDCCH modulation\n",frame,next_slot>>1);
|
||||
normal_prefix_mod(&txdataF[aa][slot_offset_F],
|
||||
&txdata[aa][slot_offset],
|
||||
normal_prefix_mod((int32_t *)&txdataF[aa][slot_offset_F],
|
||||
(int32_t *)&txdata[aa][slot_offset],
|
||||
2,
|
||||
frame_parms);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (frame_parms->Ncp == EXTENDED)
|
||||
PHY_ofdm_mod(&txdataF[aa][slot_offset_F], // input
|
||||
&txdata[aa][slot_offset], // output
|
||||
PHY_ofdm_mod((int *)&txdataF[aa][slot_offset_F], // input
|
||||
(int *)&txdata[aa][slot_offset], // output
|
||||
frame_parms->ofdm_symbol_size,
|
||||
6, // number of symbols
|
||||
frame_parms->nb_prefix_samples, // number of prefix samples
|
||||
CYCLIC_PREFIX);
|
||||
else {
|
||||
normal_prefix_mod(&txdataF[aa][slot_offset_F],
|
||||
&txdata[aa][slot_offset],
|
||||
normal_prefix_mod((int32_t *)&txdataF[aa][slot_offset_F],
|
||||
(int32_t *)&txdata[aa][slot_offset],
|
||||
7,
|
||||
frame_parms);
|
||||
}
|
||||
@@ -337,17 +338,18 @@ void apply_nr_rotation(NR_DL_FRAME_PARMS *fp,
|
||||
c16_t *txdataF,
|
||||
int slot,
|
||||
int first_symbol,
|
||||
int nsymb)
|
||||
int nsymb,
|
||||
int link_type)
|
||||
{
|
||||
int symb_offset = (slot%fp->slots_per_subframe)*fp->symbols_per_slot;
|
||||
|
||||
c16_t *symbol_rotation = fp->symbol_rotation[0] + symb_offset;
|
||||
c16_t *symbol_rotation = fp->symbol_rotation[link_type] + symb_offset;
|
||||
|
||||
for (int sidx = first_symbol; sidx < first_symbol + nsymb; sidx++) {
|
||||
c16_t *this_rotation = symbol_rotation + sidx;
|
||||
c16_t *this_symbol = (txdataF) + sidx * fp->ofdm_symbol_size;
|
||||
|
||||
LOG_D(PHY,"Rotating symbol %d, slot %d, symbol_subframe_index %d (%d,%d)\n",
|
||||
LOG_I(PHY,"Rotating symbol %d, slot %d, symbol_subframe_index %d (%d,%d)\n",
|
||||
sidx,
|
||||
slot,
|
||||
sidx + symb_offset,
|
||||
@@ -371,4 +373,4 @@ void apply_nr_rotation(NR_DL_FRAME_PARMS *fp,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
|
||||
#include "PHY/NR_UE_ESTIMATION/nr_estimation.h"
|
||||
#include <common/utils/LOG/log.h>
|
||||
#include "executables/softmodem-common.h"
|
||||
|
||||
//#define DEBUG_FEP
|
||||
|
||||
@@ -48,7 +49,11 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
|
||||
unsigned int nb_prefix_samples;
|
||||
unsigned int nb_prefix_samples0;
|
||||
if (ue->is_synchronized) {
|
||||
bool is_synced = ue->is_synchronized;
|
||||
if(get_softmodem_params()->sl_mode == 2) {
|
||||
is_synced = ue->is_synchronized_sl;
|
||||
}
|
||||
if (is_synced) {
|
||||
nb_prefix_samples = frame_parms->nb_prefix_samples;
|
||||
nb_prefix_samples0 = frame_parms->nb_prefix_samples0;
|
||||
} else {
|
||||
@@ -161,13 +166,19 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
|
||||
|
||||
unsigned int nb_prefix_samples;
|
||||
unsigned int nb_prefix_samples0;
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
if (ue->is_synchronized_sl) {
|
||||
nb_prefix_samples = frame_parms->nb_prefix_samples;
|
||||
nb_prefix_samples0 = frame_parms->nb_prefix_samples0;
|
||||
}
|
||||
}
|
||||
if (pbch_decoded) {
|
||||
nb_prefix_samples = frame_parms->nb_prefix_samples;
|
||||
nb_prefix_samples0 = frame_parms->nb_prefix_samples0;
|
||||
}
|
||||
else {
|
||||
nb_prefix_samples = frame_parms->nb_prefix_samples;
|
||||
nb_prefix_samples0 = frame_parms->nb_prefix_samples;
|
||||
nb_prefix_samples0 = frame_parms->nb_prefix_samples0;
|
||||
}
|
||||
unsigned int frame_length_samples = frame_parms->samples_per_frame;
|
||||
|
||||
@@ -178,8 +189,8 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
|
||||
unsigned int slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0);
|
||||
unsigned int rx_offset = sample_offset + slot_offset;
|
||||
unsigned int abs_symbol = Ns * frame_parms->symbols_per_slot + symbol;
|
||||
for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++)
|
||||
rx_offset += (abs_symbol%(0x7<<frame_parms->numerology_index)) ? nb_prefix_samples : nb_prefix_samples0;
|
||||
for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++)
|
||||
rx_offset += (idx_symb%(0x7<<frame_parms->numerology_index)) ? nb_prefix_samples : nb_prefix_samples0;
|
||||
rx_offset += frame_parms->ofdm_symbol_size * symbol;
|
||||
|
||||
#ifdef DEBUG_FEP
|
||||
@@ -230,7 +241,7 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
|
||||
stop_meas(&ue->rx_dft_stats);
|
||||
|
||||
int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot;
|
||||
c16_t rot2 = frame_parms->symbol_rotation[0][symbol + symb_offset];
|
||||
c16_t rot2 = frame_parms->symbol_rotation[get_softmodem_params()->sl_mode == 2 ? NR_LINK_TYPE_SL : 0][symbol + symb_offset];
|
||||
rot2.i=-rot2.i;
|
||||
|
||||
#ifdef DEBUG_FEP
|
||||
@@ -240,7 +251,7 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
|
||||
#endif
|
||||
|
||||
c16_t *this_symbol = &rxdataF[aa][frame_parms->ofdm_symbol_size*symbol];
|
||||
rotate_cpx_vector(this_symbol, &rot2, this_symbol, frame_parms->ofdm_symbol_size, 15);
|
||||
//rotate_cpx_vector(this_symbol, &rot2, this_symbol, frame_parms->ofdm_symbol_size, 15);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FEP
|
||||
@@ -314,14 +325,15 @@ void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms,
|
||||
c16_t *rxdataF,
|
||||
int slot,
|
||||
int first_symbol,
|
||||
int nsymb)
|
||||
int nsymb,
|
||||
int link_type)
|
||||
{
|
||||
int symb_offset = (slot%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot;
|
||||
int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size;
|
||||
|
||||
for (int symbol=first_symbol;symbol<nsymb;symbol++) {
|
||||
|
||||
c16_t rot2 = frame_parms->symbol_rotation[1][symbol + symb_offset];
|
||||
|
||||
c16_t rot2 = frame_parms->symbol_rotation[link_type][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);
|
||||
|
||||
|
||||
@@ -72,6 +72,10 @@ void nr_chest_time_domain_avg(NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint16_t dmrs_bitmap,
|
||||
uint16_t num_rbs);
|
||||
|
||||
int nr_psbch_dmrs_rx(int symbol,
|
||||
unsigned int *nr_gold_psbch,
|
||||
int32_t *output);
|
||||
|
||||
static inline uint8_t is_dmrs_symbol(uint8_t l, uint16_t dmrsSymbMask)
|
||||
{
|
||||
DevAssert(l < 32);
|
||||
|
||||
@@ -232,6 +232,38 @@ int nr_pbch_dmrs_rx(int symbol,
|
||||
return(0);
|
||||
}
|
||||
|
||||
int nr_psbch_dmrs_rx(int symbol,
|
||||
unsigned int *nr_gold_psbch,
|
||||
int32_t *output)
|
||||
{
|
||||
AssertFatal(symbol >= 0 && symbol < 14, "Illegal symbol %d\n", symbol);
|
||||
int offset = (symbol == 0) ? 0 : 4;
|
||||
int m0 = (symbol - offset) * 33;
|
||||
int m1 = ((symbol - offset) + 1) * 33;
|
||||
/// QPSK modulation
|
||||
for (int m = m0; m < m1; m++) {
|
||||
AssertFatal(((m << 1) >> 5) < NR_PSBCH_DMRS_LENGTH_DWORD, "Index in output is invalid %d >= %d\n",
|
||||
((m << 1) >> 5), NR_PSBCH_DMRS_LENGTH_DWORD);
|
||||
AssertFatal((((m << 1) + 1) >> 5) < NR_PSBCH_DMRS_LENGTH_DWORD, "Index in output is invalid %d >= %d\n",
|
||||
(((m << 1) + 1) >> 5), NR_PSBCH_DMRS_LENGTH_DWORD);
|
||||
uint8_t idx = ((((nr_gold_psbch[(m << 1) >> 5]) >> ((m << 1) & 0x1f)) & 1) << 1) ^ (((nr_gold_psbch[((m << 1) + 1) >> 5]) >> (((m << 1) + 1) & 0x1f)) & 1);
|
||||
AssertFatal(((m - m0) << 1) + 1 < 200, "Index in output is invalid %d >= %d\n",
|
||||
((m - m0) << 1) + 1, 200);
|
||||
AssertFatal(((NR_MOD_TABLE_QPSK_OFFSET + idx) << 1) + 1 < 14, "Index in output is invalid %d >= 14\n",
|
||||
((NR_MOD_TABLE_QPSK_OFFSET + idx) << 1) + 1);
|
||||
((int16_t*)output)[(m - m0) << 1] = nr_rx_mod_table[(NR_MOD_TABLE_QPSK_OFFSET + idx) << 1];
|
||||
((int16_t*)output)[((m - m0) << 1) + 1] = nr_rx_mod_table[((NR_MOD_TABLE_QPSK_OFFSET + idx) << 1) + 1];
|
||||
#ifdef DEBUG_PSBCH
|
||||
printf("%d %d\n", (m - m0) << 1, nr_rx_mod_table[(NR_MOD_TABLE_QPSK_OFFSET + idx) << 1]);
|
||||
if (m < 16) {
|
||||
printf("nr_gold_psbch[(m << 1) >> 5] %x\n", nr_gold_psbch[(m << 1) >> 5]);
|
||||
printf("m %d output %d %d addr %p\n", m, ((int16_t*)output)[m << 1], ((int16_t*)output)[(m << 1) + 1], &output[0]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief This function generate gold ptrs sequence for each OFDM symbol
|
||||
\param *in gold sequence for ptrs per OFDM symbol
|
||||
|
||||
@@ -51,6 +51,20 @@ void nr_gold_pbch(PHY_VARS_NR_UE* ue)
|
||||
|
||||
}
|
||||
|
||||
void nr_gold_psbch(PHY_VARS_NR_UE* ue)
|
||||
{
|
||||
uint8_t reset = 1;
|
||||
unsigned int x1;
|
||||
unsigned int x2 = ue->frame_parms.Nid_SL;
|
||||
|
||||
for (int n = 0; n < NR_PSBCH_DMRS_LENGTH_DWORD; n++) {
|
||||
AssertFatal(n < sizeof(ue->nr_gold_psbch) / sizeof(ue->nr_gold_psbch[0]),
|
||||
"Invalid nr_gold_psbch index %d > %d\n", n, NR_PSBCH_DMRS_LENGTH_DWORD);
|
||||
ue->nr_gold_psbch[n] = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void nr_gold_pdcch(PHY_VARS_NR_UE* ue,
|
||||
unsigned short nid)
|
||||
{
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
#define SYNCHRO_FFT_SIZE_MAX (8192) /* maximum size of fft for synchronisation */
|
||||
|
||||
#define NO_RATE_CHANGE (1)
|
||||
|
||||
#define INITIAL_PSS_NR (7)
|
||||
#ifdef PSS_DECIMATOR
|
||||
#define RATE_CHANGE (SYNCHRO_FFT_SIZE_MAX/SYNCHRO_FFT_SIZE_PSS)
|
||||
#define SYNCHRO_FFT_SIZE_PSS (256)
|
||||
@@ -86,33 +86,26 @@
|
||||
|
||||
/************** VARIABLES *****************************************/
|
||||
|
||||
//#define STATIC_SYNC_BUFFER
|
||||
|
||||
#ifdef STATIC_SYNC_BUFFER
|
||||
/* buffer defined in file lte_sync_time */
|
||||
EXTERN int16_t synchro_tmp[SYNC_TMP_SIZE] __attribute__((aligned(32)));
|
||||
EXTERN int16_t synchroF_tmp[SYNCF_TMP_SIZE] __attribute__((aligned(32)));
|
||||
#else
|
||||
EXTERN int16_t *synchro_tmp;
|
||||
EXTERN int16_t *synchroF_tmp;
|
||||
#endif
|
||||
|
||||
EXTERN int16_t *primary_synchro_nr[NUMBER_PSS_SEQUENCE]
|
||||
EXTERN c16_t *primary_synchro_nr[NUMBER_PSS_SEQUENCE] __attribute__((aligned(32)));
|
||||
#ifdef INIT_VARIABLES_PSS_NR_H
|
||||
= { NULL, NULL, NULL}
|
||||
#endif
|
||||
;
|
||||
EXTERN int16_t *primary_synchro_nr2[NUMBER_PSS_SEQUENCE]
|
||||
EXTERN c16_t *primary_synchro_nr2[NUMBER_PSS_SEQUENCE] __attribute__((aligned(32)));
|
||||
#ifdef INIT_VARIABLES_PSS_NR_H
|
||||
= { NULL, NULL, NULL}
|
||||
#endif
|
||||
;
|
||||
EXTERN int16_t *primary_synchro_time_nr[NUMBER_PSS_SEQUENCE]
|
||||
EXTERN c16_t *primary_synchro_time_nr[NUMBER_PSS_SEQUENCE] __attribute__((aligned(32)));
|
||||
#ifdef INIT_VARIABLES_PSS_NR_H
|
||||
= { NULL, NULL, NULL}
|
||||
#endif
|
||||
;
|
||||
|
||||
EXTERN int16_t *primary_synchro_time_nr_sl[NUMBER_PSS_SEQUENCE_SL]
|
||||
#ifdef INIT_VARIABLES_PSS_NR_H
|
||||
= { NULL, NULL}
|
||||
#endif
|
||||
;
|
||||
/* profiling structure */
|
||||
EXTERN time_stats_t generic_time[TIME_LAST];
|
||||
|
||||
@@ -123,7 +116,6 @@ EXTERN time_stats_t generic_time[TIME_LAST];
|
||||
void init_context_synchro_nr(NR_DL_FRAME_PARMS *frame_parms_ue);
|
||||
void free_context_synchro_nr(void);
|
||||
void init_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue);
|
||||
void free_context_pss_nr(void);
|
||||
int set_pss_nr(int ofdm_symbol_size);
|
||||
int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change);
|
||||
int pss_search_time_nr(c16_t **rxdata, PHY_VARS_NR_UE *ue, int fo_flag, int is);
|
||||
|
||||
@@ -56,6 +56,8 @@ int nr_pdsch_dmrs_rx(PHY_VARS_NR_UE *ue,
|
||||
|
||||
void nr_gold_pbch(PHY_VARS_NR_UE* ue);
|
||||
|
||||
void nr_gold_psbch(PHY_VARS_NR_UE* ue);
|
||||
|
||||
void nr_gold_pdcch(PHY_VARS_NR_UE* ue,
|
||||
unsigned short n_idDMRS);
|
||||
|
||||
|
||||
@@ -41,7 +41,13 @@
|
||||
|
||||
/* PSS parameters */
|
||||
#define NUMBER_PSS_SEQUENCE (3)
|
||||
#define NUMBER_PSS_SEQUENCE_SL (2)
|
||||
#define PSS_SEQ_OFFSET (0)
|
||||
#define PSS_SEQ_OFFSET_SL (22)
|
||||
#define PSS_SSS_SUB_CARRIER_START (56)
|
||||
#define PSS_SSS_SUB_CARRIER_START_SL (2)
|
||||
#define INVALID_PSS_SEQUENCE (NUMBER_PSS_SEQUENCE)
|
||||
#define INVALID_PSS_SEQUENCE_SL (NUMBER_PSS_SEQUENCE_SL)
|
||||
#define LENGTH_PSS_NR (127)
|
||||
#define N_SC_RB (12) /* Resource block size in frequency domain expressed as a number if subcarriers */
|
||||
#define SCALING_PSS_NR (3)
|
||||
@@ -62,6 +68,12 @@
|
||||
#define SSS_SYMBOL_NB ((2) + OFFSET_SS_PBCH)
|
||||
#define PBCH_LAST_SYMBOL_NB ((3) + OFFSET_SS_PBCH)
|
||||
|
||||
#define OFFSET_SS_PSBCH 0//-1
|
||||
#define PSS0_SL_SYMBOL_NB ((1) + OFFSET_SS_PSBCH)
|
||||
#define PSS1_SL_SYMBOL_NB ((2) + OFFSET_SS_PSBCH)
|
||||
#define SSS0_SL_SYMBOL_NB ((3) + OFFSET_SS_PSBCH)
|
||||
#define SSS1_SL_SYMBOL_NB ((4) + OFFSET_SS_PSBCH)
|
||||
|
||||
/* SS/PBCH parameters */
|
||||
#define N_RB_SS_PBCH_BLOCK (20)
|
||||
#define NB_SYMBOLS_PBCH (3)
|
||||
|
||||
@@ -51,15 +51,26 @@
|
||||
#define NUMBER_SSS_SEQUENCE (336)
|
||||
#define INVALID_SSS_SEQUENCE (NUMBER_SSS_SEQUENCE)
|
||||
#define LENGTH_SSS_NR (127)
|
||||
#define SCALING_METRIC_SSS_NR (15)//(19)
|
||||
#define SCALING_METRIC_SSS_NR (19)//(15)
|
||||
|
||||
#define N_ID_2_NUMBER (NUMBER_PSS_SEQUENCE)
|
||||
#define N_ID_2_NUMBER_SL (NUMBER_PSS_SEQUENCE_SL)
|
||||
#define N_ID_1_NUMBER (NUMBER_SSS_SEQUENCE)
|
||||
|
||||
#define GET_NID2(Nid_cell) (Nid_cell%3)
|
||||
#define GET_NID1(Nid_cell) (Nid_cell/3)
|
||||
|
||||
#define GET_NID2_SL(Nid_SL) (Nid_SL/NUMBER_SSS_SEQUENCE)
|
||||
#define GET_NID1_SL(Nid_SL) (Nid_SL%NUMBER_SSS_SEQUENCE)
|
||||
|
||||
#define PSS_SC_START_NR (52) /* see from TS 38.211 table 7.4.3.1-1: Resources within an SS/PBCH block for PSS... */
|
||||
#define SSS_START_IDX (3) /* [0:PSBCH 1:PSS0 2:PSS1 3:SSS0 4:SSS1] */
|
||||
#define NUM_SSS_SYMBOLS (2)
|
||||
|
||||
#define SSS_START_IDX (3) /* [0:PSBCH 1:PSS0 2:PSS1 3:SSS0 4:SSS1] */
|
||||
#define NUM_SSS_SYMBOLS (2)
|
||||
|
||||
#define SSS_METRIC_FLOOR_NR (30000)
|
||||
|
||||
/************** VARIABLES *****************************************/
|
||||
|
||||
@@ -89,15 +100,17 @@ EXTERN int16_t d_sss[N_ID_2_NUMBER][N_ID_1_NUMBER][LENGTH_SSS_NR];
|
||||
void init_context_sss_nr(int amp);
|
||||
void free_context_sss_nr(void);
|
||||
|
||||
void insert_sss_nr(int16_t *sss_time,
|
||||
void insert_sss_nr(c16_t *sss_time,
|
||||
NR_DL_FRAME_PARMS *frame_parms);
|
||||
|
||||
int pss_ch_est_nr(PHY_VARS_NR_UE *ue,
|
||||
int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR]);
|
||||
c16_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
c16_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR]);
|
||||
|
||||
int rx_sss_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric, uint8_t *phase_max, int *freq_offset_sss, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
int rx_sss_sl_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric, uint8_t *phase_max, int *freq_offset_sss);
|
||||
|
||||
#undef INIT_VARIABLES_SSS_NR_H
|
||||
#undef EXTERN
|
||||
|
||||
|
||||
@@ -54,7 +54,8 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
|
||||
|
||||
short ncoef = 32767 - coef;
|
||||
|
||||
LOG_D(PHY,"AbsSubframe %d: rx_offset (before) = %d\n",subframe,ue->rx_offset);
|
||||
LOG_D(NR_PHY, "AbsSubframe %d: rx_offset (before) = %d\n", subframe,
|
||||
get_softmodem_params()->sl_mode != 2 ? ue->rx_offset : ue->rx_offset_sl);
|
||||
|
||||
// search for maximum position within the cyclic prefix
|
||||
for (int i = -frame_parms->nb_prefix_samples/2; i < frame_parms->nb_prefix_samples/2; i++) {
|
||||
@@ -89,10 +90,17 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
|
||||
else
|
||||
sync_offset = 0;
|
||||
|
||||
if ( abs(diff) < (SYNCH_HYST+sync_offset) )
|
||||
ue->rx_offset = 0;
|
||||
else
|
||||
ue->rx_offset = diff;
|
||||
if ( abs(diff) < (SYNCH_HYST+sync_offset) ) {
|
||||
if (get_softmodem_params()->sl_mode == 0)
|
||||
ue->rx_offset = 0;
|
||||
else
|
||||
ue->rx_offset_sl = 0;
|
||||
} else {
|
||||
if (get_softmodem_params()->sl_mode == 0)
|
||||
ue->rx_offset = diff;
|
||||
else
|
||||
ue->rx_offset_sl = diff;
|
||||
}
|
||||
|
||||
if(abs(diff)<5)
|
||||
count_max_pos_ok ++;
|
||||
|
||||
@@ -723,6 +723,94 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
return(0);
|
||||
}
|
||||
|
||||
int nr_psbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
uint8_t gNB_id,
|
||||
unsigned char Ns,
|
||||
unsigned char symbol,
|
||||
int dmrss,
|
||||
NR_UE_SSB *current_ssb)
|
||||
{
|
||||
ue->frame_parms.nushift = 0;
|
||||
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;
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
printf("PSBCH DMRS Correlation : ThreadId %d, gNB_id %d , OFDM size %d, Ncp=%d, Ns=%d, symbol %d, ssb_offset %d\n",
|
||||
proc->thread_id, gNB_id, ue->frame_parms.ofdm_symbol_size, ue->frame_parms.Ncp, Ns, symbol, ssb_offset);
|
||||
#endif
|
||||
|
||||
AssertFatal(dmrss >= 0 && dmrss <= 12, "symbol %d is illegal for PSBCH DM-RS \n", dmrss);
|
||||
int pilot[300] __attribute__((aligned(16)));
|
||||
nr_psbch_dmrs_rx(dmrss, &ue->nr_gold_psbch[current_ssb->i_ssb], &pilot[0]);
|
||||
if (0 < dmrss && dmrss < 5)
|
||||
return 0;
|
||||
|
||||
int16_t ch[2], *pil, *rxF;
|
||||
c16_t **rxdataF = ue->common_vars.rxdataF;
|
||||
int symbol_offset = ue->frame_parms.ofdm_symbol_size * symbol;
|
||||
unsigned short k = 0;
|
||||
for (int aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
int re_offset = ssb_offset;
|
||||
pil = (int16_t *)&pilot[0];
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
current_ssb->c_re += ch[0];
|
||||
current_ssb->c_im += ch[1];
|
||||
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
current_ssb->c_re += ch[0];
|
||||
current_ssb->c_im += ch[1];
|
||||
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
current_ssb->c_re += ch[0];
|
||||
current_ssb->c_im += ch[1];
|
||||
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
|
||||
for (int pilot_cnt = 3; pilot_cnt < (3 * 11); pilot_cnt += 3) {
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
current_ssb->c_re += ch[0];
|
||||
current_ssb->c_im += ch[1];
|
||||
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
current_ssb->c_re += ch[0];
|
||||
current_ssb->c_im += ch[1];
|
||||
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
current_ssb->c_re += ch[0];
|
||||
current_ssb->c_im += ch[1];
|
||||
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
@@ -989,6 +1077,223 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
return(0);
|
||||
}
|
||||
|
||||
int nr_psbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates [][estimateSz],
|
||||
struct complex16 dl_ch_estimates_time [][ue->frame_parms.ofdm_symbol_size],
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
uint8_t gNB_id,
|
||||
unsigned char Ns,
|
||||
unsigned char symbol,
|
||||
int dmrss,
|
||||
uint8_t ssb_index,
|
||||
uint8_t n_hf)
|
||||
{
|
||||
int pilot[200] __attribute__((aligned(16)));
|
||||
unsigned short k;
|
||||
unsigned int pilot_cnt;
|
||||
int16_t *pil,*rxF,*dl_ch,*fl,*fm,*fr;
|
||||
int ch_offset,symbol_offset;
|
||||
|
||||
uint8_t nushift;
|
||||
c16_t **rxdataF=ue->common_vars.rxdataF;
|
||||
|
||||
nushift = 0;// 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;
|
||||
|
||||
ch_offset = ue->frame_parms.ofdm_symbol_size*symbol;
|
||||
|
||||
AssertFatal(dmrss >= 0 && dmrss <= 13,
|
||||
"symbol %d is illegal for PSBCH DM-RS \n",
|
||||
dmrss);
|
||||
|
||||
symbol_offset = ue->frame_parms.ofdm_symbol_size*symbol;
|
||||
|
||||
k = nushift;
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
printf("PSBCH Channel Estimation : ThreadId %d, gNB_id %d ch_offset %d, OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n",proc->thread_id, gNB_id,ch_offset,ue->frame_parms.ofdm_symbol_size,
|
||||
ue->frame_parms.Ncp,Ns,k, symbol);
|
||||
#endif
|
||||
|
||||
fl = filt16a_l0;
|
||||
fm = filt16a_m0;
|
||||
fr = filt16a_r0;
|
||||
|
||||
idft_size_idx_t idftsizeidx;
|
||||
|
||||
switch (ue->frame_parms.ofdm_symbol_size) {
|
||||
case 128:
|
||||
idftsizeidx = IDFT_128;
|
||||
break;
|
||||
|
||||
case 256:
|
||||
idftsizeidx = IDFT_256;
|
||||
break;
|
||||
|
||||
case 512:
|
||||
idftsizeidx = IDFT_512;
|
||||
break;
|
||||
|
||||
case 1024:
|
||||
idftsizeidx = IDFT_1024;
|
||||
break;
|
||||
|
||||
case 1536:
|
||||
idftsizeidx = IDFT_1536;
|
||||
break;
|
||||
|
||||
case 2048:
|
||||
idftsizeidx = IDFT_2048;
|
||||
break;
|
||||
|
||||
case 3072:
|
||||
idftsizeidx = IDFT_3072;
|
||||
break;
|
||||
|
||||
case 4096:
|
||||
idftsizeidx = IDFT_4096;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("unsupported ofdm symbol size \n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
// generate pilot
|
||||
nr_psbch_dmrs_rx(dmrss, &ue->nr_gold_psbch[ssb_index], &pilot[0]);
|
||||
|
||||
for (int aarx = 0; aarx < ue->frame_parms.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));
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
printf("psbch ch est pilot addr %p RB_DL %d\n",&pilot[0], ue->frame_parms.N_RB_DL);
|
||||
printf("k %d, first_carrier %d\n",k,ue->frame_parms.first_carrier_offset);
|
||||
printf("rxF addr %p\n", rxF);
|
||||
printf("dl_ch addr %p\n",dl_ch);
|
||||
#endif
|
||||
|
||||
// Treat first 2 pilots specially (left edge)
|
||||
int16_t ch[2];
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1]));
|
||||
printf("pilot 0 : rxF - > (%d,%d) addr %p ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]);
|
||||
#endif
|
||||
multadd_real_vector_complex_scalar(fl, ch, dl_ch, 16);
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
|
||||
//for (int i= 0; i<8; i++)
|
||||
//printf("dl_ch addr %p %d\n", dl_ch+i, *(dl_ch+i));
|
||||
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
||||
#endif
|
||||
multadd_real_vector_complex_scalar(fm, ch, dl_ch, 16);
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
printf("pilot 2 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
||||
#endif
|
||||
|
||||
multadd_real_vector_complex_scalar(fr,
|
||||
ch,
|
||||
dl_ch,
|
||||
16);
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
dl_ch += 24;
|
||||
|
||||
for (pilot_cnt = 3; pilot_cnt < (3 * 11); pilot_cnt += 3) {
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
||||
#endif
|
||||
multadd_real_vector_complex_scalar(fl,
|
||||
ch,
|
||||
dl_ch,
|
||||
16);
|
||||
|
||||
//for (int i= 0; i<8; i++)
|
||||
// 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;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
|
||||
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
||||
#endif
|
||||
multadd_real_vector_complex_scalar(fm,
|
||||
ch,
|
||||
dl_ch,
|
||||
16);
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
|
||||
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+2,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
||||
#endif
|
||||
|
||||
multadd_real_vector_complex_scalar(fr,
|
||||
ch,
|
||||
dl_ch,
|
||||
16);
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
dl_ch += 24;
|
||||
|
||||
}
|
||||
|
||||
if( dmrss == 12) // update time statistics for last PSBCH symbol
|
||||
{
|
||||
// do ifft of channel estimate
|
||||
LOG_D(PHY,"Channel Impulse Computation Slot %d Symbol %d ch_offset %d\n", Ns, symbol, ch_offset);
|
||||
idft(idftsizeidx,
|
||||
(int16_t*) &dl_ch_estimates[aarx][ch_offset],
|
||||
(int16_t*) dl_ch_estimates_time[aarx],
|
||||
1);
|
||||
}
|
||||
}
|
||||
|
||||
if (dmrss == 12)
|
||||
UEscopeCopy(ue, psbchDlChEstimateTime, (void*)dl_ch_estimates_time, sizeof(struct complex16), ue->frame_parms.nb_antennas_rx, idftsizeidx);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
unsigned char symbol,
|
||||
|
||||
@@ -67,6 +67,14 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
NR_UE_SSB *current_ssb,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
int nr_psbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
uint8_t gNB_id,
|
||||
unsigned char Ns,
|
||||
unsigned char symbol,
|
||||
int dmrss,
|
||||
NR_UE_SSB *current_ssb);
|
||||
|
||||
int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
@@ -78,6 +86,18 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
uint8_t n_hf,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
int nr_psbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates [][estimateSz],
|
||||
struct complex16 dl_ch_estimates_time [][estimateSz],
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
uint8_t gNB_id,
|
||||
unsigned char Ns,
|
||||
unsigned char symbol,
|
||||
int dmrss,
|
||||
uint8_t ssb_index,
|
||||
uint8_t n_hf);
|
||||
|
||||
int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
bool is_SI,
|
||||
@@ -115,6 +135,10 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
void nr_ue_sl_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
|
||||
int ssb_index,
|
||||
UE_nr_rxtx_proc_t *proc);
|
||||
|
||||
void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
#include "PHY/phy_extern_nr_ue.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "PHY/sse_intrin.h"
|
||||
#include "openair1/PHY/NR_REFSIG/sss_nr.h"
|
||||
#include "openair1/PHY/NR_REFSIG/ss_pbch_nr.h"
|
||||
|
||||
//#define k1 1000
|
||||
#define k1 ((long long int) 1000)
|
||||
@@ -236,6 +238,40 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
|
||||
rsrp);
|
||||
}
|
||||
|
||||
// This function implements:
|
||||
// - Sidelink SS reference signal received power (SSS-RSRP)
|
||||
// Measurement units:
|
||||
// - RSRP: W (dBW)
|
||||
// - RX Gain dB
|
||||
void nr_ue_sl_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
|
||||
int ssb_index,
|
||||
UE_nr_rxtx_proc_t *proc) {
|
||||
uint32_t rsrp = 0;
|
||||
int nb_re = 0;
|
||||
for (int aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
for (int i = 0; i < NUM_SSS_SYMBOLS; i++) {
|
||||
uint8_t l_sss = (SSS_START_IDX + i) % ue->frame_parms.symbols_per_slot;
|
||||
int16_t *rxF_sss = (int16_t *)&ue->common_vars.rxdataF[aarx][(l_sss * ue->frame_parms.ofdm_symbol_size)];
|
||||
for (int k = PSS_SSS_SUB_CARRIER_START_SL; k < (PSS_SSS_SUB_CARRIER_START_SL + LENGTH_SSS_NR); k++) {
|
||||
#ifdef DEBUG_MEAS_UE
|
||||
LOG_I(NR_PHY, "In %s rxF_sss %d %d\n", __FUNCTION__, rxF_sss[k * 2], rxF_sss[k * 2 + 1]);
|
||||
#endif
|
||||
rsrp += (((int32_t)rxF_sss[k * 2] * rxF_sss[k * 2]) + ((int32_t)rxF_sss[k * 2 + 1] * rxF_sss[k * 2 + 1]));
|
||||
nb_re++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rsrp /= nb_re;
|
||||
ue->measurements.ssb_rsrp_dBm[ssb_index] = 10 * log10(rsrp) +
|
||||
30 - 10 * log10(pow(2, 30)) -
|
||||
((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) -
|
||||
dB_fixed(ue->frame_parms.ofdm_symbol_size);
|
||||
|
||||
LOG_I(NR_PHY, "In %s: [UE %d] ssb %d SS-RSRP: %d dBm/RE (%d)\n",
|
||||
__FUNCTION__, ue->Mod_id, ssb_index, ue->measurements.ssb_rsrp_dBm[ssb_index], rsrp);
|
||||
}
|
||||
|
||||
// This function computes the received noise power
|
||||
// Measurement units:
|
||||
// - psd_awgn (AWGN power spectral density): dBm/Hz
|
||||
|
||||
119
openair1/PHY/NR_UE_TRANSPORT/nr_generate_psbch_dmrs_sl.c
Normal file
119
openair1/PHY/NR_UE_TRANSPORT/nr_generate_psbch_dmrs_sl.c
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <nr-uesoftmodem.h>
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/phy_extern.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
|
||||
//#define DEBUG_PSBCH
|
||||
//#define DEBUG_PSBCH_ENCODING
|
||||
//#define DEBUG_PSBCH_DMRS
|
||||
|
||||
|
||||
int nr_sl_generate_psbch_dmrs(uint32_t *gold_psbch_dmrs,
|
||||
c16_t *txdataF,
|
||||
int16_t amp,
|
||||
uint8_t ssb_start_symbol,
|
||||
NR_DL_FRAME_PARMS *frame_parms) {
|
||||
int dmrs_modulations_per_symbol = 33;
|
||||
int16_t mod_dmrs[NR_PSBCH_DMRS_LENGTH << 1];
|
||||
LOG_D(NR_PHY, "PSBCH DMRS mapping started at symbol %d\n", ssb_start_symbol);
|
||||
|
||||
/// QPSK modulation
|
||||
for (int m = 0; m < NR_PSBCH_DMRS_LENGTH; m++) {
|
||||
AssertFatal(((m << 1) >> 5) < NR_PSBCH_DMRS_LENGTH_DWORD, "Invalid index size %d\n", (m << 1) >> 5);
|
||||
int idx = (((gold_psbch_dmrs[(m << 1) >> 5]) >> ((m << 1) & 0x1f)) & 3);
|
||||
AssertFatal(((idx << 1) + 1) < (sizeof(nr_qpsk_mod_table) / sizeof(nr_qpsk_mod_table[0])), "Invalid index size %d\n", (idx << 1) + 1);
|
||||
AssertFatal((m << 1) + 1 < (sizeof(mod_dmrs) / sizeof(mod_dmrs[0])), "Invalid index size %d\n", (idx << 1) + 1);
|
||||
mod_dmrs[m << 1] = nr_qpsk_mod_table[idx << 1];
|
||||
mod_dmrs[(m << 1) + 1] = nr_qpsk_mod_table[(idx << 1) + 1];
|
||||
#ifdef DEBUG_PSBCH_DMRS
|
||||
printf("m %d idx %d gold seq %d b0-b1 %d-%d mod_dmrs %d %d\n", m, idx, gold_psbch_dmrs[(m << 1) >> 5], (((gold_psbch_dmrs[(m << 1) >> 5]) >> ((m << 1) & 0x1f)) & 1),
|
||||
(((gold_psbch_dmrs[((m << 1) + 1) >> 5]) >> (((m << 1)+1) & 0x1f)) & 1), mod_dmrs[(m << 1)], mod_dmrs[(m << 1)+1]);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Resource mapping
|
||||
// PSBCH DMRS are mapped within the SSB block on every fourth subcarrier starting from nushift of symbols 1, 2, 3
|
||||
///symbol 0 [0+nushift:4:236+nushift] -- 33 mod symbols
|
||||
int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier;
|
||||
int l = ssb_start_symbol;
|
||||
int m = 0;
|
||||
for (; m < dmrs_modulations_per_symbol; m++) {
|
||||
#ifdef DEBUG_PSBCH_DMRS
|
||||
printf("m %d at k %d of l %d\n", m, k, l);
|
||||
#endif
|
||||
AssertFatal(((m << 1) + 1) < (sizeof(mod_dmrs) / sizeof(mod_dmrs[0])), "Invalid index into mod_dmrs. Index %d > %lu\n",
|
||||
(m << 1) + 1, (sizeof(mod_dmrs) / sizeof(mod_dmrs[0])));
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].r = (amp * mod_dmrs[m << 1]) >> 15;
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].i = (amp * mod_dmrs[(m << 1) + 1]) >> 15;
|
||||
#ifdef DEBUG_PSBCH_DMRS
|
||||
printf("(%d,%d)\n",
|
||||
((int16_t *)txdataF)[(l * frame_parms->ofdm_symbol_size + k)].r,
|
||||
((int16_t *)txdataF)[(l * frame_parms->ofdm_symbol_size + k)].i);
|
||||
#endif
|
||||
k+=4;
|
||||
if (k >= frame_parms->ofdm_symbol_size)
|
||||
k-=frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
|
||||
int N_SSSB_Symb = 13;
|
||||
l = ssb_start_symbol + 5;
|
||||
while (l < N_SSSB_Symb)
|
||||
{
|
||||
k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier;
|
||||
int mod_count = 0;
|
||||
while (m < NR_PSBCH_DMRS_LENGTH) {
|
||||
#ifdef DEBUG_PSBCH_DMRS
|
||||
printf("m %d at k %d of l %d\n", m, k, l);
|
||||
#endif
|
||||
AssertFatal(((m << 1) + 1) < (sizeof(mod_dmrs) / sizeof(mod_dmrs[0])), "Invalid index into mod_dmrs. Index %d > %lu\n",
|
||||
(m << 1) + 1, (sizeof(mod_dmrs) / sizeof(mod_dmrs[0])));
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].r = (amp * mod_dmrs[m << 1]) >> 15;
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].i = (amp * mod_dmrs[(m << 1) + 1]) >> 15;
|
||||
#ifdef DEBUG_PSBCH_DMRS
|
||||
printf("%d (%d,%d)\n", m,
|
||||
((int16_t *)txdataF)[(l * frame_parms->ofdm_symbol_size + k)].r,
|
||||
((int16_t *)txdataF)[(l * frame_parms->ofdm_symbol_size + k)].i);
|
||||
#endif
|
||||
k+=4;
|
||||
if (k >= frame_parms->ofdm_symbol_size)
|
||||
k-=frame_parms->ofdm_symbol_size;
|
||||
mod_count++;
|
||||
m++;
|
||||
if (mod_count == dmrs_modulations_per_symbol)
|
||||
break;
|
||||
}
|
||||
l++;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PSBCH_DMRS
|
||||
write_output("txdataF_psbch_dmrs.m", "txdataF_psbch_dmrs", txdataF[0], frame_parms->samples_per_frame_wCP>>1, 1, 1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -44,13 +44,14 @@
|
||||
#include "PHY/NR_REFSIG/pss_nr.h"
|
||||
#include "PHY/NR_REFSIG/sss_nr.h"
|
||||
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
|
||||
extern openair0_config_t openair0_cfg[];
|
||||
//static nfapi_nr_config_request_t config_t;
|
||||
//static nfapi_nr_config_request_t* config =&config_t;
|
||||
int cnt=0;
|
||||
|
||||
#define DEBUG_INITIAL_SYNCH
|
||||
#define DEBUG_INITIAL_SYNCH 1
|
||||
#define DUMP_PBCH_CH_ESTIMATES 0
|
||||
|
||||
// create a new node of SSB structure
|
||||
@@ -197,9 +198,169 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini
|
||||
|
||||
}
|
||||
|
||||
int nr_psbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int psbch_initial_symbol, NR_UE_PDCCH_CONFIG *phy_pdcch_config)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
int ret = -1;
|
||||
NR_UE_SSB *best_ssb = NULL;
|
||||
NR_UE_SSB *current_ssb;
|
||||
uint8_t N_L = 2;
|
||||
uint8_t N_hf = 0;
|
||||
for (int l = 0; l < N_L; l++) {
|
||||
current_ssb = create_ssb_node(l, N_hf);
|
||||
start_meas(&ue->dlsch_channel_estimation_stats);
|
||||
// computing correlation between received DMRS symbols and transmitted sequence for current i_ssb and n_hf
|
||||
for (int i = psbch_initial_symbol; i < 13; i++) {
|
||||
if (i >= 1 && i <= 4)
|
||||
continue;
|
||||
nr_psbch_dmrs_correlation(ue, proc, 0, 0, i, i - psbch_initial_symbol, current_ssb);
|
||||
}
|
||||
stop_meas(&ue->dlsch_channel_estimation_stats);
|
||||
|
||||
current_ssb->metric = current_ssb->c_re*current_ssb->c_re + current_ssb->c_im*current_ssb->c_im;
|
||||
|
||||
// generate a list of SSB structures
|
||||
if (best_ssb == NULL)
|
||||
best_ssb = current_ssb;
|
||||
else
|
||||
best_ssb = insert_into_list(best_ssb, current_ssb);
|
||||
|
||||
}
|
||||
NR_UE_SSB *temp_ptr = best_ssb;
|
||||
while (ret != 0 && temp_ptr != NULL) {
|
||||
start_meas(&ue->dlsch_channel_estimation_stats);
|
||||
const int estimateSz = frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates[frame_parms->nb_antennas_rx][estimateSz];
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_time[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size];
|
||||
|
||||
for (int i = psbch_initial_symbol; i < 13; i++) {
|
||||
if (i >= 1 && i <= 4)
|
||||
continue;
|
||||
nr_psbch_channel_estimation(ue, estimateSz, dl_ch_estimates, dl_ch_estimates_time,
|
||||
proc, 0, 0, i, i - psbch_initial_symbol, temp_ptr->i_ssb, temp_ptr->n_hf);
|
||||
}
|
||||
stop_meas(&ue->dlsch_channel_estimation_stats);
|
||||
nr_ue_sl_ssb_rsrp_measurements(ue, temp_ptr->i_ssb, proc);
|
||||
fapiPsbch_t result;
|
||||
ret = nr_rx_psbch(ue, proc, estimateSz, dl_ch_estimates, ue->psbch_vars[0], frame_parms,
|
||||
0, temp_ptr->i_ssb, SISO, phy_pdcch_config, &result);
|
||||
temp_ptr = temp_ptr->next_ssb;
|
||||
}
|
||||
free_list(best_ssb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char duplex_string[2][4] = {"FDD","TDD"};
|
||||
char prefix_string[2][9] = {"NORMAL","EXTENDED"};
|
||||
|
||||
int nr_sl_initial_sync(UE_nr_rxtx_proc_t *proc,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
int n_frames)
|
||||
{
|
||||
/* Initial synchronisation
|
||||
*
|
||||
* 1 radio frame = 10 ms
|
||||
* <--------------------------------------------------------------------------->
|
||||
* -----------------------------------------------------------------------------
|
||||
* | Received UE data buffer |
|
||||
* ----------------------------------------------------------------------------
|
||||
* -------------------------------------------------
|
||||
* <-------------->| psbch | spss | spss | ssss | ssss | psbch |....
|
||||
* -------------------------------------------------
|
||||
* sync_pos SL S-SSB/PSBCH block
|
||||
*/
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INITIAL_UE_SYNC, VCD_FUNCTION_IN);
|
||||
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
LOG_I(NR_PHY, "nr_initial SL sync ue RB_DL %d prefix 0 %d\n", fp->N_RB_DL, fp->nb_prefix_samples0);
|
||||
int ret = -1;
|
||||
int32_t sync_pos = 0;
|
||||
for (int is = 0; is < n_frames; is++) {
|
||||
sync_pos = pss_synchro_nr(ue, is, NO_RATE_CHANGE);
|
||||
if (sync_pos >= fp->nb_prefix_samples) {
|
||||
// In 5G SL, the first SSB symbol is the PSBCH, so we need adjust the SSB
|
||||
// offset accordingly (psbch_plus_prefix_size). Additionally, there are 2
|
||||
// PSS symbols. So in the case where we correlate on the second PSS,
|
||||
// we need to adjust the SSB offset accordingly (subtracting first PSS prefix).
|
||||
// However, if we correlated on the second PSS, we do not need to include
|
||||
// the size of the first PSS0, becasue the correlation occurs on each individual PSS.
|
||||
// The sync position (sync_pos) is the start of the found PSS + nb_prefix_samples.
|
||||
// PSBCH PREFIX | PSBCH 0 | PSS 0 PREFIX | PSS 0 | PSS 1 PREFIX | PSS 1 |
|
||||
// 176 | 2048 | 144 | 2048 | 144 | 2048 |
|
||||
// ----------------------------------------------------------------------
|
||||
// 176 | 2048 | 144 | - | 144 | X | SSB Offset = X - (144 + 144 + 2048 + 144)
|
||||
// 176 | 2048 | 144 | X | 144 | 2048 | SSB Offset = X - (144 + 2048 + 144)
|
||||
uint32_t psbch_plus_prefix_size = fp->ofdm_symbol_size + fp->nb_prefix_samples0;
|
||||
uint32_t num_pss_prefix_samples_size = fp->nb_prefix_samples;/*(ue->common_vars.N2_id + 1) * fp->nb_prefix_samples;*/
|
||||
LOG_I(NR_PHY, "This is num_pss_prefix_samples_size %d, psbch_plus_prefix_size %d, sync_pos %d, N2_id %d\n",
|
||||
num_pss_prefix_samples_size, psbch_plus_prefix_size, sync_pos, ue->common_vars.N2_id);
|
||||
ue->ssb_offset = sync_pos - num_pss_prefix_samples_size - psbch_plus_prefix_size;
|
||||
} else {
|
||||
ue->ssb_offset = sync_pos + (fp->samples_per_subframe * 10) - fp->nb_prefix_samples;
|
||||
}
|
||||
LOG_I(NR_PHY, "[UE%d] Initial SL sync : n_frames %d Estimated PSS position %d, Nid2 %d ssb_offset %d prefix0 %d\n",
|
||||
ue->Mod_id, n_frames, sync_pos, ue->common_vars.N2_id, ue->ssb_offset,ue->frame_parms.nb_prefix_samples0);
|
||||
if (sync_pos < (NR_NUMBER_OF_SUBFRAMES_PER_FRAME * fp->samples_per_subframe - (NB_SYMBOLS_PBCH * fp->ofdm_symbol_size))) {
|
||||
uint8_t phase_tdd_ncp;
|
||||
int32_t metric_tdd_ncp = 0;
|
||||
const uint32_t rxdataF_sz = ue->frame_parms.samples_per_slot_wCP;
|
||||
__attribute__ ((aligned(32))) c16_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz];
|
||||
for (int i = 0; i < 13; i++)
|
||||
nr_slot_fep_init_sync(ue, proc, i, is * fp->samples_per_frame + ue->ssb_offset,
|
||||
false, rxdataF);
|
||||
memcpy(ue->common_vars.rxdataF[0], rxdataF[0], rxdataF_sz * sizeof(int32_t));
|
||||
LOG_I(NR_PHY, "Calling sss detection (normal CP) prefix0 %d\n",ue->frame_parms.nb_prefix_samples0);
|
||||
int freq_offset_sss = 0;
|
||||
ret = rx_sss_sl_nr(ue, proc, &metric_tdd_ncp, &phase_tdd_ncp, &freq_offset_sss);
|
||||
if (ue->UE_fo_compensation) {
|
||||
double sampling_time = 1 / (1.0e3 * fp->samples_per_subframe);
|
||||
double off_angle = -2 * M_PI * sampling_time * freq_offset_sss;
|
||||
int start = is * fp->samples_per_frame + ue->ssb_offset;
|
||||
int end = start + NR_N_SYMBOLS_SSB * (fp->ofdm_symbol_size + fp->nb_prefix_samples);
|
||||
for (int n = start; n < end; n++) {
|
||||
for (int ar = 0; ar < fp->nb_antennas_rx; ar++) {
|
||||
double re = ((double)(((short *)ue->common_vars.rxdata[ar]))[2 * n]);
|
||||
double im = ((double)(((short *)ue->common_vars.rxdata[ar]))[2 * n + 1]);
|
||||
((short *)ue->common_vars.rxdata[ar])[2 * n] = (short)(round(re * cos(n * off_angle) - im * sin(n * off_angle)));
|
||||
((short *)ue->common_vars.rxdata[ar])[2 * n + 1] = (short)(round(re * sin(n * off_angle) + im *cos(n * off_angle)));
|
||||
}
|
||||
}
|
||||
ue->common_vars.freq_offset += freq_offset_sss;
|
||||
}
|
||||
if (ret == 0) {
|
||||
nr_gold_psbch(ue);
|
||||
NR_UE_PDCCH_CONFIG phy_pdcch_config = {0};
|
||||
ret = nr_psbch_detection(proc, ue, 0, &phy_pdcch_config);
|
||||
}
|
||||
LOG_I(NR_PHY, "TDD Normal prefix: CellId %d metric %d, phase %d, psbch %d\n",
|
||||
fp->Nid_cell, metric_tdd_ncp, phase_tdd_ncp, ret);
|
||||
} else {
|
||||
LOG_I(NR_PHY, "TDD Normal prefix: SSS error condition: sync_pos %d\n", sync_pos);
|
||||
}
|
||||
if (ret == 0) break;
|
||||
if (ret < 0) exit(-1);
|
||||
}
|
||||
if (ret == 0) {
|
||||
LOG_I(NR_PHY, "[UE %d] rx_offset %d Measured Carrier Frequency %.0f Hz (offset %d Hz) prefix0 %d\n",
|
||||
ue->Mod_id, ue->rx_offset_sl, openair0_cfg[0].rx_freq[0] + ue->common_vars.freq_offset, ue->common_vars.freq_offset,ue->frame_parms.nb_prefix_samples0);
|
||||
if (ue->UE_scan_carrier == 0) {
|
||||
ue->psbch_vars[0]->pdu_errors_conseq = 0;
|
||||
}
|
||||
} else {
|
||||
LOG_I(NR_PHY, "[UE%d] Initial sync : PSBCH not ok. Estimated PSS position %d, Nid1 %d, Nid2 %d, Frame_type %d\n",
|
||||
ue->Mod_id, sync_pos, GET_NID1_SL(fp->Nid_SL), GET_NID2_SL(fp->Nid_SL), fp->frame_type);
|
||||
ue->psbch_vars[0]->pdu_errors_last = ue->psbch_vars[0]->pdu_errors;
|
||||
ue->psbch_vars[0]->pdu_errors++;
|
||||
ue->psbch_vars[0]->pdu_errors_conseq++;
|
||||
int rx_power = 0;
|
||||
ue->measurements.rx_power_avg[0] = rx_power / fp->nb_antennas_rx;
|
||||
ue->measurements.rx_power_avg_dB[0] = dB_fixed(ue->measurements.rx_power_avg[0]);
|
||||
LOG_I(NR_PHY, "[UE%d] Gain Control - Initial sync : Estimated power: %d dB\n", ue->Mod_id, ue->measurements.rx_power_avg_dB[0]);
|
||||
}
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INITIAL_UE_SYNC, VCD_FUNCTION_OUT);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int nr_initial_sync(UE_nr_rxtx_proc_t *proc,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
int n_frames, int sa)
|
||||
|
||||
450
openair1/PHY/NR_UE_TRANSPORT/nr_psbch.c
Normal file
450
openair1/PHY/NR_UE_TRANSPORT/nr_psbch.c
Normal file
@@ -0,0 +1,450 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file PHY/LTE_TRANSPORT/psbch.c
|
||||
* \brief Top-level routines for generating and decoding the PSBCH/BCH physical/transport channel V8.6 2009-03
|
||||
* \author R. Knopp, F. Kaltenberger
|
||||
* \date 2011
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email: knopp@eurecom.fr,florian.kaltenberger.fr
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/CODING/coding_extern.h"
|
||||
#include "PHY/phy_extern_nr_ue.h"
|
||||
#include "PHY/sse_intrin.h"
|
||||
#include "PHY/LTE_REFSIG/lte_refsig.h"
|
||||
#include "openair1/SCHED_NR_UE/defs.h"
|
||||
#include <openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h>
|
||||
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
|
||||
#include "openair1/PHY/NR_REFSIG/refsig_defs_ue.h"
|
||||
|
||||
// #define DEBUG_PSBCH
|
||||
//#define DEBUG_PSBCH_ENCODING
|
||||
|
||||
//#include "PHY_INTERFACE/defs.h"
|
||||
|
||||
|
||||
static void nr_psbch_quantize(int16_t *psbch_llr8,
|
||||
int16_t *psbch_llr,
|
||||
uint16_t len) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (psbch_llr[i] > 31)
|
||||
psbch_llr8[i] = 32;
|
||||
else if (psbch_llr[i] < -31)
|
||||
psbch_llr8[i] = -32;
|
||||
else
|
||||
psbch_llr8[i] = psbch_llr[i];
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t nr_psbch_extract(c16_t **rxdataF,
|
||||
const int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
struct complex16 rxdataF_ext[][PSBCH_MAX_RE_PER_SYMBOL],
|
||||
struct complex16 dl_ch_estimates_ext[][PSBCH_MAX_RE_PER_SYMBOL],
|
||||
uint32_t symbol,
|
||||
uint32_t s_offset,
|
||||
NR_DL_FRAME_PARMS *frame_parms) {
|
||||
uint16_t rb;
|
||||
uint8_t i,j,aarx;
|
||||
int nushiftmod4 = 0;//frame_parms->nushift;
|
||||
AssertFatal(symbol == 0 || symbol < 14,
|
||||
"symbol %d illegal for PSBCH extraction\n",
|
||||
symbol);
|
||||
|
||||
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
|
||||
unsigned int rx_offset = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier;
|
||||
rx_offset = (rx_offset)%(frame_parms->ofdm_symbol_size);
|
||||
struct complex16 *rxF = (struct complex16 *)&rxdataF[aarx][(symbol+s_offset)*frame_parms->ofdm_symbol_size];
|
||||
struct complex16 *rxF_ext = rxdataF_ext[aarx];
|
||||
#ifdef DEBUG_PSBCH
|
||||
LOG_I(NR_PHY,"extract_rbs (nushift %d): rx_offset=%d, symbol %u\n",frame_parms->nushift,
|
||||
(rx_offset + ((symbol+s_offset)*(frame_parms->ofdm_symbol_size))),symbol);
|
||||
int16_t *p = (int16_t *)rxF;
|
||||
|
||||
for (int i =0; i<8; i++) {
|
||||
LOG_I(NR_PHY,"rxF [%d]= %d\n",i,rxF[i]);
|
||||
LOG_I(NR_PHY,"psbch extract rxF %d %d addr %p\n", p[2*i], p[2*i+1], &p[2*i]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
for (rb=0; rb<11; rb++) {
|
||||
j=0;
|
||||
|
||||
if (symbol == 0 || ((symbol > 4) && (symbol <= 13))) {
|
||||
for (i=0; i<12; i++) {
|
||||
if ((i!=nushiftmod4) &&
|
||||
(i!=(nushiftmod4+4)) &&
|
||||
(i!=(nushiftmod4+8))) {
|
||||
rxF_ext[j]=rxF[rx_offset];
|
||||
#ifdef DEBUG_PSBCH
|
||||
LOG_I(NR_PHY,"rxF ext[%d] = (%d,%d) rxF [%u]= (%d,%d)\n", (9*rb) + j,
|
||||
rxF_ext[j].r, rxF_ext[j].i,
|
||||
rx_offset,
|
||||
rxF[rx_offset].r,rxF[rx_offset].i);
|
||||
#endif
|
||||
j++;
|
||||
}
|
||||
|
||||
rx_offset=(rx_offset+1)%(frame_parms->ofdm_symbol_size);
|
||||
//rx_offset = (rx_offset >= frame_parms->ofdm_symbol_size) ? (rx_offset - frame_parms->ofdm_symbol_size + 1) : (rx_offset+1);
|
||||
}
|
||||
|
||||
rxF_ext+=9;
|
||||
}
|
||||
}
|
||||
|
||||
struct complex16 *dl_ch0 = &dl_ch_estimates[aarx][((symbol+s_offset)*(frame_parms->ofdm_symbol_size))];
|
||||
|
||||
//printf("dl_ch0 addr %p\n",dl_ch0);
|
||||
struct complex16 *dl_ch0_ext = dl_ch_estimates_ext[aarx];
|
||||
|
||||
for (rb=0; rb<11; rb++) {
|
||||
j=0;
|
||||
|
||||
if (symbol == 0 || ((symbol > 4) && (symbol <= 13))) {
|
||||
for (i=0; i<12; i++) {
|
||||
if ((i!=nushiftmod4) &&
|
||||
(i!=(nushiftmod4+4)) &&
|
||||
(i!=(nushiftmod4+8))) {
|
||||
dl_ch0_ext[j]=dl_ch0[i];
|
||||
#ifdef DEBUG_PSBCH
|
||||
if ((rb==0) && (i<2))
|
||||
printf("dl ch0 ext[%d] = (%d,%d) dl_ch0 [%d]= (%d,%d)\n",j,
|
||||
dl_ch0_ext[j].r, dl_ch0_ext[j].i,
|
||||
i,
|
||||
dl_ch0[j].r, dl_ch0[j].i);
|
||||
#endif
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
dl_ch0+=12;
|
||||
dl_ch0_ext+=9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
//__m128i avg128;
|
||||
|
||||
//compute average channel_level on each (TX,RX) antenna pair
|
||||
int nr_psbch_channel_level(struct complex16 dl_ch_estimates_ext[][PSBCH_MAX_RE_PER_SYMBOL],
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
int nb_re) {
|
||||
int16_t nb_rb=nb_re/12;
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
__m128i avg128;
|
||||
__m128i *dl_ch128;
|
||||
#elif defined(__arm__)
|
||||
int32x4_t avg128;
|
||||
int16x8_t *dl_ch128;
|
||||
#endif
|
||||
int avg1=0,avg2=0;
|
||||
|
||||
for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
|
||||
//clear average level
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
avg128 = _mm_setzero_si128();
|
||||
dl_ch128=(__m128i *)dl_ch_estimates_ext[aarx];
|
||||
#elif defined(__arm__)
|
||||
avg128 = vdupq_n_s32(0);
|
||||
dl_ch128=(int16x8_t *)dl_ch_estimates_ext[aarx];
|
||||
#endif
|
||||
|
||||
for (int rb=0; rb<nb_rb; rb++) {
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
avg128 = _mm_add_epi32(avg128,_mm_madd_epi16(dl_ch128[0],dl_ch128[0]));
|
||||
avg128 = _mm_add_epi32(avg128,_mm_madd_epi16(dl_ch128[1],dl_ch128[1]));
|
||||
avg128 = _mm_add_epi32(avg128,_mm_madd_epi16(dl_ch128[2],dl_ch128[2]));
|
||||
#elif defined(__arm__)
|
||||
abort();
|
||||
// to be filled in
|
||||
#endif
|
||||
dl_ch128+=3;
|
||||
/*
|
||||
if (rb==0) {
|
||||
print_shorts("dl_ch128",&dl_ch128[0]);
|
||||
print_shorts("dl_ch128",&dl_ch128[1]);
|
||||
print_shorts("dl_ch128",&dl_ch128[2]);
|
||||
}*/
|
||||
}
|
||||
|
||||
avg1 = (((int *)&avg128)[0] +
|
||||
((int *)&avg128)[1] +
|
||||
((int *)&avg128)[2] +
|
||||
((int *)&avg128)[3])/(nb_rb*12);
|
||||
|
||||
if (avg1>avg2)
|
||||
avg2 = avg1;
|
||||
|
||||
//LOG_I(PHY,"Channel level : %d, %d\n",avg1, avg2);
|
||||
}
|
||||
|
||||
return(avg2);
|
||||
}
|
||||
|
||||
static void nr_psbch_channel_compensation(struct complex16 rxdataF_ext[][PSBCH_MAX_RE_PER_SYMBOL],
|
||||
struct complex16 dl_ch_estimates_ext[][PSBCH_MAX_RE_PER_SYMBOL],
|
||||
int nb_re,
|
||||
struct complex16 rxdataF_comp[][PSBCH_MAX_RE_PER_SYMBOL],
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t output_shift) {
|
||||
for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
|
||||
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);
|
||||
*rxdataF_comp128++ = mulByConjugate128(rxdataF128++, dl_ch128++, output_shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void nr_psbch_unscrambling(NR_UE_PSBCH *psbch,
|
||||
int16_t *demod_psbch_e,
|
||||
uint16_t Nid,
|
||||
uint8_t nushift,
|
||||
uint16_t M,
|
||||
uint16_t length,
|
||||
uint8_t bitwise,
|
||||
uint32_t unscrambling_mask,
|
||||
uint32_t psbch_a_prime,
|
||||
uint32_t *psbch_a_interleaved) {
|
||||
uint8_t reset, offset;
|
||||
uint32_t x1, x2, s=0;
|
||||
uint8_t k=0;
|
||||
reset = 1;
|
||||
// x1 is set in first call to lte_gold_generic
|
||||
x2 = Nid; //this is c_init
|
||||
|
||||
// The Gold sequence is shifted by nushift* M, so we skip (nushift*M /32) double words
|
||||
for (int i=0; i<(uint16_t)ceil(((float)M)/32); i++) {
|
||||
s = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
}
|
||||
|
||||
// Scrambling is now done with offset (nushift*M)%32
|
||||
offset = 0; //(nushift*M)&0x1f;
|
||||
|
||||
for (int i=0; i<length; i++) {
|
||||
/*if (((i+offset)&0x1f)==0) {
|
||||
s = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
}*/
|
||||
if (bitwise) {
|
||||
if (((k+offset)&0x1f)==0 && (!((unscrambling_mask>>i)&1))) {
|
||||
s = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
}
|
||||
|
||||
*psbch_a_interleaved ^= ((unscrambling_mask>>i)&1)? ((psbch_a_prime>>i)&1)<<i : (((psbch_a_prime>>i)&1) ^ ((s>>((k+offset)&0x1f))&1))<<i;
|
||||
k += (!((unscrambling_mask>>i)&1));
|
||||
#ifdef DEBUG_PSBCH_ENCODING
|
||||
printf("i %d k %d offset %d (unscrambling_mask>>i)&1) %d s: %08x\t psbch_a_interleaved 0x%08x (!((unscrambling_mask>>i)&1)) %d\n", i, k, offset, (unscrambling_mask>>i)&1, s, *psbch_a_interleaved,
|
||||
(!((unscrambling_mask>>i)&1)));
|
||||
#endif
|
||||
} else {
|
||||
if (((i+offset)&0x1f)==0) {
|
||||
s = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
}
|
||||
|
||||
if (((s>>((i+offset)&0x1f))&1)==1)
|
||||
demod_psbch_e[i] = -demod_psbch_e[i];
|
||||
|
||||
#ifdef DEBUG_PSBCH_ENCODING
|
||||
|
||||
if (i<8)
|
||||
printf("s %d demod_psbch_e[i] %d\n", ((s>>((i+offset)&0x1f))&1), demod_psbch_e[i]);
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nr_sl_common_signal_procedures(PHY_VARS_NR_UE *ue, int frame, int slot)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
c16_t **txdataF = ue->common_vars.txdataF;
|
||||
uint8_t ssb_index = 0; //TODO: Need update to get 0 or 1 from parameter in case of mu = 1.
|
||||
int txdataF_offset = slot * fp->samples_per_slot_wCP;
|
||||
|
||||
uint16_t ssb_start_symbol = 0;
|
||||
LOG_D(NR_PHY, "common_signal_procedures: frame %d, slot %d ssb index %d, ssb_start_symbol %d, txdataF_offset %d\n",
|
||||
frame, slot, ssb_index, ssb_start_symbol, txdataF_offset);
|
||||
|
||||
const int prb_offset = 0; //TODO: Need to properly get these values.
|
||||
const int sc_offset = 0; //TODO: Need to properly get these values.
|
||||
fp->ssb_start_subcarrier = prb_offset * 12 + sc_offset;
|
||||
LOG_D(NR_PHY, "SSB first subcarrier %d (%d,%d)\n", fp->ssb_start_subcarrier, prb_offset, sc_offset);
|
||||
nr_gold_psbch(ue);
|
||||
nr_sl_generate_pss(&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, fp);
|
||||
nr_sl_generate_sss(&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, fp);
|
||||
nr_sl_generate_psbch_dmrs(&ue->nr_gold_psbch[ssb_index & 7], &txdataF[0][txdataF_offset], AMP, ssb_start_symbol, fp);
|
||||
uint8_t n_hf = 0;
|
||||
nr_generate_sl_psbch(ue, &txdataF[0][txdataF_offset], AMP, ssb_start_symbol, n_hf, frame, fp);
|
||||
}
|
||||
|
||||
int nr_rx_psbch( PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int estimateSz, struct complex16 dl_ch_estimates [][estimateSz],
|
||||
NR_UE_PSBCH *nr_ue_psbch_vars,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t gNB_id,
|
||||
uint8_t i_ssb,
|
||||
MIMO_mode_t mimo_mode,
|
||||
NR_UE_PDCCH_CONFIG *phy_pdcch_config,
|
||||
fapiPsbch_t *result) {
|
||||
|
||||
NR_UE_COMMON *nr_ue_common_vars = &ue->common_vars;
|
||||
uint8_t ssb_index = 0; //TODO: Need update to get 0 or 1 from parameter in case of mu = 1.
|
||||
int symbol_offset = ue->is_synchronized > 0 ? (ue->slss->sl_timeoffsetssb_r16 + ue->slss->sl_timeinterval_r16 * ssb_index) * frame_parms->symbols_per_slot : 0;
|
||||
int psbch_e_rx_idx = 0;
|
||||
int16_t psbch_unClipped[NR_POLAR_PSBCH_E] = {0};
|
||||
int16_t psbch_e_rx[NR_POLAR_PSBCH_E] = {0};
|
||||
// symbol refers to symbol within SSB. symbol_offset is the offset of the SSB wrt start of slot
|
||||
for (int symbol = 0; symbol < 13; symbol++) {
|
||||
const uint16_t nb_re = 99;
|
||||
__attribute__ ((aligned(32))) struct complex16 rxdataF_ext[frame_parms->nb_antennas_rx][PSBCH_MAX_RE_PER_SYMBOL];
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_ext[frame_parms->nb_antennas_rx][PSBCH_MAX_RE_PER_SYMBOL];
|
||||
memset(dl_ch_estimates_ext,0, sizeof dl_ch_estimates_ext);
|
||||
nr_psbch_extract(nr_ue_common_vars->rxdataF,
|
||||
estimateSz,
|
||||
dl_ch_estimates,
|
||||
rxdataF_ext,
|
||||
dl_ch_estimates_ext,
|
||||
symbol,
|
||||
symbol_offset,
|
||||
frame_parms);
|
||||
|
||||
int log2_maxh = 0;
|
||||
if (symbol == 0) {
|
||||
int max_h = nr_psbch_channel_level(dl_ch_estimates_ext,
|
||||
frame_parms,
|
||||
nb_re);
|
||||
log2_maxh = 3 + (log2_approx(max_h) / 2);
|
||||
#ifdef DEBUG_PSBCH
|
||||
LOG_I(NR_PHY, "PSBCH Symbol %d ofdm size %d\n", symbol, frame_parms->ofdm_symbol_size );
|
||||
LOG_I(NR_PHY,"PSBCH log2_maxh = %d (%d)\n", log2_maxh, max_h);
|
||||
#endif
|
||||
}
|
||||
|
||||
__attribute__ ((aligned(32))) struct complex16 rxdataF_comp[frame_parms->nb_antennas_rx][PSBCH_MAX_RE_PER_SYMBOL];
|
||||
nr_psbch_channel_compensation(rxdataF_ext,
|
||||
dl_ch_estimates_ext,
|
||||
nb_re,
|
||||
rxdataF_comp,
|
||||
frame_parms,
|
||||
log2_maxh); // log2_maxh+I0_shift
|
||||
|
||||
int nb = 198; // QPSK 2 bits 99*2 (m from TX side)
|
||||
nr_psbch_quantize(psbch_e_rx + psbch_e_rx_idx, (short *)rxdataF_comp[0], nb);
|
||||
memcpy(psbch_unClipped + psbch_e_rx_idx, rxdataF_comp[0], nb*sizeof(int16_t));
|
||||
psbch_e_rx_idx += nb;
|
||||
|
||||
if (symbol == 0)
|
||||
symbol += 4; // skip to accommodate PSS and SSS
|
||||
}
|
||||
// legacy code use int16, but it is complex16
|
||||
UEscopeCopy(ue, psbchRxdataF_comp, psbch_unClipped, sizeof(struct complex16), frame_parms->nb_antennas_rx, psbch_e_rx_idx/2);
|
||||
UEscopeCopy(ue, psbchLlr, psbch_e_rx, sizeof(int16_t), frame_parms->nb_antennas_rx, psbch_e_rx_idx);
|
||||
#ifdef DEBUG_PSBCH
|
||||
for (int cnt = 0; cnt < NR_POLAR_PSBCH_E; cnt++)
|
||||
printf("psbch rx llr %d\n",*(psbch_e_rx + cnt));
|
||||
|
||||
#endif
|
||||
//un-scrambling
|
||||
uint16_t M = NR_POLAR_PSBCH_E;
|
||||
uint8_t nushift = 0; //(Lmax==4)? i_ssb&3 : i_ssb&7;
|
||||
uint32_t psbch_a_interleaved = 0;
|
||||
uint32_t psbch_a_prime = 0;
|
||||
nr_psbch_unscrambling(nr_ue_psbch_vars, psbch_e_rx, frame_parms->Nid_SL, nushift, M, NR_POLAR_PSBCH_E,
|
||||
0, 0, psbch_a_prime, &psbch_a_interleaved);
|
||||
//polar decoding de-rate matching
|
||||
uint64_t tmp = 0;
|
||||
uint32_t decoderState = polar_decoder_int16(psbch_e_rx, (uint64_t *)&tmp, 0,
|
||||
NR_POLAR_PSBCH_MESSAGE_TYPE,
|
||||
NR_POLAR_PSBCH_PAYLOAD_BITS,
|
||||
NR_POLAR_PSBCH_AGGREGATION_LEVEL);
|
||||
psbch_a_prime = tmp;
|
||||
if(decoderState)
|
||||
return(decoderState);
|
||||
|
||||
uint32_t payload = 0;
|
||||
for (int i = 0; i < NR_POLAR_PSBCH_PAYLOAD_BITS; i++)
|
||||
payload |= (((uint64_t)psbch_a_prime >> i) & 1) << (31 - i);
|
||||
LOG_I(NR_PHY, "PSBCH payload received 0x%x \n", payload);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
result->decoded_output[i] = (uint8_t)((payload >> ((3 - i) << 3)) & 0xff);
|
||||
|
||||
frame_parms->half_frame_bit = (result->xtra_byte >> 4) & 0x01; // computing the half frame index from the extra byte
|
||||
frame_parms->ssb_index = i_ssb; // ssb index corresponds to i_ssb for Lmax = 4,8
|
||||
|
||||
if (frame_parms->Lmax == 64) { // for Lmax = 64 ssb index 4th,5th and 6th bits are in extra byte
|
||||
for (int i = 0; i < 3; i++)
|
||||
frame_parms->ssb_index += (((result->xtra_byte >> (7 - i)) & 0x01) << (3 + i));
|
||||
}
|
||||
|
||||
ue->symbol_offset = 0;
|
||||
if (frame_parms->half_frame_bit)
|
||||
ue->symbol_offset += (frame_parms->slots_per_frame>>1)*frame_parms->symbols_per_slot;
|
||||
|
||||
uint8_t frame_number_4lsb = 0;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
frame_number_4lsb |= ((result->xtra_byte >> i) & 1) << (3 - i);
|
||||
|
||||
proc->decoded_frame_rx = frame_number_4lsb;
|
||||
#ifdef DEBUG_PSBCH
|
||||
printf("xtra_byte %x payload %x\n", result->xtra_byte, payload);
|
||||
|
||||
for (int i=0; i<(NR_POLAR_PSBCH_PAYLOAD_BITS>>3); i++) {
|
||||
// printf("unscrambling psbch_a[%d] = %x \n", i,psbch_a[i]);
|
||||
printf("[PSBCH] decoder payload[%d] = %x\n",i,result->decoded_output[i]);
|
||||
}
|
||||
// TODO: Handle MAC Layer on RX
|
||||
|
||||
nr_downlink_indication_t dl_indication;
|
||||
fapi_nr_rx_indication_t *rx_ind = calloc(1, sizeof(*rx_ind));
|
||||
uint16_t number_pdus = 1;
|
||||
|
||||
nr_fill_dl_indication(&dl_indication, NULL, rx_ind, proc, ue, gNB_id, phy_pdcch_config);
|
||||
nr_fill_rx_indication(rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, gNB_id, ue, NULL, NULL, number_pdus, proc,(void *)result);
|
||||
|
||||
if (ue->if_inst && ue->if_inst->dl_indication)
|
||||
ue->if_inst->dl_indication(&dl_indication, NULL);
|
||||
else
|
||||
free(rx_ind); // dl_indication would free(), so free() here if not called
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#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
|
||||
|
||||
extern short nr_qpsk_mod_table[8];
|
||||
// Functions below implement 36-211 and 36-212
|
||||
|
||||
/** @addtogroup _PHY_TRANSPORT_
|
||||
@@ -280,6 +281,54 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
|
||||
*/
|
||||
int rx_sss(PHY_VARS_NR_UE *phy_vars_ue,int32_t *tot_metric,uint8_t *flip_max,uint8_t *phase_max);
|
||||
|
||||
/*!
|
||||
\fn int nr_sl_generate_psbch_dmrs
|
||||
\brief Generation of the DMRS for the PSBCH
|
||||
@param
|
||||
@returns 0 on success
|
||||
*/
|
||||
int nr_sl_generate_psbch_dmrs(uint32_t *gold_pbch_dmrs,
|
||||
c16_t *txdataF,
|
||||
int16_t amp,
|
||||
uint8_t ssb_start_symbol,
|
||||
NR_DL_FRAME_PARMS *frame_parms);
|
||||
|
||||
/*!
|
||||
\fn int nr_generate_pss
|
||||
\brief Generation of the NR PSS
|
||||
@param
|
||||
@returns 0 on success
|
||||
*/
|
||||
int nr_sl_generate_pss(c16_t *txdataF,
|
||||
int16_t amp,
|
||||
uint8_t ssb_start_symbol,
|
||||
NR_DL_FRAME_PARMS *frame_parms);
|
||||
|
||||
/*!
|
||||
\fn int nr_generate_sss
|
||||
\brief Generation of the NR SSS
|
||||
@param
|
||||
@returns 0 on success
|
||||
*/
|
||||
int nr_sl_generate_sss(c16_t *txdataF,
|
||||
int16_t amp,
|
||||
uint8_t ssb_start_symbol,
|
||||
NR_DL_FRAME_PARMS *frame_parms);
|
||||
|
||||
/*!
|
||||
\fn int nr_generate_sl_pbch
|
||||
\brief Generation of the PBCH
|
||||
@param
|
||||
@returns 0 on success
|
||||
*/
|
||||
int nr_generate_sl_psbch(PHY_VARS_NR_UE *ue,
|
||||
c16_t *txdataF,
|
||||
int16_t amp,
|
||||
uint8_t ssb_start_symbol,
|
||||
uint8_t n_hf,
|
||||
int sfn,
|
||||
NR_DL_FRAME_PARMS *frame_parms);
|
||||
|
||||
/*! \brief receiver for the PBCH
|
||||
\returns number of tx antennas or -1 if error
|
||||
*/
|
||||
@@ -294,12 +343,34 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
|
||||
fapiPbch_t* result,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
/*! \brief receiver for the PBCH
|
||||
\returns number of tx antennas or -1 if error
|
||||
*/
|
||||
|
||||
void nr_sl_common_signal_procedures(PHY_VARS_NR_UE *ue, int frame, int slot);
|
||||
|
||||
int nr_rx_psbch(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
const int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
NR_UE_PSBCH *nr_ue_psbch_vars,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t eNB_id,
|
||||
uint8_t i_ssb,
|
||||
MIMO_mode_t mimo_mode,
|
||||
NR_UE_PDCCH_CONFIG *phy_pdcch_config,
|
||||
fapiPsbch_t* result);
|
||||
|
||||
int nr_pbch_detection(UE_nr_rxtx_proc_t *proc,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
int pbch_initial_symbol,
|
||||
nr_phy_data_t *phy_data,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
int nr_psbch_detection(UE_nr_rxtx_proc_t *proc,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
int psbch_initial_symbol,
|
||||
NR_UE_PDCCH_CONFIG *phy_pdcch_config);
|
||||
|
||||
#ifndef modOrder
|
||||
#define modOrder(I_MCS,I_TBS) ((I_MCS-I_TBS)*2+2) // Find modulation order from I_TBS and I_MCS
|
||||
@@ -307,6 +378,10 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t *proc,
|
||||
|
||||
int dump_ue_stats(PHY_VARS_NR_UE *phy_vars_ue, UE_nr_rxtx_proc_t *proc, char* buffer, int length, runmode_t mode, int input_level_dBm);
|
||||
|
||||
int nr_sl_initial_sync(UE_nr_rxtx_proc_t *proc,
|
||||
PHY_VARS_NR_UE *phy_vars_ue,
|
||||
int n_frames);
|
||||
|
||||
/*!
|
||||
\brief This function performs the initial cell search procedure - PSS detection, SSS detection and PBCH detection. At the
|
||||
end, the basic frame parameters are known (Frame configuration - TDD/FDD and cyclic prefix length,
|
||||
@@ -330,6 +405,13 @@ void nr_get_carrier_frequencies(PHY_VARS_NR_UE *ue,
|
||||
uint64_t *dl_Carrier,
|
||||
uint64_t *ul_Carrier);
|
||||
|
||||
/*!
|
||||
\brief This function gets the carrier frequencies either from FP or command-line-set global variables, depending on the availability of the latter
|
||||
@param fp Pointer to frame params
|
||||
@param sl_Carrier Pointer to SL carrier to be set
|
||||
*/
|
||||
void nr_get_carrier_frequencies_sl(PHY_VARS_NR_UE *ue,
|
||||
uint64_t *sl_Carrier);
|
||||
/*!
|
||||
\brief This function sets the OAI RF card rx/tx params
|
||||
@param openair0_cfg Pointer OAI config for a specific card
|
||||
@@ -347,6 +429,10 @@ void nr_rf_card_config_freq(openair0_config_t *openair0_cfg,
|
||||
uint64_t dl_Carrier,
|
||||
int freq_offset);
|
||||
|
||||
void nr_sl_rf_card_config_freq(PHY_VARS_NR_UE *ue,
|
||||
openair0_config_t *openair0_cfg,
|
||||
int freq_offset);
|
||||
|
||||
void nr_pdcch_unscrambling(int16_t *z,
|
||||
uint16_t scrambling_RNTI,
|
||||
uint32_t length,
|
||||
|
||||
@@ -166,6 +166,17 @@ typedef struct {
|
||||
uint8_t ptrs_symbol_index;
|
||||
} NR_UE_DLSCH_t;
|
||||
|
||||
typedef struct {
|
||||
long sl_numssb_withinperiod_r16;
|
||||
long sl_timeoffsetssb_r16;
|
||||
long sl_timeinterval_r16;
|
||||
long sl_numssb_withinperiod_r16_copy;
|
||||
long sl_timeinterval_r16_copy;
|
||||
long sl_timeoffsetssb_r16_copy;
|
||||
uint16_t slss_id;
|
||||
uint8_t sl_mib_length;
|
||||
uint8_t sl_mib[5];
|
||||
} NR_SLSS_t;
|
||||
|
||||
/**@}*/
|
||||
#endif
|
||||
|
||||
@@ -46,6 +46,15 @@ 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){
|
||||
@@ -113,3 +122,17 @@ void nr_rf_card_config_freq(openair0_config_t *openair0_cfg,
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void nr_sl_rf_card_config_freq(PHY_VARS_NR_UE *ue, openair0_config_t *openair0_cfg, int freq_offset) {
|
||||
|
||||
for (int i = 0; i < openair0_cfg->rx_num_channels; i++) {
|
||||
openair0_cfg->rx_gain[ue->rf_map.chain + i] = ue->rx_total_gain_dB;
|
||||
if (ue->UE_scan_carrier == 1) {
|
||||
if (freq_offset >= 0)
|
||||
openair0_cfg->rx_freq[ue->rf_map.chain + i] += abs(freq_offset);
|
||||
else
|
||||
openair0_cfg->rx_freq[ue->rf_map.chain + i] -= abs(freq_offset);
|
||||
freq_offset=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
254
openair1/PHY/NR_UE_TRANSPORT/psbch_nr_sl.c
Normal file
254
openair1/PHY/NR_UE_TRANSPORT/psbch_nr_sl.c
Normal file
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* 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/nr_psbch.c
|
||||
* \brief Top-level routines for generating the PSBCH/BCH physical/transport channel V15.1 03/2018
|
||||
* \author Guy De Souza
|
||||
* \thanks Special Thanks to Son Dang for helpful contributions and testing
|
||||
* \date 2018
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email: desouza@eurecom.fr
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/LTE_REFSIG/lte_refsig.h"
|
||||
#include "PHY/sse_intrin.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
|
||||
//#define DEBUG_PSBCH
|
||||
//#define DEBUG_PSBCH_ENCODING
|
||||
//#define DEBUG_PSBCH_DMRS
|
||||
|
||||
extern short nr_qpsk_mod_table[8];
|
||||
|
||||
static void nr_psbch_scrambling(NR_UE_PSBCH *psbch,
|
||||
uint32_t Nid,
|
||||
uint8_t nushift,
|
||||
uint16_t M,
|
||||
uint16_t length,
|
||||
uint8_t encoded,
|
||||
uint32_t unscrambling_mask) {
|
||||
uint32_t *psbch_e = psbch->psbch_e;
|
||||
uint8_t reset = 1;
|
||||
uint32_t x1, s = 0;
|
||||
uint32_t x2 = Nid;
|
||||
// The Gold sequence is shifted by nushift* M, so we skip (nushift*M /32) double words
|
||||
for (int i = 0; i < (uint16_t)ceil(((float)M) / 32); i++) {
|
||||
s = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
}
|
||||
|
||||
// Scrambling is now done with offset (nushift*M)%32
|
||||
uint8_t offset = 0; //(nushift*M)&0x1f;
|
||||
#ifdef DEBUG_PSBCH_ENCODING
|
||||
printf("Scrambling params: nushift %d M %d length %d encoded %d offset %d\n", nushift, M, length, encoded, offset);
|
||||
#endif
|
||||
#ifdef DEBUG_PSBCH_ENCODING
|
||||
printf("s: %04x\t", s);
|
||||
#endif
|
||||
|
||||
int k = 0;
|
||||
if (!encoded) {
|
||||
/// 1st Scrambling
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if ((unscrambling_mask>>i)&1)
|
||||
psbch->psbch_a_prime ^= ((psbch->psbch_a_interleaved >> i) & 1) << i;
|
||||
else {
|
||||
if (((k + offset) & 0x1f) == 0) {
|
||||
s = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
}
|
||||
|
||||
psbch->psbch_a_prime ^= (((psbch->psbch_a_interleaved >> i) & 1) ^ ((s >> ((k + offset) & 0x1f)) & 1)) << i;
|
||||
k++; /// k increase only when payload bit is not special bit
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/// 2nd Scrambling
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (((i + offset) & 0x1f) == 0) {
|
||||
s = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
}
|
||||
AssertFatal((i >> 5) < NR_POLAR_PSBCH_E_DWORD, "Invalid index into psbch->psbch_e. Index %d > %d\n",
|
||||
(i >> 5), NR_POLAR_PSBCH_E_DWORD);
|
||||
psbch_e[i >> 5] ^= (((s >> ((i + offset) & 0x1f)) & 1) << (i & 0x1f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int nr_generate_sl_psbch(PHY_VARS_NR_UE *ue,
|
||||
c16_t *txdataF,
|
||||
int16_t amp,
|
||||
uint8_t ssb_start_symbol,
|
||||
uint8_t n_hf,
|
||||
int sfn,
|
||||
NR_DL_FRAME_PARMS *frame_parms) {
|
||||
LOG_I(NR_PHY, "PSBCH SL generation started\n");
|
||||
|
||||
/* payload is 56 bits */
|
||||
PSBCH_payload psbch_payload; // NR Side Link Payload for Rel 16
|
||||
psbch_payload.coverageIndicator = 0; // 1 bit
|
||||
psbch_payload.tddConfig = 0xFFF; // 12 bits for TDD configuration
|
||||
psbch_payload.DFN = 0x3FF; // 10 bits for DFN
|
||||
psbch_payload.slotIndex = 0x2A; // 7 bits for Slot Index //frame_parms->p_TDD_UL_DL_ConfigDedicated->slotIndex;
|
||||
psbch_payload.reserved = 0; // 2 bits reserved
|
||||
|
||||
NR_UE_PSBCH m_psbch;
|
||||
ue->psbch_vars[0] = &m_psbch;
|
||||
NR_UE_PSBCH *psbch = ue->psbch_vars[0];
|
||||
memset((void *)psbch, 0, sizeof(NR_UE_PSBCH));
|
||||
psbch->psbch_a = *((uint32_t *)&psbch_payload);
|
||||
psbch->psbch_a_interleaved = psbch->psbch_a; // skip interlevaing for Sidelink
|
||||
|
||||
psbch->psbch_a_prime = 0;
|
||||
|
||||
#ifdef DEBUG_PSBCH_ENCODING
|
||||
printf("PSBCH payload = 0x%08x\n",psbch->psbch_a);
|
||||
#endif
|
||||
|
||||
// Encoder reversal
|
||||
uint64_t a_reversed = 0;
|
||||
for (int i = 0; i < NR_POLAR_PSBCH_PAYLOAD_BITS; i++)
|
||||
a_reversed |= (((uint64_t)psbch->psbch_a_interleaved >> i) & 1) << (31 - i);
|
||||
|
||||
/// CRC, coding and rate matching
|
||||
polar_encoder_fast(&a_reversed, (void*)psbch->psbch_e, 0, 0,
|
||||
NR_POLAR_PSBCH_MESSAGE_TYPE, NR_POLAR_PSBCH_PAYLOAD_BITS, NR_POLAR_PSBCH_AGGREGATION_LEVEL);
|
||||
|
||||
#ifdef DEBUG_PSBCH_ENCODING
|
||||
printf("PSBCH SL generation started\n");
|
||||
printf("Channel coding:\n");
|
||||
for (int i=0; i<NR_POLAR_PSBCH_E_DWORD; i++)
|
||||
printf("sl_psbch_e[%d]: 0x%08x\n", i, psbch->psbch_e[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
/// Scrambling
|
||||
uint16_t M = NR_POLAR_PSBCH_E;
|
||||
uint8_t nushift = 0;
|
||||
nr_psbch_scrambling(psbch, (uint32_t)frame_parms->Nid_SL, nushift, M, NR_POLAR_PSBCH_E, 1, 0);
|
||||
#ifdef DEBUG_PSBCH_ENCODING
|
||||
printf("Scrambling:\n");
|
||||
|
||||
for (int i=0; i<NR_POLAR_PSBCH_E_DWORD; i++) {
|
||||
printf("sl_psbch_e[%d]: 0x%08x\n", i, psbch->psbch_e[i]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
/// QPSK modulation
|
||||
int16_t mod_psbch_e[NR_POLAR_PSBCH_E];
|
||||
for (int i = 0; i < NR_POLAR_PSBCH_E >> 1; i++) {
|
||||
AssertFatal(((i << 1) >> 5) < NR_POLAR_PSBCH_E_DWORD, "Invalid index into psbch->psbch_e. Index %d > %d\n",
|
||||
((i << 1) >> 5), NR_POLAR_PSBCH_E_DWORD);
|
||||
uint8_t idx = ((psbch->psbch_e[(i << 1) >> 5] >> ((i << 1) & 0x1f)) & 3);
|
||||
AssertFatal(((idx << 1) + 1) < 8, "Invalid index into nr_qpsk_mod_table. Index %d > 8\n",
|
||||
(idx << 1) + 1);
|
||||
AssertFatal(((i << 1) + 1) < (sizeof(mod_psbch_e) / sizeof(mod_psbch_e[0])), "Invalid index into mod_psbch_e. Index %d > %lu\n",
|
||||
(i << 1) + 1, sizeof(mod_psbch_e) / sizeof(mod_psbch_e[0]));
|
||||
mod_psbch_e[i << 1] = nr_qpsk_mod_table[idx << 1];
|
||||
mod_psbch_e[(i << 1) + 1] = nr_qpsk_mod_table[(idx << 1) + 1];
|
||||
#ifdef DEBUG_PSBCH
|
||||
printf("i %d idx %d mod_psbch %d %d\n", i, idx, mod_psbch_e[2*i], mod_psbch_e[2*i+1]);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Resource mapping
|
||||
nushift = 0; //config->cell_config.phy_cell_id.value &3;
|
||||
// PSBCH modulated symbols are mapped within the SSB block on symbols 1, 2, 3 excluding the subcarriers used for the PSBCH DMRS
|
||||
///symbol 1 [0:132] -- 99 mod symbols
|
||||
int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier;
|
||||
int l = ssb_start_symbol;
|
||||
int m = 0;
|
||||
|
||||
for (int ssb_sc_idx = 0; ssb_sc_idx < NR_PSBCH_MAX_NB_CARRIERS; ssb_sc_idx++) {
|
||||
if ((ssb_sc_idx & 3) == nushift) { //skip DMRS
|
||||
k++;
|
||||
continue;
|
||||
} else {
|
||||
#ifdef DEBUG_PSBCH
|
||||
printf("m %d ssb_sc_idx %d at k %d of l %d\n", m, ssb_sc_idx, k, l);
|
||||
#endif
|
||||
AssertFatal(((m << 1) + 1) < (sizeof(mod_psbch_e) / sizeof(mod_psbch_e[0])), "Invalid index into mod_psbch_e. Index %d > %lu\n",
|
||||
(m << 1) + 1, sizeof(mod_psbch_e) / sizeof(mod_psbch_e[0]));
|
||||
int idx = (l * frame_parms->ofdm_symbol_size + k);
|
||||
AssertFatal((idx + 1) < frame_parms->samples_per_frame_wCP, "txdataF index %d invalid!\n", idx + 1);
|
||||
txdataF[idx].r = (amp * mod_psbch_e[m << 1]) >> 15;
|
||||
txdataF[idx].i = (amp * mod_psbch_e[(m << 1) + 1]) >> 15;
|
||||
k++;
|
||||
m++;
|
||||
}
|
||||
|
||||
if (k >= frame_parms->ofdm_symbol_size)
|
||||
k-=frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
|
||||
int N_SSSB_Symb = 14;
|
||||
///symbol 5 to N_SSSB_Symb [0:132] -- 99 mod symbols
|
||||
l = ssb_start_symbol + 5;
|
||||
AssertFatal(m == 99, "m does not equal 99");
|
||||
m = 99;
|
||||
while (l < N_SSSB_Symb - 1)
|
||||
{
|
||||
k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier;
|
||||
|
||||
for (int ssb_sc_idx = 0; ssb_sc_idx < NR_PSBCH_MAX_NB_CARRIERS; ssb_sc_idx++) {
|
||||
if ((ssb_sc_idx & 3) == nushift) { //skip DMRS
|
||||
k++;
|
||||
continue;
|
||||
} else {
|
||||
#ifdef DEBUG_PSBCH
|
||||
printf("m %d ssb_sc_idx %d at k %d of l %d\n", m, ssb_sc_idx, k, l);
|
||||
#endif
|
||||
|
||||
AssertFatal((m << 1) + 1 < (sizeof(mod_psbch_e) / sizeof(mod_psbch_e[0])),
|
||||
"Indexing outside of mod_psbch_e bounds. %d > %lu",
|
||||
(m << 1) + 1 , (sizeof(mod_psbch_e) / sizeof(mod_psbch_e[0])));
|
||||
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].r = (amp * mod_psbch_e[m << 1]) >> 15;
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].i = (amp * mod_psbch_e[(m << 1) + 1]) >> 15;
|
||||
k++;
|
||||
m++;
|
||||
}
|
||||
|
||||
if (k >= frame_parms->ofdm_symbol_size)
|
||||
k-=frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
l++;
|
||||
}
|
||||
#ifdef DEBUG_PSBCH
|
||||
char buffer[frame_parms->ofdm_symbol_size];
|
||||
for (int i = 0; i < 13; i++) {
|
||||
if (i >= 1 && i <= 4)
|
||||
continue;
|
||||
bzero(buffer, sizeof(buffer));
|
||||
LOG_I(NR_PHY, "PSBCH %d = %s\n", i, hexdump(&txdataF[frame_parms->ofdm_symbol_size*i],
|
||||
frame_parms->ofdm_symbol_size, buffer, sizeof(buffer)));
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -64,69 +64,33 @@
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
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, int pss_seq_offset)
|
||||
{
|
||||
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);
|
||||
int16_t d_pss[LENGTH_PSS_NR];
|
||||
const int x_initial[INITIAL_PSS_NR] = {0, 1, 1, 0, 1, 1, 1};
|
||||
int16_t x[LENGTH_PSS_NR];
|
||||
int16_t *primary_synchro_time = primary_synchro_time_nr[N_ID_2];
|
||||
unsigned int length = fp->ofdm_symbol_size;
|
||||
unsigned int size = length * IQ_SIZE; /* i & q */
|
||||
int16_t *primary_synchro = primary_synchro_nr[N_ID_2]; /* pss in complex with alternatively i then q */
|
||||
int16_t *primary_synchro2 = primary_synchro_nr2[N_ID_2]; /* pss in complex with alternatively i then q */
|
||||
|
||||
|
||||
#define INITIAL_PSS_NR (7)
|
||||
const int x_initial[INITIAL_PSS_NR] = {0, 1, 1 , 0, 1, 1, 1};
|
||||
|
||||
assert(N_ID_2 < NUMBER_PSS_SEQUENCE);
|
||||
assert(size <= SYNCF_TMP_SIZE);
|
||||
assert(size <= SYNC_TMP_SIZE);
|
||||
|
||||
bzero(synchroF_tmp, size);
|
||||
bzero(synchro_tmp, size);
|
||||
|
||||
for (int i=0; i < INITIAL_PSS_NR; i++) {
|
||||
for (int i = 0; i < INITIAL_PSS_NR; i++)
|
||||
x[i] = x_initial[i];
|
||||
|
||||
for (int i = 0; i < (LENGTH_PSS_NR - INITIAL_PSS_NR); i++)
|
||||
x[i + INITIAL_PSS_NR] = (x[i + 4] + x[i]) % (2);
|
||||
|
||||
int16_t d_pss[LENGTH_PSS_NR];
|
||||
for (int n = 0; n < LENGTH_PSS_NR; n++) {
|
||||
int m = (n + 43 * N_ID_2) % (LENGTH_PSS_NR);
|
||||
d_pss[n] = 1 - 2 * x[m];
|
||||
}
|
||||
|
||||
for (int i=0; i < (LENGTH_PSS_NR - INITIAL_PSS_NR); i++) {
|
||||
x[i+INITIAL_PSS_NR] = (x[i + 4] + x[i])%(2);
|
||||
c16_t *primary_synchro = primary_synchro_nr[N_ID_2];
|
||||
c16_t *primary_synchro2 = primary_synchro_nr2[N_ID_2];
|
||||
for (int i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
primary_synchro[i].r = (d_pss[i] * SHRT_MAX) >> SCALING_PSS_NR;
|
||||
primary_synchro[i].i = 0;
|
||||
primary_synchro2[i].r = d_pss[i];
|
||||
primary_synchro2[i].i = d_pss[i];
|
||||
}
|
||||
|
||||
for (int n=0; n < LENGTH_PSS_NR; n++) {
|
||||
int m = (n + 43*N_ID_2)%(LENGTH_PSS_NR);
|
||||
d_pss[n] = 1 - 2*x[m];
|
||||
}
|
||||
|
||||
/* PSS is directly mapped to subcarrier without modulation 38.211 */
|
||||
for (int i=0; i < LENGTH_PSS_NR; i++) {
|
||||
#if 1
|
||||
primary_synchro[2*i] = (d_pss[i] * SHRT_MAX)>>SCALING_PSS_NR; /* Maximum value for type short int ie int16_t */
|
||||
primary_synchro[2*i+1] = 0;
|
||||
primary_synchro2[i] = d_pss[i];
|
||||
#else
|
||||
primary_synchro[2*i] = d_pss[i] * AMP;
|
||||
primary_synchro[2*i+1] = 0;
|
||||
primary_synchro2[i] = d_pss[i];
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DBG_PSS_NR
|
||||
|
||||
if (N_ID_2 == 0) {
|
||||
char output_file[255];
|
||||
char sequence_name[255];
|
||||
sprintf(output_file, "pss_seq_%d_%u.m", N_ID_2, length);
|
||||
sprintf(sequence_name, "pss_seq_%d_%u", N_ID_2, length);
|
||||
printf("file %s sequence %s\n", output_file, sequence_name);
|
||||
|
||||
LOG_M(output_file, sequence_name, primary_synchro, LENGTH_PSS_NR, 1, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* call of IDFT should be done with ordered input as below
|
||||
*
|
||||
* n input samples
|
||||
@@ -149,99 +113,27 @@ 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 k = fp->first_carrier_offset + fp->ssb_start_subcarrier + 56; //and
|
||||
unsigned int subcarrier_start = get_softmodem_params()->sl_mode == 0 ? 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;
|
||||
|
||||
|
||||
for (int i=0; i < LENGTH_PSS_NR; i++) {
|
||||
synchroF_tmp[2*k] = primary_synchro[2*i];
|
||||
synchroF_tmp[2*k+1] = primary_synchro[2*i+1];
|
||||
|
||||
LOG_I(NR_PHY,"generate_pss_nr: subcarrier_start %d, k %d\n",subcarrier_start,k);
|
||||
c16_t in[sizeof(int16_t) * fp->ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
memset(in, 0, sizeof(in));
|
||||
for (int i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
in[k]= primary_synchro[i];
|
||||
k++;
|
||||
|
||||
if (k == length) k=0;
|
||||
|
||||
if (k == fp->ofdm_symbol_size) k = 0;
|
||||
}
|
||||
|
||||
/* IFFT will give temporal signal of Pss */
|
||||
|
||||
|
||||
|
||||
idft((int16_t)get_idft(length),
|
||||
synchroF_tmp, /* complex input */
|
||||
synchro_tmp, /* complex output */
|
||||
1); /* scaling factor */
|
||||
|
||||
/* then get final pss in time */
|
||||
for (unsigned int i=0; i<length; i++) {
|
||||
((int32_t *)primary_synchro_time)[i] = ((int32_t *)synchro_tmp)[i];
|
||||
c16_t out[sizeof(int16_t) * fp->ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
memset(out, 0, sizeof(out));
|
||||
memset(primary_synchro_time_nr[N_ID_2], 0, sizeof(int16_t) * fp->ofdm_symbol_size);
|
||||
idft((int16_t)get_idft(fp->ofdm_symbol_size), (int16_t *)in, (int16_t *)out, 1);
|
||||
for (unsigned int i = 0; i < fp->ofdm_symbol_size; i++) {
|
||||
primary_synchro_time_nr[N_ID_2][i] = out[i];
|
||||
}
|
||||
|
||||
#ifdef DBG_PSS_NR
|
||||
|
||||
if (N_ID_2 == 0) {
|
||||
char output_file[255];
|
||||
char sequence_name[255];
|
||||
sprintf(output_file, "%s%d_%u%s","pss_seq_t_", N_ID_2, length, ".m");
|
||||
sprintf(sequence_name, "%s%d_%u","pss_seq_t_", N_ID_2, length);
|
||||
|
||||
printf("file %s sequence %s\n", output_file, sequence_name);
|
||||
|
||||
LOG_M(output_file, sequence_name, primary_synchro_time, length, 1, 1);
|
||||
sprintf(output_file, "%s%d_%u%s","pss_seq_f_", N_ID_2, length, ".m");
|
||||
sprintf(sequence_name, "%s%d_%u","pss_seq_f_", N_ID_2, length);
|
||||
LOG_M(output_file, sequence_name, synchroF_tmp, length, 1, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
/* it allows checking that process of idft on a signal and then dft gives same signal with limited errors */
|
||||
|
||||
if ((N_ID_2 == 0) && (length == 256)) {
|
||||
|
||||
LOG_M("pss_f00.m","pss_f00",synchro_tmp,length,1,1);
|
||||
|
||||
|
||||
bzero(synchroF_tmp, size);
|
||||
|
||||
|
||||
|
||||
/* get pss in the time domain by applying an inverse FFT */
|
||||
dft((int16_t)get_dft(length),
|
||||
synchro_tmp, /* complex input */
|
||||
synchroF_tmp, /* complex output */
|
||||
1); /* scaling factor */
|
||||
|
||||
if ((N_ID_2 == 0) && (length == 256)) {
|
||||
LOG_M("pss_f_0.m","pss_f_0",synchroF_tmp,length,1,1);
|
||||
}
|
||||
|
||||
/* check Pss */
|
||||
k = length - (LENGTH_PSS_NR/2);
|
||||
|
||||
#define LIMIT_ERROR_FFT (10)
|
||||
|
||||
for (int i=0; i < LENGTH_PSS_NR; i++) {
|
||||
if (abs(synchroF_tmp[2*k] - primary_synchro[2*i]) > LIMIT_ERROR_FFT) {
|
||||
printf("Pss Error[%d] Compute %d Reference %d \n", k, synchroF_tmp[2*k], primary_synchro[2*i]);
|
||||
}
|
||||
|
||||
if (abs(synchroF_tmp[2*k+1] - primary_synchro[2*i+1]) > LIMIT_ERROR_FFT) {
|
||||
printf("Pss Error[%d] Compute %d Reference %d\n", (2*k+1), synchroF_tmp[2*k+1], primary_synchro[2*i+1]);
|
||||
}
|
||||
|
||||
k++;
|
||||
|
||||
if (k >= length) {
|
||||
k-=length;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@@ -259,60 +151,47 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp,int N_ID_2)
|
||||
|
||||
void init_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue)
|
||||
{
|
||||
int ofdm_symbol_size = frame_parms_ue->ofdm_symbol_size;
|
||||
int sizePss = LENGTH_PSS_NR * IQ_SIZE; /* complex value i & q signed 16 bits */
|
||||
int size = ofdm_symbol_size * IQ_SIZE; /* i and q samples signed 16 bits */
|
||||
int16_t *p = NULL;
|
||||
|
||||
AssertFatal(ofdm_symbol_size > 127, "illegal ofdm_symbol_size %d\n",ofdm_symbol_size);
|
||||
for (int i = 0; i < NUMBER_PSS_SEQUENCE; i++) {
|
||||
|
||||
p = malloc16(sizePss); /* pss in complex with alternatively i then q */
|
||||
LOG_I(NR_PHY,"Calling init_context_pss_nr\n");
|
||||
AssertFatal(frame_parms_ue->ofdm_symbol_size > 127, "illegal frame_parms_ue->ofdm_symbol_size %d\n",
|
||||
frame_parms_ue->ofdm_symbol_size);
|
||||
c16_t *p = NULL;
|
||||
int pss_sequence = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL;
|
||||
c16_t txdataF[3*4096];
|
||||
for (int i = 0; i < pss_sequence; i++) {
|
||||
LOG_I(NR_PHY,"Initializing PSS %d\n",i);
|
||||
p = malloc(LENGTH_PSS_NR * sizeof(c16_t));
|
||||
if (p != NULL) {
|
||||
primary_synchro_nr[i] = p;
|
||||
bzero( primary_synchro_nr[i], sizePss);
|
||||
}
|
||||
else {
|
||||
bzero(primary_synchro_nr[i], LENGTH_PSS_NR * sizeof(c16_t));
|
||||
} else {
|
||||
LOG_E(PHY,"Fatal memory allocation problem \n");
|
||||
assert(0);
|
||||
}
|
||||
p = malloc(LENGTH_PSS_NR*2);
|
||||
p = malloc(LENGTH_PSS_NR * sizeof(c16_t));
|
||||
if (p != NULL) {
|
||||
primary_synchro_nr2[i] = p;
|
||||
bzero( primary_synchro_nr2[i],LENGTH_PSS_NR*2);
|
||||
bzero(primary_synchro_nr2[i], LENGTH_PSS_NR * sizeof(c16_t));
|
||||
} else {
|
||||
LOG_E(PHY,"Fatal memory allocation problem \n");
|
||||
assert(0);
|
||||
}
|
||||
p = malloc16(size);
|
||||
p = malloc(sizeof(c16_t) * frame_parms_ue->ofdm_symbol_size);
|
||||
if (p != NULL) {
|
||||
primary_synchro_time_nr[i] = p;
|
||||
bzero( primary_synchro_time_nr[i], size);
|
||||
}
|
||||
else {
|
||||
bzero(primary_synchro_time_nr[i], sizeof(c16_t) * frame_parms_ue->ofdm_symbol_size);
|
||||
} else {
|
||||
LOG_E(PHY,"Fatal memory allocation problem \n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
generate_pss_nr(frame_parms_ue,i);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* NAME : free_context_pss_nr
|
||||
*
|
||||
* PARAMETERS : none
|
||||
*
|
||||
* RETURN : none
|
||||
*
|
||||
* DESCRIPTION : free context related to pss
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
void free_context_pss_nr(void)
|
||||
{
|
||||
for (int i = 0; i < NUMBER_PSS_SEQUENCE; i++) {
|
||||
free_and_zero(primary_synchro_nr[i]);
|
||||
free_and_zero(primary_synchro_nr2[i]);
|
||||
free_and_zero(primary_synchro_time_nr[i]);
|
||||
if (get_softmodem_params()->sl_mode==0 || get_softmodem_params()->sync_ref) generate_pss_nr(frame_parms_ue, i, pss_sequence);
|
||||
else {
|
||||
int tmp=frame_parms_ue->Nid_SL;
|
||||
frame_parms_ue->Nid_SL = 336*i;
|
||||
nr_sl_generate_pss(txdataF,AMP,0,frame_parms_ue);
|
||||
frame_parms_ue->Nid_SL = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,25 +209,7 @@ void free_context_pss_nr(void)
|
||||
|
||||
void init_context_synchro_nr(NR_DL_FRAME_PARMS *frame_parms_ue)
|
||||
{
|
||||
#ifndef STATIC_SYNC_BUFFER
|
||||
|
||||
/* initialise global buffers for synchronisation */
|
||||
synchroF_tmp = malloc16(SYNCF_TMP_SIZE);
|
||||
if (synchroF_tmp == NULL) {
|
||||
LOG_E(PHY,"Fatal memory allocation problem \n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
synchro_tmp = malloc16(SYNC_TMP_SIZE);
|
||||
if (synchro_tmp == NULL) {
|
||||
LOG_E(PHY,"Fatal memory allocation problem \n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
init_context_pss_nr(frame_parms_ue);
|
||||
|
||||
init_context_sss_nr(AMP);
|
||||
}
|
||||
|
||||
@@ -366,29 +227,11 @@ void init_context_synchro_nr(NR_DL_FRAME_PARMS *frame_parms_ue)
|
||||
|
||||
void free_context_synchro_nr(void)
|
||||
{
|
||||
#ifndef STATIC_SYNC_BUFFER
|
||||
|
||||
if (synchroF_tmp != NULL) {
|
||||
free(synchroF_tmp);
|
||||
synchroF_tmp = NULL;
|
||||
for (int i = 0; i < NUMBER_PSS_SEQUENCE; i++) {
|
||||
free_and_zero(primary_synchro_nr[i]);
|
||||
free_and_zero(primary_synchro_nr2[i]);
|
||||
free_and_zero(primary_synchro_time_nr[i]);
|
||||
}
|
||||
else {
|
||||
LOG_E(PHY,"Fatal memory deallocation problem \n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (synchro_tmp != NULL) {
|
||||
free(synchro_tmp);
|
||||
synchro_tmp = NULL;
|
||||
}
|
||||
else {
|
||||
LOG_E(PHY,"Fatal memory deallocation problem \n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
free_context_pss_nr();
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@@ -408,42 +251,10 @@ void set_frame_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue, int rate_change
|
||||
/* set new value according to rate_change */
|
||||
frame_parms_ue->ofdm_symbol_size = (frame_parms_ue->ofdm_symbol_size / rate_change);
|
||||
frame_parms_ue->samples_per_subframe = (frame_parms_ue->samples_per_subframe / 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);
|
||||
|
||||
#ifdef SYNCHRO_DECIMAT
|
||||
set_pss_nr(frame_parms_ue->ofdm_symbol_size);
|
||||
#endif
|
||||
init_context_pss_nr(frame_parms_ue);
|
||||
init_context_sss_nr(AMP);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* NAME : restore_frame_context_pss_nr
|
||||
*
|
||||
* PARAMETERS : configuration for UE and eNB with new FFT size
|
||||
*
|
||||
* RETURN : 0 if OK else error
|
||||
*
|
||||
* DESCRIPTION : initialisation of UE and eNode contexts
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
void restore_frame_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue, int rate_change)
|
||||
{
|
||||
frame_parms_ue->ofdm_symbol_size = frame_parms_ue->ofdm_symbol_size * rate_change;
|
||||
frame_parms_ue->samples_per_subframe = frame_parms_ue->samples_per_subframe * 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);
|
||||
#ifdef SYNCHRO_DECIMAT
|
||||
set_pss_nr(frame_parms_ue->ofdm_symbol_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
*
|
||||
@@ -555,9 +366,7 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change)
|
||||
#endif
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PSS_SEARCH_TIME_NR, VCD_FUNCTION_IN);
|
||||
|
||||
synchro_position = pss_search_time_nr(rxdata, PHY_vars_UE, fo_flag, is);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PSS_SEARCH_TIME_NR, VCD_FUNCTION_OUT);
|
||||
|
||||
#if TEST_SYNCHRO_TIMING_PSS
|
||||
@@ -650,133 +459,109 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change)
|
||||
int pss_search_time_nr(c16_t **rxdata, PHY_VARS_NR_UE *ue, int fo_flag, int is)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
int *eNB_id = (int *)&ue->common_vars.eNb_id;
|
||||
int *f_off = (int *)&ue->common_vars.freq_offset;
|
||||
unsigned int n, ar, peak_position, pss_source;
|
||||
int64_t peak_value;
|
||||
int64_t avg[NUMBER_PSS_SEQUENCE] = {0};
|
||||
double ffo_est = 0;
|
||||
unsigned int length = is == 0 ? frame_parms->samples_per_frame + (2 * frame_parms->ofdm_symbol_size) :
|
||||
frame_parms->samples_per_frame;
|
||||
AssertFatal(length > 0, "illegal length %d\n", length);
|
||||
|
||||
// performing the correlation on a frame length plus one symbol for the first of the two frame
|
||||
// to take into account the possibility of PSS in between the two frames
|
||||
unsigned int length;
|
||||
if (is==0)
|
||||
length = frame_parms->samples_per_frame + (2*frame_parms->ofdm_symbol_size);
|
||||
else
|
||||
length = frame_parms->samples_per_frame;
|
||||
|
||||
|
||||
AssertFatal(length>0,"illegal length %d\n",length);
|
||||
peak_value = 0;
|
||||
peak_position = 0;
|
||||
pss_source = 0;
|
||||
|
||||
int maxval=0;
|
||||
for (int i=0;i<2*(frame_parms->ofdm_symbol_size);i++) {
|
||||
maxval = max(maxval,primary_synchro_time_nr[0][i]);
|
||||
maxval = max(maxval,-primary_synchro_time_nr[0][i]);
|
||||
maxval = max(maxval,primary_synchro_time_nr[1][i]);
|
||||
maxval = max(maxval,-primary_synchro_time_nr[1][i]);
|
||||
maxval = max(maxval,primary_synchro_time_nr[2][i]);
|
||||
maxval = max(maxval,-primary_synchro_time_nr[2][i]);
|
||||
int maxval = 0;
|
||||
for (int i = 0; i < frame_parms->ofdm_symbol_size; i++) {
|
||||
maxval = max(maxval, primary_synchro_time_nr[0][i].r);
|
||||
maxval = max(maxval, primary_synchro_time_nr[0][i].i);
|
||||
maxval = max(maxval, -primary_synchro_time_nr[0][i].r);
|
||||
maxval = max(maxval, -primary_synchro_time_nr[0][i].i);
|
||||
maxval = max(maxval, primary_synchro_time_nr[1][i].r);
|
||||
maxval = max(maxval, primary_synchro_time_nr[1][i].i);
|
||||
maxval = max(maxval, -primary_synchro_time_nr[1][i].r);
|
||||
maxval = max(maxval, -primary_synchro_time_nr[1][i].i);
|
||||
if (get_softmodem_params()->sl_mode == 0) {
|
||||
maxval = max(maxval, primary_synchro_time_nr[2][i].r);
|
||||
maxval = max(maxval, primary_synchro_time_nr[2][i].i);
|
||||
maxval = max(maxval, -primary_synchro_time_nr[2][i].r);
|
||||
maxval = max(maxval, -primary_synchro_time_nr[2][i].i);
|
||||
}
|
||||
}
|
||||
int shift = log2_approx(maxval);//*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples)*2);
|
||||
|
||||
int avg_size = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL;
|
||||
int64_t avg[avg_size];
|
||||
bzero(avg, avg_size);
|
||||
|
||||
int shift = log2_approx(maxval);
|
||||
int64_t peak_value = 0;
|
||||
unsigned int peak_position = 0;
|
||||
unsigned int pss_source = 0;
|
||||
/* Search pss in the received buffer each 4 samples which ensures a memory alignment on 128 bits (32 bits x 4 ) */
|
||||
/* This is required by SIMD (single instruction Multiple Data) Extensions of Intel processors. */
|
||||
/* 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 = NUMBER_PSS_SEQUENCE;
|
||||
uint16_t pss_index_end = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL;
|
||||
if (ue->target_Nid_cell != -1) {
|
||||
pss_index_start = GET_NID2(ue->target_Nid_cell);
|
||||
pss_index_end = pss_index_start + 1;
|
||||
}
|
||||
|
||||
unsigned int step = get_softmodem_params()->sl_mode == 0 ? 8 : 4;
|
||||
for (int pss_index = pss_index_start; pss_index < pss_index_end; pss_index++) {
|
||||
for (n = 0; n < length; n += 8) { //
|
||||
|
||||
int64_t pss_corr_ue=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<frame_parms->nb_antennas_rx; ar++) {
|
||||
|
||||
for (unsigned int n = 0; n < length; n += step) {
|
||||
int64_t pss_corr_ue = 0;
|
||||
for (unsigned int ar = 0; ar < frame_parms->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 *)primary_synchro_time_nr[pss_index], &(rxdata[ar][n + is * frame_parms->samples_per_frame]), frame_parms->ofdm_symbol_size, shift);
|
||||
const c32_t result = dot_product(primary_synchro_time_nr[pss_index],
|
||||
&(rxdata[ar][n + is * frame_parms->samples_per_frame]),
|
||||
frame_parms->ofdm_symbol_size,
|
||||
shift);
|
||||
const c64_t r64 = {.r = result.r, .i = result.i};
|
||||
pss_corr_ue += squaredMod(r64);
|
||||
//((short*)pss_corr_ue[pss_index])[2*n] += ((short*) &result)[0]; /* real part */
|
||||
//((short*)pss_corr_ue[pss_index])[2*n+1] += ((short*) &result)[1]; /* imaginary part */
|
||||
//((short*)&synchro_out)[0] += ((int*) &result)[0]; /* real part */
|
||||
//((short*)&synchro_out)[1] += ((int*) &result)[1]; /* imaginary part */
|
||||
|
||||
if (get_softmodem_params()->sl_mode > 0) {
|
||||
//non-coherentely combine repeition of PSS
|
||||
const c32_t result = dot_product(primary_synchro_time_nr[pss_index],
|
||||
&(rxdata[ar][n + is * frame_parms->samples_per_frame + frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples]),
|
||||
frame_parms->ofdm_symbol_size,
|
||||
shift);
|
||||
const c64_t r64 = {.r = result.r, .i = result.i};
|
||||
pss_corr_ue += squaredMod(r64);
|
||||
}
|
||||
}
|
||||
|
||||
/* calculate the absolute value of sync_corr[n] */
|
||||
avg[pss_index]+=pss_corr_ue;
|
||||
if (pss_corr_ue > peak_value) {
|
||||
peak_value = pss_corr_ue;
|
||||
peak_position = n;
|
||||
pss_source = pss_index;
|
||||
|
||||
#ifdef DEBUG_PSS_NR
|
||||
printf("pss_index %d: n %6u peak_value %15llu\n", pss_index, n, (unsigned long long)pss_corr_ue[n]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fo_flag){
|
||||
|
||||
double ffo_est = 0;
|
||||
if (fo_flag) {
|
||||
// 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 *)primary_synchro_time_nr[pss_source], &(rxdata[0][peak_position + is * frame_parms->samples_per_frame]), frame_parms->ofdm_symbol_size >> 1, shift);
|
||||
c32_t r1 = dot_product(primary_synchro_time_nr[pss_source],
|
||||
&(rxdata[0][peak_position + is * frame_parms->samples_per_frame]),
|
||||
frame_parms->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 *)primary_synchro_time_nr[pss_source] + (frame_parms->ofdm_symbol_size >> 1),
|
||||
c32_t r2 = dot_product(primary_synchro_time_nr[pss_source] + (frame_parms->ofdm_symbol_size >> 1),
|
||||
&(rxdata[0][peak_position + is * frame_parms->samples_per_frame]) + (frame_parms->ofdm_symbol_size >> 1),
|
||||
frame_parms->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 DBG_PSS_NR
|
||||
printf("ffo %lf\n",ffo_est);
|
||||
#endif
|
||||
}
|
||||
|
||||
// computing absolute value of frequency offset
|
||||
*f_off = ffo_est*frame_parms->subcarrier_spacing;
|
||||
ue->common_vars.freq_offset = ffo_est * frame_parms->subcarrier_spacing;
|
||||
int *id = get_softmodem_params()->sl_mode == 0 ? (int *)&ue->common_vars.eNb_id : (int *)&ue->common_vars.N2_id;
|
||||
*id = pss_source;
|
||||
|
||||
for (int pss_index = pss_index_start; pss_index < pss_index_end; pss_index++)
|
||||
avg[pss_index] /= (length / 4);
|
||||
|
||||
*eNB_id = pss_source;
|
||||
LOG_I(NR_PHY, "[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %llu (%d dB) avg %d dB, ffo %lf\n",
|
||||
pss_source, peak_position, (unsigned long long)peak_value, dB_fixed64(peak_value), dB_fixed64(avg[pss_source]), ffo_est);
|
||||
|
||||
LOG_I(PHY,"[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %llu (%d dB) avg %d dB, ffo %lf\n", pss_source, peak_position, (unsigned long long)peak_value, dB_fixed64(peak_value),dB_fixed64(avg[pss_source]),ffo_est);
|
||||
|
||||
if (peak_value < 5*avg[pss_source])
|
||||
if (peak_value < 5 * avg[pss_source])
|
||||
return(-1);
|
||||
|
||||
|
||||
#ifdef DBG_PSS_NR
|
||||
|
||||
static int debug_cnt = 0;
|
||||
|
||||
if (debug_cnt == 0) {
|
||||
if (is)
|
||||
LOG_M("rxdata1.m","rxd0",rxdata[frame_parms->samples_per_frame],length,1,1);
|
||||
else
|
||||
LOG_M("rxdata0.m","rxd0",rxdata[0],length,1,1);
|
||||
} else {
|
||||
debug_cnt++;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return peak_position;
|
||||
return(peak_position);
|
||||
}
|
||||
|
||||
|
||||
127
openair1/PHY/NR_UE_TRANSPORT/pss_nr_sl.c
Normal file
127
openair1/PHY/NR_UE_TRANSPORT/pss_nr_sl.c
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <nr-uesoftmodem.h>
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/phy_extern.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "PHY/NR_REFSIG/ss_pbch_nr.h"
|
||||
#include "openair1/PHY/NR_REFSIG/pss_nr.h"
|
||||
|
||||
int nr_sl_generate_pss(c16_t *txdataF,
|
||||
int16_t amp,
|
||||
uint8_t ssb_start_symbol,
|
||||
NR_DL_FRAME_PARMS *frame_parms)
|
||||
{
|
||||
const int x_initial[INITIAL_PSS_NR] = {0, 1, 1, 0, 1, 1, 1};
|
||||
int16_t x[LENGTH_PSS_NR];
|
||||
for (int i = 0; i < INITIAL_PSS_NR; i++)
|
||||
x[i] = x_initial[i];
|
||||
|
||||
for (int i = 0; i < (LENGTH_PSS_NR - INITIAL_PSS_NR); i++)
|
||||
x[i + INITIAL_PSS_NR] = (x[i + 4] + x[i]) % (2);
|
||||
|
||||
#ifdef NR_PSS_DEBUG
|
||||
write_output("d_pss.m", "d_pss", (void*)d_pss, NR_PSS_LENGTH, 1, 0);
|
||||
printf("PSS: ofdm_symbol_size %d, first_carrier_offset %d\n",frame_parms->ofdm_symbol_size,frame_parms->first_carrier_offset);
|
||||
#endif
|
||||
|
||||
/// Resource mapping
|
||||
uint8_t Nid2 = frame_parms->Nid_SL / 336;
|
||||
int16_t d_pss[LENGTH_PSS_NR];
|
||||
c16_t *primary_synchro = primary_synchro_nr[Nid2];
|
||||
c16_t *primary_synchro2 = primary_synchro_nr2[Nid2];
|
||||
|
||||
// PSS occupies a predefined position (subcarriers 2-128, symbol 0) within the SSB block starting from
|
||||
int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + PSS_SSS_SUB_CARRIER_START_SL;
|
||||
if (k >= frame_parms->ofdm_symbol_size) k -= frame_parms->ofdm_symbol_size;
|
||||
|
||||
int l = ssb_start_symbol + 1;
|
||||
for (int i = 0; i < NR_PSS_LENGTH; i++) {
|
||||
int m = (i + 22 + 43 * Nid2) % (NR_PSS_LENGTH);
|
||||
d_pss[i] = (1 - 2 * x[m]) * 23170;
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].r = (((int16_t)amp) * d_pss[i]) >> 15;
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].i = 0;
|
||||
primary_synchro[i].r = (d_pss[i] * SHRT_MAX) >> SCALING_PSS_NR;
|
||||
primary_synchro[i].i = 0;
|
||||
primary_synchro2[i].r = d_pss[i];
|
||||
primary_synchro2[i].i = d_pss[i];
|
||||
k++;
|
||||
|
||||
if (k >= frame_parms->ofdm_symbol_size)
|
||||
k-=frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
|
||||
// PSS occupies a predefined position (subcarriers 2-128, symbol 0) within the SSB block starting from
|
||||
k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + PSS_SSS_SUB_CARRIER_START_SL;
|
||||
if (k >= frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size;
|
||||
|
||||
l = ssb_start_symbol + 2;
|
||||
|
||||
for (int i = 0; i < NR_PSS_LENGTH; i++) {
|
||||
int m = (i + 22 + 43 * Nid2) % (NR_PSS_LENGTH);
|
||||
d_pss[i] = (1 - 2 * x[m]) * 23170;
|
||||
// printf("pss: writing position k %d / %d\n",k,frame_parms->ofdm_symbol_size);
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].r = (((int16_t)amp) * d_pss[i]) >> 15;
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].i = 0;
|
||||
k++;
|
||||
|
||||
if (k >= frame_parms->ofdm_symbol_size)
|
||||
k-=frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
|
||||
#ifdef NR_PSS_DEBUG
|
||||
LOG_M("pss_0.m", "pss_0",
|
||||
(void*)&txdataF[0][ssb_start_symbol*frame_parms->ofdm_symbol_size],
|
||||
frame_parms->ofdm_symbol_size, 1, 1);
|
||||
char buffer[frame_parms->ofdm_symbol_size];
|
||||
for (int i = 1; i < 3; i++) {
|
||||
bzero(buffer, sizeof(buffer));
|
||||
LOG_I(NR_PHY, "PSS %d = %s\n", i, hexdump(&txdataF[frame_parms->ofdm_symbol_size*i],
|
||||
frame_parms->ofdm_symbol_size, buffer, sizeof(buffer)));
|
||||
}
|
||||
#endif
|
||||
LOG_I(NR_PHY,"nr_sl_generate_pss : ssb_start_subcarrier %d, k %d\n",frame_parms->ssb_start_subcarrier,k);
|
||||
|
||||
k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + PSS_SSS_SUB_CARRIER_START_SL;
|
||||
if (k >= frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size;
|
||||
c16_t in[sizeof(int16_t) * frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
memset(in, 0, sizeof(in));
|
||||
for (int i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
in[k]= primary_synchro[i];
|
||||
k++;
|
||||
if (k == frame_parms->ofdm_symbol_size) k = 0;
|
||||
}
|
||||
|
||||
c16_t out[sizeof(int16_t) * frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
memset(out, 0, sizeof(out));
|
||||
memset(primary_synchro_time_nr[Nid2], 0, sizeof(int16_t) * frame_parms->ofdm_symbol_size);
|
||||
idft((int16_t)get_idft(frame_parms->ofdm_symbol_size), (int16_t *)in, (int16_t *)out, 1);
|
||||
for (unsigned int i = 0; i < frame_parms->ofdm_symbol_size; i++) {
|
||||
primary_synchro_time_nr[Nid2][i] = out[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/MODULATION/modulation_UE.h"
|
||||
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "PHY/NR_REFSIG/ss_pbch_nr.h"
|
||||
|
||||
#define DEFINE_VARIABLES_SSS_NR_H
|
||||
@@ -67,50 +67,32 @@ void init_context_sss_nr(int amp)
|
||||
{
|
||||
int16_t x0[LENGTH_SSS_NR];
|
||||
int16_t x1[LENGTH_SSS_NR];
|
||||
int16_t dss_current;
|
||||
int m0, m1;
|
||||
|
||||
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 };
|
||||
|
||||
for (int i=0; i < INITIAL_SSS_NR; i++) {
|
||||
for (int i = 0; i < INITIAL_SSS_NR; i++) {
|
||||
x0[i] = x0_initial[i];
|
||||
x1[i] = x1_initial[i];
|
||||
}
|
||||
|
||||
for (int i=0; i < (LENGTH_SSS_NR - INITIAL_SSS_NR); i++) {
|
||||
x0[i+7] = (x0[i + 4] + x0[i])%(2);
|
||||
x1[i+7] = (x1[i + 1] + x1[i])%(2);
|
||||
for (int i = 0; i < (LENGTH_SSS_NR - INITIAL_SSS_NR); i++) {
|
||||
x0[i + 7] = (x0[i + 4] + x0[i]) % (2);
|
||||
x1[i + 7] = (x1[i + 1] + x1[i]) % (2);
|
||||
}
|
||||
|
||||
for (int N_ID_2 = 0; N_ID_2 < N_ID_2_NUMBER; N_ID_2++) {
|
||||
|
||||
int nid_2_num = get_softmodem_params()->sl_mode == 0 ? N_ID_2_NUMBER : N_ID_2_NUMBER_SL;
|
||||
int dss_current;
|
||||
int m0, m1;
|
||||
for (int N_ID_2 = 0; N_ID_2 < nid_2_num; N_ID_2++) {
|
||||
for (int N_ID_1 = 0; N_ID_1 < N_ID_1_NUMBER; N_ID_1++) {
|
||||
|
||||
m0 = 15*(N_ID_1/112) + (5*N_ID_2);
|
||||
m1 = N_ID_1%112;
|
||||
|
||||
m0 = 15 * (N_ID_1 / 112) + (5 * N_ID_2);
|
||||
m1 = N_ID_1 % 112;
|
||||
for (int n = 0; n < LENGTH_SSS_NR; n++) {
|
||||
|
||||
dss_current = (1 - 2*x0[(n + m0)%(LENGTH_SSS_NR)])*(1 - 2*x1[(n + m1)%(LENGTH_SSS_NR)]);
|
||||
|
||||
dss_current = (1 - 2 * x0 [(n + m0) % (LENGTH_SSS_NR)]) * (1 - 2 * x1[(n + m1) % (LENGTH_SSS_NR)]);
|
||||
/* Modulation of SSS is a BPSK TS 36.211 chapter 5.1.2 BPSK */
|
||||
#if 1
|
||||
d_sss[N_ID_2][N_ID_1][n] = dss_current;// * amp;
|
||||
(void) amp;
|
||||
#else
|
||||
(void) amp;
|
||||
d_sss[N_ID_2][N_ID_1][n] = (dss_current * SHRT_MAX)>>SCALING_PSS_NR;
|
||||
#endif
|
||||
d_sss[N_ID_2][N_ID_1][n] = dss_current;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (int i = 0; i < LENGTH_SSS_NR; i++) {
|
||||
printf("sss ref[%i] : %d %d \n", i, d_sss[0][0][i], d_sss[0][0][i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@@ -129,18 +111,10 @@ void init_context_sss_nr(int amp)
|
||||
|
||||
//#define DEBUG_SSS_NR
|
||||
//#define DEBUG_PLOT_SSS
|
||||
void insert_sss_nr(int16_t *sss_time,
|
||||
void insert_sss_nr(c16_t *sss_time,
|
||||
NR_DL_FRAME_PARMS *frame_parms)
|
||||
{
|
||||
unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size;
|
||||
unsigned int size = ofdm_symbol_size * IQ_SIZE; /* i & q */
|
||||
|
||||
assert(size <= SYNCF_TMP_SIZE);
|
||||
assert(size <= SYNC_TMP_SIZE);
|
||||
|
||||
bzero(synchroF_tmp, size);
|
||||
bzero(synchro_tmp, size);
|
||||
|
||||
int Nid2 = GET_NID2(frame_parms->Nid_cell);
|
||||
int Nid1 = GET_NID1(frame_parms->Nid_cell);
|
||||
|
||||
@@ -169,12 +143,12 @@ void insert_sss_nr(int16_t *sss_time,
|
||||
unsigned int k = ofdm_symbol_size - ((LENGTH_SSS_NR/2)+1);
|
||||
|
||||
/* SSS is directly mapped to subcarrier */
|
||||
for (int i=0; i<LENGTH_SSS_NR; i++) {
|
||||
synchroF_tmp[2*k] = d_sss[Nid2][Nid1][i];
|
||||
synchroF_tmp[2*k+1] = 0;
|
||||
|
||||
c16_t in[sizeof(int16_t) * ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
memset(in, 0, sizeof(in));
|
||||
for (int i = 0; i < LENGTH_SSS_NR; i++) {
|
||||
in[i].r = d_sss[Nid2][Nid1][i];
|
||||
in[i].i = 0;
|
||||
k++;
|
||||
|
||||
if (k >= ofdm_symbol_size) {
|
||||
k++;
|
||||
k-=ofdm_symbol_size;
|
||||
@@ -182,13 +156,12 @@ void insert_sss_nr(int16_t *sss_time,
|
||||
}
|
||||
|
||||
/* get sss in the frequency domain by applying an inverse FFT */
|
||||
idft(IDFT_2048,synchroF_tmp, /* complex input */
|
||||
synchro_tmp, /* complex output */
|
||||
1); /* scaling factor */
|
||||
|
||||
/* then get final sss in time */
|
||||
for (unsigned int i=0; i<ofdm_symbol_size; i++) {
|
||||
((int32_t *)sss_time)[i] = ((int32_t *)synchro_tmp)[i];
|
||||
c16_t out[sizeof(int16_t) * ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
memset(out, 0, sizeof(out));
|
||||
memset(sss_time, 0, sizeof(int16_t) * ofdm_symbol_size);
|
||||
idft(IDFT_2048, (int16_t *)&in, (int16_t *)&out, 1);
|
||||
for (unsigned int i = 0; i < ofdm_symbol_size; i++) {
|
||||
sss_time[i] = out[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,99 +178,35 @@ void insert_sss_nr(int16_t *sss_time,
|
||||
*********************************************************************/
|
||||
|
||||
int pss_ch_est_nr(PHY_VARS_NR_UE *ue,
|
||||
int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR])
|
||||
c16_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
c16_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR])
|
||||
{
|
||||
int16_t *pss;
|
||||
int16_t *pss_ext2,*sss_ext2,*sss_ext3,tmp_re,tmp_im,tmp_re2,tmp_im2;
|
||||
uint8_t aarx,i;
|
||||
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
|
||||
pss = primary_synchro_nr2[ue->common_vars.eNb_id];
|
||||
|
||||
sss_ext3 = (int16_t*)&sss_ext[0][0];
|
||||
|
||||
#if 0
|
||||
int16_t chest[2*LENGTH_PSS_NR];
|
||||
#endif
|
||||
|
||||
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
|
||||
|
||||
sss_ext2 = (int16_t*)&sss_ext[aarx][0];
|
||||
pss_ext2 = (int16_t*)&pss_ext[aarx][0];
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
int16_t *p = pss;
|
||||
|
||||
for (int i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
printf(" pss ref [%d] %d %d at address %p\n", i, p[2*i], p[2*i+1], &p[2*i]);
|
||||
printf(" pss ext [%d] %d %d at address %p\n", i, pss_ext2[2*i], pss_ext2[2*i+1], &pss_ext2[2*i]);
|
||||
}
|
||||
|
||||
#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], &sss_ext2[2*i]);
|
||||
printf(" sss ref [%d] %d %d at address %p\n", i, d_sss[0][0][i], d_sss[0][0][i], &d_sss[0][0][i]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int32_t amp;
|
||||
int shift;
|
||||
for (i = 0; i < LENGTH_PSS_NR; 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;
|
||||
#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
|
||||
// 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)));
|
||||
|
||||
// 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 (aarx==0) {
|
||||
sss_ext3[i<<1] = tmp_re2;
|
||||
sss_ext3[1+(i<<1)] = tmp_im2;
|
||||
int id = get_softmodem_params()->sl_mode == 0 ? ue->common_vars.eNb_id : ue->common_vars.N2_id;
|
||||
c16_t *pss = primary_synchro_nr2[id];
|
||||
c16_t tmp, tmp2;
|
||||
c16_t *sss_ext3 = &sss_ext[0][0];
|
||||
for (uint8_t aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
c16_t *sss_ext2 = &sss_ext[aarx][0];
|
||||
c16_t *pss_ext2 = &pss_ext[aarx][0];
|
||||
int32_t amp;
|
||||
int shift;
|
||||
for (uint8_t i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
tmp.r = pss_ext2[i].r * pss[i].r;
|
||||
tmp.i = -pss_ext2[i].i * pss[i].i;
|
||||
amp = (((int32_t)tmp.r) * tmp.r) + ((int32_t)tmp.i) * tmp.i;
|
||||
shift = log2_approx(amp) / 2;
|
||||
tmp2.r = (int16_t)(((tmp.r * (int32_t)sss_ext2[i].r) >> shift) - ((tmp.i * (int32_t)sss_ext2[i].i >> shift)));
|
||||
tmp2.i = (int16_t)(((tmp.r * (int32_t)sss_ext2[i].i) >> shift) + ((tmp.i * (int32_t)sss_ext2[i].r >> shift)));
|
||||
if (aarx == 0) {
|
||||
sss_ext3[i].r = tmp2.r;
|
||||
sss_ext3[i].i = tmp2.i;
|
||||
} else {
|
||||
sss_ext3[i<<1] += tmp_re2;
|
||||
sss_ext3[1+(i<<1)] += tmp_im2;
|
||||
sss_ext3[i].r += tmp2.r;
|
||||
sss_ext3[i].i += tmp2.i;
|
||||
}
|
||||
}
|
||||
}
|
||||
#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
|
||||
|
||||
// sss_ext now contains the compensated SSS
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -315,97 +224,49 @@ int pss_ch_est_nr(PHY_VARS_NR_UE *ue,
|
||||
|
||||
int do_pss_sss_extract_nr(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR],
|
||||
c16_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
c16_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR],
|
||||
uint8_t doPss, uint8_t doSss,
|
||||
uint8_t subframe,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) // add flag to indicate extracting only PSS, only SSS, or both
|
||||
{
|
||||
uint8_t aarx;
|
||||
int32_t *pss_rxF,*pss_rxF_ext;
|
||||
int32_t *sss_rxF,*sss_rxF_ext;
|
||||
uint8_t pss_symbol, sss_symbol;
|
||||
c16_t *pss_rxF,*pss_rxF_ext;
|
||||
c16_t *sss_rxF,*sss_rxF_ext;
|
||||
uint8_t pss_symbol = 0;
|
||||
uint8_t sss_symbol = get_softmodem_params()->sl_mode == 0 ?
|
||||
(SSS_SYMBOL_NB - PSS_SYMBOL_NB) :
|
||||
(SSS0_SL_SYMBOL_NB - PSS0_SL_SYMBOL_NB) ;
|
||||
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
|
||||
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
|
||||
|
||||
pss_symbol = 0;
|
||||
sss_symbol = SSS_SYMBOL_NB-PSS_SYMBOL_NB;
|
||||
|
||||
unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size;
|
||||
|
||||
pss_rxF = (int32_t *)&rxdataF[aarx][pss_symbol*ofdm_symbol_size];
|
||||
sss_rxF = (int32_t *)&rxdataF[aarx][sss_symbol*ofdm_symbol_size];
|
||||
|
||||
pss_rxF = &rxdataF[aarx][pss_symbol * frame_parms->ofdm_symbol_size];
|
||||
sss_rxF = &rxdataF[aarx][sss_symbol * frame_parms->ofdm_symbol_size];
|
||||
pss_rxF_ext = &pss_ext[aarx][0];
|
||||
sss_rxF_ext = &sss_ext[aarx][0];
|
||||
|
||||
unsigned int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + 56;
|
||||
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);
|
||||
|
||||
if (k>= frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size;
|
||||
|
||||
for (int i=0; i < LENGTH_PSS_NR; i++) {
|
||||
if (doPss) {
|
||||
if (doPss) {
|
||||
pss_rxF_ext[i] = pss_rxF[k];
|
||||
}
|
||||
|
||||
if (doSss) {
|
||||
sss_rxF_ext[i] = sss_rxF[k];
|
||||
}
|
||||
|
||||
k++;
|
||||
|
||||
if (k == ofdm_symbol_size) k=0;
|
||||
|
||||
if (k == frame_parms->ofdm_symbol_size) k = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
int16_t *p = (int16_t *)sss_rxF_ext;
|
||||
|
||||
for (int i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
printf(" sss ext 2 [%d] %d %d at address %p\n", i, p[2*i], p[2*i+1], &p[2*i]);
|
||||
printf(" sss ref [%d] %d %d at address %p\n", i, d_sss[0][0][i], d_sss[0][0][i], &d_sss[0][0][i]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
|
||||
int16_t *p2 = (int16_t *)pss_rxF_ext;
|
||||
|
||||
for (int i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
printf(" pss_rxF_ext [%d] %d %d at address %p\n", i, p2[2*i], p2[2*i+1], &p2[2*i]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* NAME : pss_sss_extract_nr
|
||||
*
|
||||
* PARAMETERS : none
|
||||
*
|
||||
* RETURN : none
|
||||
*
|
||||
* DESCRIPTION :
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
int pss_sss_extract_nr(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR],
|
||||
uint8_t subframe,
|
||||
c16_t rxdataF[][phy_vars_ue->frame_parms.samples_per_slot_wCP])
|
||||
{
|
||||
return do_pss_sss_extract_nr(phy_vars_ue, proc, pss_ext, sss_ext, 1 /* doPss */, 1 /* doSss */, subframe, rxdataF);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* NAME : rx_sss_nr
|
||||
@@ -419,170 +280,63 @@ int pss_sss_extract_nr(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
int rx_sss_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric, uint8_t *phase_max, int *freq_offset_sss, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
|
||||
int rx_sss_nr(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int32_t *tot_metric,
|
||||
uint8_t *phase_max,
|
||||
int *freq_offset_sss,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
|
||||
{
|
||||
uint8_t i;
|
||||
int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR];
|
||||
int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR];
|
||||
uint8_t Nid2 = GET_NID2(ue->common_vars.eNb_id);
|
||||
uint16_t Nid1;
|
||||
uint8_t phase;
|
||||
int16_t *sss;
|
||||
NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
|
||||
int32_t metric, metric_re;
|
||||
int16_t *d;
|
||||
c16_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR];
|
||||
c16_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR];
|
||||
do_pss_sss_extract_nr(ue, proc, pss_ext, sss_ext, 1 /* doPss */, 1 /* doSss */, 0 /* subframe */, rxdataF);
|
||||
pss_ch_est_nr(ue, pss_ext, sss_ext);
|
||||
|
||||
|
||||
// pss sss extraction
|
||||
pss_sss_extract_nr(ue,
|
||||
proc,
|
||||
pss_ext,
|
||||
sss_ext,
|
||||
0,
|
||||
rxdataF); /* subframe */
|
||||
|
||||
#ifdef DEBUG_PLOT_SSS
|
||||
|
||||
write_output("rxsig0.m","rxs0",&ue->common_vars.rxdata[0][0],ue->frame_parms.samples_per_subframe,1,1);
|
||||
write_output("rxdataF0_pss.m","rxF0_pss",&ue->common_vars.rxdataF[0][0],frame_parms->ofdm_symbol_size,1,1);
|
||||
write_output("rxdataF0_sss.m","rxF0_sss",&ue->common_vars.rxdataF[0][(SSS_SYMBOL_NB-PSS_SYMBOL_NB)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size,1,1);
|
||||
write_output("pss_ext.m","pss_ext",pss_ext,LENGTH_PSS_NR,1,1);
|
||||
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
int16_t *p = (int16_t *)sss_ext[0];
|
||||
int16_t *p2 = (int16_t *)pss_ext[0];
|
||||
|
||||
for (int i = 0; i < LENGTH_SSS_NR; i++) {
|
||||
printf("sss ref [%i] : %d %d \n", i, d_sss[0][0][i], d_sss[0][0][i]);
|
||||
printf("sss ext [%i] : %d %d \n", i, p[2*i], p[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, p2[2*i], p2[2*i+1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
// get conjugated channel estimate from PSS, H* = R* \cdot PSS
|
||||
// and do channel estimation and compensation based on PSS
|
||||
|
||||
pss_ch_est_nr(ue,
|
||||
pss_ext,
|
||||
sss_ext);
|
||||
|
||||
// now do the SSS detection based on the precomputed sequences in PHY/LTE_TRANSPORT/sss.h
|
||||
*tot_metric = INT_MIN;
|
||||
|
||||
sss = (int16_t*)&sss_ext[0][0];
|
||||
|
||||
#ifdef DEBUG_PLOT_SSS
|
||||
|
||||
write_output("sss_ext.m","sss_ext",sss_ext[0],LENGTH_SSS_NR,1,1);
|
||||
write_output("sss_ref.m","sss_ref", d_sss,LENGTH_SSS_NR,1,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) */
|
||||
|
||||
uint16_t Nid1_start = 0;
|
||||
uint16_t Nid1_end = N_ID_1_NUMBER;
|
||||
if (ue->target_Nid_cell != -1) {
|
||||
Nid1_start = GET_NID1(ue->target_Nid_cell);
|
||||
Nid1_end = Nid1_start + 1;
|
||||
}
|
||||
|
||||
for (Nid1 = Nid1_start; Nid1 < Nid1_end; Nid1++) { // all possible Nid1 values
|
||||
for (phase = 0; phase < PHASE_HYPOTHESIS_NUMBER; phase++) { // phase offset between PSS and SSS
|
||||
|
||||
metric = 0;
|
||||
metric_re = 0;
|
||||
|
||||
c16_t *sss = &sss_ext[0][0];
|
||||
uint16_t Nid1;
|
||||
uint8_t Nid2 = get_softmodem_params()->sl_mode == 0 ? ue->common_vars.eNb_id : ue->common_vars.N2_id;
|
||||
int16_t *d;
|
||||
for (Nid1 = 0; Nid1 < N_ID_1_NUMBER; Nid1++) {
|
||||
for (uint8_t phase = 0; phase < PHASE_HYPOTHESIS_NUMBER; phase++) {
|
||||
int32_t metric = 0;
|
||||
int32_t metric_re = 0;
|
||||
d = (int16_t *)&d_sss[Nid2][Nid1];
|
||||
|
||||
// This is the inner product using one particular value of each unknown parameter
|
||||
for (i=0; i < LENGTH_SSS_NR; i++) {
|
||||
|
||||
metric_re += d[i]*(((phase_re_nr[phase]*sss[2*i])>>SCALING_METRIC_SSS_NR) - ((phase_im_nr[phase]*sss[2*i+1])>>SCALING_METRIC_SSS_NR));
|
||||
|
||||
#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
|
||||
for (uint8_t i = 0; i < LENGTH_SSS_NR; i++) {
|
||||
metric_re += d[i] * (((phase_re_nr[phase] * sss[i].r) >> SCALING_METRIC_SSS_NR) - ((phase_im_nr[phase] * sss[i].i) >> SCALING_METRIC_SSS_NR));
|
||||
}
|
||||
|
||||
metric = metric_re;
|
||||
|
||||
// if the current metric is better than the last save it
|
||||
if (metric > *tot_metric) {
|
||||
*tot_metric = metric;
|
||||
ue->frame_parms.Nid_cell = Nid2+(3*Nid1);
|
||||
*phase_max = phase;
|
||||
|
||||
#ifdef DEBUG_SSS_NR
|
||||
|
||||
LOG_D(PHY,"(phase,Nid1) (%d,%d), metric_phase %d tot_metric %d, phase_max %d \n",phase, Nid1, metric, *tot_metric, *phase_max);
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//#ifdef DEBUG_SSS_NR
|
||||
|
||||
#define SSS_METRIC_FLOOR_NR (30000)
|
||||
if (*tot_metric > SSS_METRIC_FLOOR_NR) {
|
||||
Nid2 = GET_NID2(frame_parms->Nid_cell);
|
||||
Nid1 = GET_NID1(frame_parms->Nid_cell);
|
||||
LOG_D(PHY,"Nid2 %d Nid1 %d tot_metric %d, phase_max %d \n", Nid2, Nid1, *tot_metric, *phase_max);
|
||||
if (*tot_metric > SSS_METRIC_FLOOR_NR) {
|
||||
Nid2 = GET_NID2(ue->frame_parms.Nid_cell);
|
||||
Nid1 = GET_NID1(ue->frame_parms.Nid_cell);
|
||||
LOG_I(NR_PHY,"Nid2 %d Nid1 %d tot_metric %d, phase_max %d \n", Nid2, Nid1, *tot_metric, *phase_max);
|
||||
}
|
||||
//#endif
|
||||
|
||||
if (Nid1==N_ID_1_NUMBER)
|
||||
if (Nid1 == N_ID_1_NUMBER) {
|
||||
LOG_I(NR_PHY,"Failed to detect SSS after PSS\n");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
int re = 0;
|
||||
int im = 0;
|
||||
if (Nid1 == N_ID_1_NUMBER) {
|
||||
LOG_I(PHY,"Failed to detect SSS after PSS\n");
|
||||
return -1;
|
||||
for(int i = 0; i < LENGTH_SSS_NR; i++) {
|
||||
re += d[i] * sss[i].r;
|
||||
im += d[i] * sss[i].i;
|
||||
}
|
||||
d = (int16_t *)&d_sss[Nid2][Nid1];
|
||||
for(i = 0; i<LENGTH_SSS_NR; i++) {
|
||||
re += d[i]*sss[2*i];
|
||||
im += d[i]*sss[2*i+1];
|
||||
}
|
||||
double ffo_sss = atan2(im,re)/M_PI/4.3;
|
||||
*freq_offset_sss = (int)(ffo_sss*frame_parms->subcarrier_spacing);
|
||||
|
||||
double ffo_pss = ((double)ue->common_vars.freq_offset)/frame_parms->subcarrier_spacing;
|
||||
double ffo_sss = atan2(im,re)/M_PI/4.3;
|
||||
*freq_offset_sss = (int)(ffo_sss * ue->frame_parms.subcarrier_spacing);
|
||||
double ffo_pss = ((double)ue->common_vars.freq_offset)/ue->frame_parms.subcarrier_spacing;
|
||||
LOG_I(NR_PHY, "ffo_pss %f (%i Hz), ffo_sss %f (%i Hz), ffo_pss+ffo_sss %f (%i Hz)\n",
|
||||
ffo_pss, (int)(ffo_pss*frame_parms->subcarrier_spacing), ffo_sss, *freq_offset_sss, ffo_pss+ffo_sss, (int)((ffo_pss+ffo_sss)*frame_parms->subcarrier_spacing));
|
||||
ffo_pss, (int)(ffo_pss*ue->frame_parms.subcarrier_spacing), ffo_sss, *freq_offset_sss, ffo_pss+ffo_sss, (int)((ffo_pss+ffo_sss)*ue->frame_parms.subcarrier_spacing));
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
357
openair1/PHY/NR_UE_TRANSPORT/sss_nr_sl.c
Normal file
357
openair1/PHY/NR_UE_TRANSPORT/sss_nr_sl.c
Normal file
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <nr-uesoftmodem.h>
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/phy_extern.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "PHY/NR_REFSIG/ss_pbch_nr.h"
|
||||
#include "PHY/NR_REFSIG/sss_nr.h"
|
||||
|
||||
//#define DEBUG_PLOT_SSS 1
|
||||
|
||||
int nr_sl_generate_sss(c16_t *txdataF,
|
||||
int16_t amp,
|
||||
uint8_t ssb_start_symbol,
|
||||
NR_DL_FRAME_PARMS *frame_parms)
|
||||
{
|
||||
int16_t x0[NR_SSS_LENGTH];
|
||||
int16_t x1[NR_SSS_LENGTH];
|
||||
const int x0_initial[7] = { 1, 0, 0, 0, 0, 0, 0 };
|
||||
const int x1_initial[7] = { 1, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
|
||||
|
||||
/// Sequence generation
|
||||
int Nid = frame_parms->Nid_SL;
|
||||
int Nid1 = GET_NID1_SL(Nid);
|
||||
int Nid2 = GET_NID2_SL(Nid);
|
||||
|
||||
for (int i=0; i < 7; i++) {
|
||||
x0[i] = x0_initial[i];
|
||||
x1[i] = x1_initial[i];
|
||||
}
|
||||
|
||||
for (int i=0; i < NR_SSS_LENGTH - 7; i++) {
|
||||
x0[i+7] = (x0[i + 4] + x0[i]) % 2;
|
||||
x1[i+7] = (x1[i + 1] + x1[i]) % 2;
|
||||
}
|
||||
|
||||
int m0 = 15 * (Nid1 / 112) + (5 * Nid2);
|
||||
int m1 = Nid1 % 112;
|
||||
|
||||
#ifdef NR_SSS_DEBUG
|
||||
write_output("d_sss.m", "d_sss", (void*)d_sss, NR_SSS_LENGTH, 1, 1);
|
||||
#endif
|
||||
|
||||
/// Resource mapping
|
||||
|
||||
// SSS occupies a predefined position (subcarriers 2-129, symbol 3) within the SSB block starting from
|
||||
int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + PSS_SSS_SUB_CARRIER_START_SL;
|
||||
int l = ssb_start_symbol + 3;
|
||||
|
||||
for (int i = 0; i < NR_SSS_LENGTH; i++) {
|
||||
int16_t dss_current = (1 - 2 * x0[(i + m0) % NR_SSS_LENGTH] ) * (1 - 2 * x1[(i + m1) % NR_SSS_LENGTH] ) * 23170;
|
||||
d_sss[Nid2][Nid1][i] = dss_current;
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].r = (((int16_t)amp) * dss_current) >> 15;
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].i = 0;
|
||||
k++;
|
||||
|
||||
if (k >= frame_parms->ofdm_symbol_size)
|
||||
k-=frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
|
||||
// SSS occupies a predefined position (subcarriers 2 to 129, symbol 4) within the SSB block starting from
|
||||
k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + PSS_SSS_SUB_CARRIER_START_SL;
|
||||
l = ssb_start_symbol + 4;
|
||||
|
||||
for (int i = 0; i < NR_SSS_LENGTH; i++) {
|
||||
int16_t dss_current = (1 - 2 * x0[(i + m0) % NR_SSS_LENGTH]) * (1 - 2 * x1[(i + m1) % NR_SSS_LENGTH] ) * 23170;
|
||||
d_sss[Nid2][Nid1][i] = dss_current;
|
||||
txdataF[(l*frame_parms->ofdm_symbol_size + k)].r = (((int16_t)amp) * dss_current) >> 15;
|
||||
txdataF[(l*frame_parms->ofdm_symbol_size + k)].i = 0;
|
||||
k++;
|
||||
|
||||
if (k >= frame_parms->ofdm_symbol_size)
|
||||
k-=frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
#ifdef NR_SSS_DEBUG
|
||||
// write_output("sss_0.m", "sss_0", (void*)txdataF[0][l*frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1);
|
||||
char buffer[frame_parms->ofdm_symbol_size];
|
||||
for (int i = 3; i < 5; i++) {
|
||||
bzero(buffer, sizeof(buffer));
|
||||
LOG_I(NR_PHY, "SSS %d = %s\n", i, hexdump(&txdataF[frame_parms->ofdm_symbol_size*i],
|
||||
frame_parms->ofdm_symbol_size, buffer, sizeof(buffer)));
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* NAME : pss_sss_sl_extract_nr
|
||||
*
|
||||
* PARAMETERS : none
|
||||
*
|
||||
* RETURN : none
|
||||
*
|
||||
* DESCRIPTION :
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
static int pss_sss_sl_extract_nr(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
c16_t pss0_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
c16_t sss0_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR],
|
||||
c16_t pss1_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
c16_t sss1_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR])
|
||||
{
|
||||
c16_t **rxdataF = ue->common_vars.rxdataF;
|
||||
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size;
|
||||
|
||||
c16_t *pss0_rxF, *pss0_rxF_ext;
|
||||
c16_t *sss0_rxF, *sss0_rxF_ext;
|
||||
for (uint8_t aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
|
||||
pss0_rxF = &rxdataF[aarx][PSS0_SL_SYMBOL_NB * ofdm_symbol_size];
|
||||
sss0_rxF = &rxdataF[aarx][SSS0_SL_SYMBOL_NB * ofdm_symbol_size];
|
||||
pss0_rxF_ext = &pss0_ext[aarx][0];
|
||||
sss0_rxF_ext = &sss0_ext[aarx][0];
|
||||
unsigned int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + PSS_SSS_SUB_CARRIER_START_SL;
|
||||
if (k >= ofdm_symbol_size)
|
||||
k-=ofdm_symbol_size;
|
||||
|
||||
for (int i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
pss0_rxF_ext[i] = pss0_rxF[k];
|
||||
sss0_rxF_ext[i] = sss0_rxF[k];
|
||||
k++;
|
||||
if (k == ofdm_symbol_size) k = 0;
|
||||
}
|
||||
}
|
||||
|
||||
c16_t *pss1_rxF, *pss1_rxF_ext;
|
||||
c16_t *sss1_rxF, *sss1_rxF_ext;
|
||||
for (uint8_t aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
|
||||
pss1_rxF = &rxdataF[aarx][PSS1_SL_SYMBOL_NB * ofdm_symbol_size];
|
||||
sss1_rxF = &rxdataF[aarx][SSS1_SL_SYMBOL_NB * ofdm_symbol_size];
|
||||
pss1_rxF_ext = &pss1_ext[aarx][0];
|
||||
sss1_rxF_ext = &sss1_ext[aarx][0];
|
||||
unsigned int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + PSS_SSS_SUB_CARRIER_START_SL;
|
||||
if (k >= frame_parms->ofdm_symbol_size)
|
||||
k-=frame_parms->ofdm_symbol_size;
|
||||
|
||||
for (int i=0; i < LENGTH_PSS_NR; i++) {
|
||||
pss1_rxF_ext[i] = pss1_rxF[k];
|
||||
sss1_rxF_ext[i] = sss1_rxF[k];
|
||||
k++;
|
||||
if (k == ofdm_symbol_size) k = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* NAME : pss_ch_est
|
||||
*
|
||||
* PARAMETERS : none
|
||||
*
|
||||
* RETURN : none
|
||||
*
|
||||
* DESCRIPTION : pss channel estimation
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
int pss_sl_ch_est_nr(PHY_VARS_NR_UE *ue,
|
||||
c16_t pss0_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
c16_t sss0_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR],
|
||||
c16_t pss1_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
c16_t sss1_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR])
|
||||
{
|
||||
int id = get_softmodem_params()->sl_mode == 0 ? ue->common_vars.eNb_id : ue->common_vars.N2_id;
|
||||
c16_t *pss = primary_synchro_nr[id];
|
||||
c16_t tmp, tmp2;
|
||||
c16_t *sss0_ext3 = &sss0_ext[0][0];
|
||||
for (uint8_t aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
c16_t *sss0_ext2 = &sss0_ext[aarx][0];
|
||||
c16_t *pss0_ext2 = &pss0_ext[aarx][0];
|
||||
for (uint8_t i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
// This is H*(PSS) = R* \cdot PSS
|
||||
tmp.r = (int16_t)((((int32_t)pss0_ext2[i].r) * pss[i].r)>>15);
|
||||
tmp.i = -(int16_t)((((int32_t)pss0_ext2[i].i) * pss[i].r)>>15);
|
||||
|
||||
int32_t amp = (((int32_t)tmp.r) * tmp.r) + ((int32_t)tmp.i) * tmp.i;
|
||||
int shift = log2_approx(amp) / 2;
|
||||
// This is R(SSS) \cdot H*(PSS)
|
||||
tmp2.r = (int16_t)(((tmp.r * (int32_t)sss0_ext2[i].r) >> shift) - ((tmp.i * (int32_t)sss0_ext2[i].i >> shift)));
|
||||
tmp2.i = (int16_t)(((tmp.r * (int32_t)sss0_ext2[i].i) >> shift) + ((tmp.i * (int32_t)sss0_ext2[i].r >> shift)));
|
||||
// MRC on RX antennas
|
||||
if (aarx==0) {
|
||||
sss0_ext3[i].r = tmp2.r;
|
||||
sss0_ext3[i].i = tmp2.i;
|
||||
} else {
|
||||
sss0_ext3[i].r += tmp2.r;
|
||||
sss0_ext3[i].i += tmp2.i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c16_t *sss1_ext3 = &sss1_ext[0][0];
|
||||
for (uint8_t aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
c16_t *sss1_ext2 = &sss1_ext[aarx][0];
|
||||
c16_t *pss1_ext2 = &pss1_ext[aarx][0];
|
||||
for (uint8_t i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
// This is H*(PSS) = R* \cdot PSS
|
||||
tmp.r = (int16_t)((((int32_t)pss1_ext2[i].r) * pss[i].r)>>15);
|
||||
tmp.i = -(int16_t)((((int32_t)pss1_ext2[i].i) * pss[i].r)>>15);
|
||||
int32_t amp = (((int32_t)tmp.r) * tmp.r) + ((int32_t)tmp.i) * tmp.i;
|
||||
int shift = log2_approx(amp) / 2;
|
||||
// This is R(SSS) \cdot H*(PSS)
|
||||
tmp2.r = (int16_t)(((tmp.r * (int32_t)sss1_ext2[i].r) >> shift) - ((tmp.i * (int32_t)sss1_ext2[i].i >> shift)));
|
||||
tmp2.i = (int16_t)(((tmp.r * (int32_t)sss1_ext2[i].i) >> shift) + ((tmp.i * (int32_t)sss1_ext2[i].r >> shift)));
|
||||
|
||||
// MRC on RX antennas
|
||||
if (aarx == 0) {
|
||||
sss1_ext3[i].r = tmp2.r;
|
||||
sss1_ext3[i].i = tmp2.i;
|
||||
} else {
|
||||
sss1_ext3[i].r += tmp2.r;
|
||||
sss1_ext3[i].i += tmp2.i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* NAME : rx_sss_sl_nr
|
||||
*
|
||||
* PARAMETERS : none
|
||||
*
|
||||
* RETURN : Set Nid_cell in ue context
|
||||
*
|
||||
* DESCRIPTION : Determine element Nid1 of cell identity
|
||||
* so Nid_cell in ue context is set according to Nid1 & Nid2
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
int rx_sss_sl_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric, uint8_t *phase_max, int *freq_offset_sss)
|
||||
{
|
||||
c16_t pss0_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR];
|
||||
c16_t sss0_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR];
|
||||
c16_t pss1_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR];
|
||||
c16_t sss1_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR];
|
||||
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
|
||||
pss_sss_sl_extract_nr(ue, proc, pss0_ext, sss0_ext, pss1_ext, sss1_ext);
|
||||
|
||||
#ifdef DEBUG_PLOT_SSS
|
||||
write_output("rxsig0.m","rxs0",&ue->common_vars.rxdata[0][0],ue->frame_parms.samples_per_frame,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("pss0_ext.m","pss0_ext",pss0_ext,LENGTH_PSS_NR,1,1);
|
||||
write_output("pss1_ext.m","pss1_ext",pss1_ext,LENGTH_PSS_NR,1,1);
|
||||
write_output("sss0_ext.m","sss0_ext",sss0_ext,LENGTH_PSS_NR,1,1);
|
||||
write_output("sss1_ext.m","sss1_ext",sss1_ext,LENGTH_PSS_NR,1,1);
|
||||
write_output("pss0_time.m","pss0_time",primary_synchro_time_nr[0],frame_parms->ofdm_symbol_size,1,1);
|
||||
write_output("pss1_time.m","pss1_time",primary_synchro_time_nr[1],frame_parms->ofdm_symbol_size,1,1);
|
||||
#endif
|
||||
|
||||
// get conjugated channel estimate from PSS, H* = R* \cdot PSS
|
||||
// and do channel estimation and compensation based on PSS
|
||||
pss_sl_ch_est_nr(ue, pss0_ext, sss0_ext, pss1_ext, sss1_ext);
|
||||
|
||||
write_output("sss0_comp.m","sss0_comp",sss0_ext,LENGTH_PSS_NR,1,1);
|
||||
write_output("sss1_comp.m","sss1_comp",sss1_ext,LENGTH_PSS_NR,1,1);
|
||||
/* now do the SSS detection based on the precomputed sequences in PHY/LTE_TRANSPORT/sss.
|
||||
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) */
|
||||
uint16_t Nid1;
|
||||
uint8_t Nid2 = ue->common_vars.N2_id;
|
||||
*tot_metric = INT_MIN;
|
||||
c16_t *sss0 = &sss0_ext[0][0];
|
||||
c16_t *sss1 = &sss1_ext[0][0];
|
||||
int16_t *d;
|
||||
for (Nid1 = 0; Nid1 < N_ID_1_NUMBER; Nid1++) { // all possible Nid1 values
|
||||
for (uint8_t phase = 0; phase < PHASE_HYPOTHESIS_NUMBER; phase++) { // phase offset between PSS and SSS
|
||||
int32_t metric = 0;
|
||||
int32_t metric_re = 0;
|
||||
d = (int16_t *)&d_sss[Nid2][Nid1];
|
||||
// This is the inner product using one particular value of each unknown parameter
|
||||
for (int i = 0; i < LENGTH_SSS_NR; i++) {
|
||||
metric_re += d[i] * (((phase_re_nr[phase] * sss0[i].r) >> SCALING_METRIC_SSS_NR) - ((phase_im_nr[phase] * sss0[i].i) >> SCALING_METRIC_SSS_NR)) +
|
||||
d[i] * (((phase_re_nr[phase] * sss1[i].r) >> SCALING_METRIC_SSS_NR) - ((phase_im_nr[phase] * sss1[i].i) >> SCALING_METRIC_SSS_NR));
|
||||
}
|
||||
metric = metric_re;
|
||||
if (metric > *tot_metric) {
|
||||
*tot_metric = metric;
|
||||
ue->frame_parms.Nid_SL = Nid1 + NUMBER_SSS_SEQUENCE * Nid2;
|
||||
*phase_max = phase;
|
||||
#ifdef DEBUG_SSS_NR
|
||||
LOG_I(NR_PHY,"(phase, Nid1) (%d,%d), metric_phase = %d, tot_metric = %d, phase_max = %d \n", phase, Nid1, metric, *tot_metric, *phase_max);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Nid2 = GET_NID2_SL(frame_parms->Nid_SL);
|
||||
Nid1 = GET_NID1_SL(frame_parms->Nid_SL);
|
||||
#if 1
|
||||
LOG_I(NR_PHY, "Nid2 %d Nid1 %d tot_metric %d, phase_max %d \n", Nid2, Nid1, *tot_metric, *phase_max);
|
||||
#endif
|
||||
|
||||
if (Nid1 == N_ID_1_NUMBER) {
|
||||
LOG_I(PHY,"Failled to detect SL SSS after PSS\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int re = 0;
|
||||
int im = 0;
|
||||
d = (int16_t *)&d_sss[Nid2][Nid1];
|
||||
for(int i = 0; i < LENGTH_SSS_NR; i++) {
|
||||
re += d[i] * sss0[i].r;
|
||||
im += d[i] * sss0[i].i;
|
||||
re += d[i] * sss1[i].r;
|
||||
im += d[i] * sss1[i].i;
|
||||
}
|
||||
|
||||
double ffo_sss = atan2(im, re) / M_PI / 4.3;
|
||||
*freq_offset_sss = (int)(ffo_sss * frame_parms->subcarrier_spacing);
|
||||
double ffo_pss = ((double)ue->common_vars.freq_offset) / frame_parms->subcarrier_spacing;
|
||||
LOG_I(NR_PHY, "ffo_pss %f (%i Hz), ffo_sss %f (%i Hz), ffo_pss+ffo_sss %f (%i Hz)\n",
|
||||
ffo_pss, (int)(ffo_pss * frame_parms->subcarrier_spacing), ffo_sss, *freq_offset_sss, ffo_pss + ffo_sss,
|
||||
(int)((ffo_pss + ffo_sss) * frame_parms->subcarrier_spacing));
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -61,10 +61,13 @@ enum UEdataType {
|
||||
pbchRxdataF_comp,
|
||||
pdcchLlr,
|
||||
pdcchRxdataF_comp,
|
||||
UEdataTypeNumberOfItems,
|
||||
psbchDlChEstimateTime,
|
||||
psbchLlr,
|
||||
psbchRxdataF_comp,
|
||||
pdschLlr,
|
||||
pdschRxdataF_comp,
|
||||
commonRxdataF,
|
||||
UEdataTypeNumberOfItems
|
||||
};
|
||||
|
||||
typedef struct scopeData_s {
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#include "defs_nr_common.h"
|
||||
#include "CODING/nrPolar_tools/nr_polar_pbch_defs.h"
|
||||
#include "CODING/nrPolar_tools/nr_polar_psbch_defs.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -233,17 +234,18 @@ typedef struct {
|
||||
/// - first index: rx antenna [0..nb_antennas_rx[
|
||||
/// - second index: sample [0..2*FRAME_LENGTH_COMPLEX_SAMPLES+2048[
|
||||
c16_t **rxdata;
|
||||
|
||||
/// \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[
|
||||
/// \brief Holds the received data in the frequency domain.
|
||||
/// For IFFT_FPGA this points to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER.
|
||||
/// - first index: tx antenna [0..nb_antennas_tx[
|
||||
/// - second index: sample [0..FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX[
|
||||
c16_t **rxdataF;
|
||||
|
||||
/// holds output of the sync correlator
|
||||
int32_t *sync_corr;
|
||||
/// estimated frequency offset (in radians) for all subcarriers
|
||||
int32_t freq_offset;
|
||||
// N2_id - assigned based on in coverage status received in pss
|
||||
int32_t N2_id;
|
||||
/// eNb_id user is synched to
|
||||
int32_t eNb_id;
|
||||
} NR_UE_COMMON;
|
||||
@@ -318,7 +320,24 @@ typedef struct {
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t pdcch_config[FAPI_NR_MAX_SS];
|
||||
} NR_UE_PDCCH_CONFIG;
|
||||
|
||||
#define PBCH_A 24
|
||||
#define PSBCH_A 32
|
||||
#define PSBCH_MAX_RE_PER_SYMBOL (11*12)
|
||||
#define PSBCH_MAX_RE (PSBCH_MAX_RE_PER_SYMBOL*14)
|
||||
|
||||
typedef struct {
|
||||
/// \brief Total number of PDU errors.
|
||||
uint32_t pdu_errors;
|
||||
/// \brief Total number of PDU errors 128 frames ago.
|
||||
uint32_t pdu_errors_last;
|
||||
/// \brief Total number of consecutive PDU errors.
|
||||
uint32_t pdu_errors_conseq;
|
||||
/// \brief FER (in percent) .
|
||||
//uint32_t pdu_fer;
|
||||
uint32_t psbch_a;
|
||||
uint32_t psbch_a_interleaved;
|
||||
uint32_t psbch_a_prime;
|
||||
uint32_t psbch_e[NR_POLAR_PSBCH_E_DWORD];
|
||||
} NR_UE_PSBCH;
|
||||
|
||||
typedef struct {
|
||||
int16_t amp;
|
||||
@@ -378,8 +397,14 @@ typedef struct {
|
||||
int if_freq_off;
|
||||
/// \brief Indicator that UE is synchronized to a gNB
|
||||
int is_synchronized;
|
||||
/// \brief Indicator that UE is synchronized to a SyncRef UE on Sidelink
|
||||
int is_synchronized_sl;
|
||||
/// \brief Indicator that UE lost frame synchronization on Sidelink
|
||||
int lost_sync_sl;
|
||||
/// \brief Target gNB Nid_cell when UE is resynchronizing
|
||||
int target_Nid_cell;
|
||||
/// \brief Indicator that UE is an SynchRef UE
|
||||
int sync_ref;
|
||||
/// Data structure for UE process scheduling
|
||||
UE_nr_proc_t proc;
|
||||
/// Flag to indicate the UE shouldn't do timing correction at all
|
||||
@@ -420,10 +445,13 @@ typedef struct {
|
||||
fapi_nr_config_request_t nrUE_config;
|
||||
nr_synch_request_t synch_request;
|
||||
|
||||
NR_UE_PSBCH *psbch_vars[NUMBER_OF_CONNECTED_gNB_MAX];
|
||||
NR_UE_PRACH *prach_vars[NUMBER_OF_CONNECTED_gNB_MAX];
|
||||
NR_UE_CSI_IM *csiim_vars[NUMBER_OF_CONNECTED_gNB_MAX];
|
||||
NR_UE_CSI_RS *csirs_vars[NUMBER_OF_CONNECTED_gNB_MAX];
|
||||
NR_UE_SRS *srs_vars[NUMBER_OF_CONNECTED_gNB_MAX];
|
||||
NR_SLSS_t *slss;
|
||||
|
||||
NR_UE_PRS *prs_vars[NR_MAX_PRS_COMB_SIZE];
|
||||
uint8_t prs_active_gNBs;
|
||||
NR_DL_UE_HARQ_t dl_harq_processes[2][NR_MAX_DLSCH_HARQ_PROCESSES];
|
||||
@@ -445,7 +473,10 @@ typedef struct {
|
||||
/// PBCH DMRS sequence
|
||||
uint32_t nr_gold_pbch[2][64][NR_PBCH_DMRS_LENGTH_DWORD];
|
||||
|
||||
/// PDSCH DMRS
|
||||
/// PSBCH DMRS sequence
|
||||
uint32_t nr_gold_psbch[NR_PSBCH_DMRS_LENGTH_DWORD];
|
||||
|
||||
/// PDSCH DMRS
|
||||
uint32_t ****nr_gold_pdsch[NUMBER_OF_CONNECTED_eNB_MAX];
|
||||
|
||||
// Scrambling IDs used in PDSCH DMRS
|
||||
@@ -514,6 +545,7 @@ typedef struct {
|
||||
int ssb_offset;
|
||||
uint16_t symbol_offset; /// offset in terms of symbols for detected ssb in sync
|
||||
int rx_offset; /// Timing offset
|
||||
int rx_offset_sl; /// Timing offset for Sidelink
|
||||
int rx_offset_diff; /// Timing adjustment for ofdm symbol0 on HW USRP
|
||||
int max_pos_fil; /// Timing offset IIR filter
|
||||
int time_sync_cell;
|
||||
@@ -659,6 +691,7 @@ typedef struct nr_rxtx_thread_data_s {
|
||||
UE_nr_rxtx_proc_t proc;
|
||||
PHY_VARS_NR_UE *UE;
|
||||
int writeBlockSize;
|
||||
notifiedFIFO_t txFifo;
|
||||
nr_phy_data_t phy_data;
|
||||
int tx_wait_for_dlsch;
|
||||
} nr_rxtx_thread_data_t;
|
||||
|
||||
@@ -69,6 +69,10 @@
|
||||
|
||||
#define NR_PBCH_DMRS_LENGTH 144 // in mod symbols
|
||||
#define NR_PBCH_DMRS_LENGTH_DWORD 10 // ceil(2(QPSK)*NR_PBCH_DMRS_LENGTH/32)
|
||||
#define NR_PSBCH_MAX_NB_CARRIERS 132
|
||||
#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)
|
||||
|
||||
/*used for the resource mapping*/
|
||||
#define NR_MAX_PDCCH_DMRS_LENGTH 576 // 16(L)*2(QPSK)*3(3 DMRS symbs per REG)*6(REG per CCE)
|
||||
@@ -95,6 +99,8 @@
|
||||
|
||||
#define NR_NB_NSCID 2
|
||||
|
||||
#define NR_RX_NB_TH 1
|
||||
|
||||
#define MAX_UL_DELAY_COMP 20
|
||||
|
||||
typedef enum {
|
||||
@@ -157,6 +163,8 @@ struct NR_DL_FRAME_PARMS {
|
||||
uint64_t dl_CarrierFreq;
|
||||
/// UL carrier frequency
|
||||
uint64_t ul_CarrierFreq;
|
||||
/// SL carrier frequency
|
||||
uint64_t sl_CarrierFreq;
|
||||
/// TX attenuation
|
||||
uint32_t att_tx;
|
||||
/// RX attenuation
|
||||
@@ -164,7 +172,12 @@ struct NR_DL_FRAME_PARMS {
|
||||
/// total Number of Resource Block Groups: this is ceil(N_PRB/P)
|
||||
/// Frame type (0 FDD, 1 TDD)
|
||||
frame_type_t frame_type;
|
||||
|
||||
uint16_t tdd_slot_config;
|
||||
uint8_t tdd_period;
|
||||
uint8_t tdd_config;
|
||||
/// Sidelink Cell ID
|
||||
uint16_t Nid_SL;
|
||||
/// Cell ID
|
||||
uint16_t Nid_cell;
|
||||
/// subcarrier spacing (15,30,60,120)
|
||||
@@ -216,8 +229,8 @@ struct NR_DL_FRAME_PARMS {
|
||||
/// Cyclic Prefix for DL (0=Normal CP, 1=Extended CP)
|
||||
lte_prefix_type_t Ncp;
|
||||
/// sequence which is computed based on carrier frequency and numerology to rotate/derotate each OFDM symbol according to Section 5.3 in 38.211
|
||||
/// First dimension is for the direction of the link (0 DL, 1 UL)
|
||||
c16_t symbol_rotation[2][224];
|
||||
/// First dimension is for the direction of the link (0 DL, 1 UL, 2 SL)
|
||||
c16_t symbol_rotation[3][224];
|
||||
/// sequence used to compensate the phase rotation due to timeshifted OFDM symbols
|
||||
/// First dimenstion is for different CP lengths
|
||||
c16_t timeshift_symbol_rotation[4096*2] __attribute__ ((aligned (16)));
|
||||
@@ -258,6 +271,17 @@ struct NR_DL_FRAME_PARMS {
|
||||
uint32_t ofdm_offset_divisor;
|
||||
};
|
||||
|
||||
/* NR Sidelink PSBCH payload fields
|
||||
TODO: This will be removed in the future and
|
||||
filled in by the upper layers once developed. */
|
||||
typedef struct {
|
||||
uint32_t coverageIndicator : 1;
|
||||
uint32_t tddConfig : 12;
|
||||
uint32_t DFN : 10;
|
||||
uint32_t slotIndex : 7;
|
||||
uint32_t reserved : 2;
|
||||
} PSBCH_payload;
|
||||
|
||||
// PRS config structures
|
||||
typedef struct {
|
||||
uint16_t PRSResourceSetPeriod[2]; // [slot period, slot offset] of a PRS resource set
|
||||
|
||||
@@ -99,6 +99,10 @@ SystemInformationBlockType1_nr_t;
|
||||
#define NR_UPLINK_SLOT (0x02)
|
||||
#define NR_MIXED_SLOT (0x03)
|
||||
|
||||
#define NR_LINK_TYPE_DL (0x00)
|
||||
#define NR_LINK_TYPE_UL (0x01)
|
||||
#define NR_LINK_TYPE_SL (0x02)
|
||||
|
||||
#define FRAME_DURATION_MICRO_SEC (10000) /* frame duration in microsecond */
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -23,6 +23,10 @@
|
||||
#define __PHY_EXTERN_NR_UE__H__
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
|
||||
extern uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
extern uint64_t sidelink_frequency[MAX_NUM_CCs][4];
|
||||
extern PHY_VARS_NR_UE ***PHY_vars_UE_g;
|
||||
|
||||
#endif /*__PHY_EXTERN_H__ */
|
||||
|
||||
@@ -166,7 +166,7 @@ void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx) {
|
||||
|
||||
LOG_D(PHY,"feptx_ofdm (TXPATH): frame %d, slot %d: txp (time %p) %d dB, txp (freq) %d dB\n",
|
||||
frame_tx,slot,txdata,dB_fixed(signal_energy((int32_t*)txdata,fp->get_samples_per_slot(
|
||||
slot,fp))),dB_fixed(signal_energy_nodc(ru->common.txdataF_BF[aa],2*slot_sizeF)));
|
||||
slot,fp))),dB_fixed(signal_energy_nodc(ru->common.txdataF_BF[aa],2*slot_sizeF)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -198,7 +198,7 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
|
||||
|
||||
//apply the OFDM symbol rotation here
|
||||
for (aa=0; aa<cfg->carrier_config.num_tx_ant.value; aa++) {
|
||||
apply_nr_rotation(fp, &gNB->common_vars.txdataF[aa][txdataF_offset], slot, 0, fp->Ncp == EXTENDED ? 12 : 14);
|
||||
apply_nr_rotation(fp, &gNB->common_vars.txdataF[aa][txdataF_offset], slot, 0, fp->Ncp == EXTENDED ? 12 : 14, NR_LINK_TYPE_DL);
|
||||
|
||||
T(T_GNB_PHY_DL_OUTPUT_SIGNAL, T_INT(0),
|
||||
T_INT(frame), T_INT(slot),
|
||||
|
||||
@@ -87,6 +87,11 @@ typedef struct {
|
||||
uint8_t xtra_byte;
|
||||
} fapiPbch_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t decoded_output[NR_POLAR_PSBCH_PAYLOAD_BITS];
|
||||
uint8_t xtra_byte;
|
||||
} fapiPsbch_t;
|
||||
|
||||
/** @addtogroup _PHY_PROCEDURES_
|
||||
* @{
|
||||
*/
|
||||
@@ -98,6 +103,28 @@ typedef struct {
|
||||
*/
|
||||
void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data);
|
||||
|
||||
/*! \brief Scheduling for UE SL TX procedures in normal slots.
|
||||
@param ue Pointer to UE variables on which to act
|
||||
@param proc Pointer to RXn-TXnp4 proc information
|
||||
@param gNB_id Local id of gNB on which to act, 0 in case of sidelink
|
||||
*/
|
||||
void phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id);
|
||||
|
||||
/*! \brief check weather if current slot in current frame is suitable for SL SSB time slot allocation.
|
||||
@param ue Pointer to UE variables on which to act
|
||||
@param frame frame number
|
||||
@param slot slot number
|
||||
*/
|
||||
bool phy_ssb_slot_allocation_sl(PHY_VARS_NR_UE *ue, int frame, int slot);
|
||||
|
||||
/*! \brief Scheduling for UE RX procedures in normal subframes.
|
||||
@param ue Pointer to UE variables on which to act
|
||||
@param proc Pointer to proc information
|
||||
@param dlsch_parallel use multithreaded dlsch processing
|
||||
@param phy_pdcch_config PDCCH Config for this slot
|
||||
@param txFifo Result fifo if PDSCH is run in parallel
|
||||
*/
|
||||
|
||||
void send_slot_ind(notifiedFIFO_t *nf, int slot);
|
||||
|
||||
void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
#endif
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
#include "LAYER2/NR_MAC_UE/mac_proto.h"
|
||||
#include "openair1/PHY/MODULATION/nr_modulation.h"
|
||||
#include "SCHED_NR_UE/pucch_uci_ue_nr.h"
|
||||
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
|
||||
|
||||
@@ -256,6 +258,99 @@ void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx)
|
||||
}
|
||||
}
|
||||
|
||||
bool phy_ssb_slot_allocation_sl(PHY_VARS_NR_UE *ue, int frame, int slot)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
|
||||
if ((frame * fp->slots_per_frame + slot) % (16 * fp->slots_per_frame) == 0) {
|
||||
ue->slss->sl_numssb_withinperiod_r16 = ue->slss->sl_numssb_withinperiod_r16_copy;
|
||||
ue->slss->sl_timeoffsetssb_r16 = frame * fp->slots_per_frame + ue->slss->sl_timeoffsetssb_r16_copy;
|
||||
}
|
||||
|
||||
if (ue->slss->sl_numssb_withinperiod_r16 > 0) {
|
||||
if (frame * fp->slots_per_frame + slot == ue->slss->sl_timeoffsetssb_r16) {
|
||||
ue->slss->sl_timeoffsetssb_r16 = ue->slss->sl_timeoffsetssb_r16 + ue->slss->sl_timeinterval_r16;
|
||||
ue->slss->sl_numssb_withinperiod_r16 = ue->slss->sl_numssb_withinperiod_r16 - 1;
|
||||
LOG_I(PHY,"*** SL-SSB slot allocation %d.%d ***\n", frame, slot);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
uint8_t gNB_id)
|
||||
{
|
||||
int slot_tx = proc->nr_slot_tx;
|
||||
int frame_tx = proc->frame_tx;
|
||||
AssertFatal(frame_tx >= 0 && frame_tx < 1024, "frame_tx %d is not in 0...1023\n",frame_tx);
|
||||
AssertFatal(slot_tx >= 0 && slot_tx < 20, "slot_tx %d is not in 0...19\n", slot_tx);
|
||||
|
||||
LOG_D(PHY,"****** start Sidelink TX-Chain for AbsSlot %d.%d ******\n", frame_tx, slot_tx);
|
||||
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
ue->tx_power_dBm[slot_tx] = -127;
|
||||
int num_samples_per_slot = ue->frame_parms.slots_per_frame * ue->frame_parms.samples_per_slot_wCP;
|
||||
for(int i = 0; i < ue->frame_parms.nb_antennas_tx; ++i) {
|
||||
AssertFatal(i < sizeof(ue->common_vars.txdataF), "Array index %d is over the Array size %lu\n", i, sizeof(ue->common_vars.txdataF));
|
||||
memset(ue->common_vars.txdataF[i], 0, sizeof(int32_t) * num_samples_per_slot);
|
||||
}
|
||||
}
|
||||
|
||||
if (ue->sync_ref && phy_ssb_slot_allocation_sl(ue, frame_tx, slot_tx)) {
|
||||
nr_sl_common_signal_procedures(ue, frame_tx, slot_tx);
|
||||
const int txdataF_offset = slot_tx * ue->frame_parms.samples_per_slot_wCP;
|
||||
LOG_D(NR_PHY, "%s() %d. slot %d txdataF_offset %d\n", __FUNCTION__, __LINE__, slot_tx, txdataF_offset);
|
||||
//ue->frame_parms.nb_prefix_samples0 = ue->is_synchronized_sl ? ue->frame_parms.nb_prefix_samples0 : ue->frame_parms.nb_prefix_samples;
|
||||
int slot_timestamp = ue->frame_parms.get_samples_slot_timestamp(slot_tx, &ue->frame_parms, 0);
|
||||
LOG_D(NR_PHY,"slot_timestamp %d\n",slot_timestamp);
|
||||
for (int aa = 0; aa < ue->frame_parms.nb_antennas_tx; aa++) {
|
||||
/* apply_nr_rotation(&ue->frame_parms,
|
||||
&ue->common_vars.txdataF[aa][txdataF_offset],
|
||||
slot_tx, 0, 1, NR_LINK_TYPE_SL); // Conducts rotation on 0th symbol*/
|
||||
PHY_ofdm_mod((int*)&ue->common_vars.txdataF[aa][txdataF_offset],
|
||||
(int*)&ue->common_vars.txdata[aa][slot_timestamp],
|
||||
ue->frame_parms.ofdm_symbol_size,
|
||||
1, // Takes IDFT of 1st symbol (first PSBCH)ue->frame_parms.nb_prefix_samples
|
||||
ue->frame_parms.nb_prefix_samples0,
|
||||
CYCLIC_PREFIX);
|
||||
/* apply_nr_rotation(&ue->frame_parms,
|
||||
&ue->common_vars.txdataF[aa][txdataF_offset],
|
||||
slot_tx, 1, 13, NR_LINK_TYPE_SL); // Conducts rotation on symbols located 1 (PSS) to 13 (guard)*/
|
||||
PHY_ofdm_mod((int*)&ue->common_vars.txdataF[aa][ue->frame_parms.ofdm_symbol_size + txdataF_offset], // Starting at PSS (in freq)
|
||||
(int*)&ue->common_vars.txdata[aa][ue->frame_parms.ofdm_symbol_size +
|
||||
ue->frame_parms.nb_prefix_samples0 + /*
|
||||
ue->frame_parms.nb_prefix_samples +*/
|
||||
slot_timestamp], // Starting output offset at CP0 + PSBCH0 + CP1
|
||||
ue->frame_parms.ofdm_symbol_size,
|
||||
13, // Takes IDFT of remaining 13 symbols (PSS to guard)... Notice the offset of the input and output above
|
||||
ue->frame_parms.nb_prefix_samples,
|
||||
CYCLIC_PREFIX);
|
||||
}
|
||||
#ifdef DEBUG_PHY_PROC
|
||||
char buffer1[ue->frame_parms.ofdm_symbol_size];
|
||||
for (int i = 0; i < 13; i++) {
|
||||
bzero(buffer1, sizeof(buffer1));
|
||||
LOG_I(NR_PHY, "%s(): %d After rotation txdataF[%d] = %s\n",
|
||||
__FUNCTION__, __LINE__, txdataF_offset + (ue->frame_parms.ofdm_symbol_size * i),
|
||||
hexdump((void *)&ue->common_vars.txdataF[0][txdataF_offset + (ue->frame_parms.ofdm_symbol_size * i)], ue->frame_parms.ofdm_symbol_size, buffer1, sizeof(buffer1)));
|
||||
}
|
||||
char buffer0[ue->frame_parms.ofdm_symbol_size];
|
||||
for (int i = 0; i < 13; i++) {
|
||||
bzero(buffer0, sizeof(buffer0));
|
||||
LOG_I(NR_PHY, "%s(): %d Time domain txdata[%d] = %s\n",
|
||||
__FUNCTION__, __LINE__, slot_timestamp + ue->frame_parms.ofdm_symbol_size * i,
|
||||
hexdump((void *)&ue->common_vars.txdata[0][slot_timestamp + ue->frame_parms.ofdm_symbol_size * i], ue->frame_parms.ofdm_symbol_size, buffer0, sizeof(buffer0)));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
LOG_D(PHY,"****** end Sidelink TX-Chain for AbsSlot %d.%d ******\n", frame_tx, slot_tx);
|
||||
}
|
||||
|
||||
void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
nr_phy_data_tx_t *phy_data) {
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#include "NR_ServingCellConfigCommon.h"
|
||||
#include "NR_ServingCellConfig.h"
|
||||
#ifndef __NR_UNITARY_DEFS__H__
|
||||
#define __NR_UNITARY_DEFS__H__
|
||||
|
||||
|
||||
@@ -191,7 +191,7 @@ int main(int argc, char **argv)
|
||||
double sigma2, sigma2_dB=10,SNR,snr0=-2.0,snr1=2.0;
|
||||
double cfo=0;
|
||||
uint8_t snr1set=0;
|
||||
int **txdata;
|
||||
c16_t **txdata;
|
||||
double **s_re,**s_im,**r_re,**r_im;
|
||||
//double iqim = 0.0;
|
||||
double ip =0.0;
|
||||
@@ -586,7 +586,7 @@ int main(int argc, char **argv)
|
||||
s_im = malloc(2*sizeof(double*));
|
||||
r_re = malloc(2*sizeof(double*));
|
||||
r_im = malloc(2*sizeof(double*));
|
||||
txdata = calloc(2,sizeof(int*));
|
||||
txdata = calloc(2, sizeof(c16_t*));
|
||||
|
||||
for (i=0; i<2; i++) {
|
||||
|
||||
@@ -596,7 +596,7 @@ int main(int argc, char **argv)
|
||||
r_re[i] = malloc16_clear(frame_length_complex_samples*sizeof(double));
|
||||
r_im[i] = malloc16_clear(frame_length_complex_samples*sizeof(double));
|
||||
printf("Allocating %d samples for txdata\n",frame_length_complex_samples);
|
||||
txdata[i] = malloc16_clear(frame_length_complex_samples*sizeof(int));
|
||||
txdata[i] = malloc16_clear(frame_length_complex_samples * sizeof(c16_t));
|
||||
}
|
||||
|
||||
if (pbch_file_fd!=NULL) {
|
||||
@@ -652,10 +652,11 @@ int main(int argc, char **argv)
|
||||
gNB->common_vars.txdataF[aa],
|
||||
slot,
|
||||
0,
|
||||
12);
|
||||
12,
|
||||
NR_LINK_TYPE_DL);
|
||||
|
||||
PHY_ofdm_mod((int *)gNB->common_vars.txdataF[aa],
|
||||
&txdata[aa][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)],
|
||||
(int *)&txdata[aa][frame_parms->get_samples_slot_timestamp(slot, frame_parms, 0)],
|
||||
frame_parms->ofdm_symbol_size,
|
||||
12,
|
||||
frame_parms->nb_prefix_samples,
|
||||
@@ -665,7 +666,8 @@ int main(int argc, char **argv)
|
||||
gNB->common_vars.txdataF[aa],
|
||||
slot,
|
||||
0,
|
||||
14);
|
||||
14,
|
||||
NR_LINK_TYPE_DL);
|
||||
|
||||
/*nr_normal_prefix_mod(gNB->common_vars.txdataF[aa],
|
||||
&txdata[aa][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)],
|
||||
@@ -726,8 +728,8 @@ int main(int argc, char **argv)
|
||||
|
||||
for (i=0; i<frame_length_complex_samples; i++) {
|
||||
for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
|
||||
r_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]);
|
||||
r_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]);
|
||||
r_re[aa][i] = (double)txdata[aa][i].r;
|
||||
r_im[aa][i] = (double)txdata[aa][i].i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -761,8 +763,8 @@ int main(int argc, char **argv)
|
||||
|
||||
for (i=0; i<frame_length_complex_samples; i++) {
|
||||
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
||||
((short*) UE->common_vars.rxdata[aa])[2*i] = (short) ((r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0)));
|
||||
((short*) UE->common_vars.rxdata[aa])[2*i+1] = (short) ((r_im[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0)));
|
||||
UE->common_vars.rxdata[aa][i].r = (short)(r_re[aa][i] + sqrt(sigma2 / 2) * gaussdouble(0.0, 1.0));
|
||||
UE->common_vars.rxdata[aa][i].i = (short)(r_im[aa][i] + sqrt(sigma2 / 2) * gaussdouble(0.0, 1.0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,10 @@ void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) { }
|
||||
|
||||
/* temporary dummy implem of get_softmodem_optmask, till basic simulators implemented as device */
|
||||
uint64_t get_softmodem_optmask(void) {return 0;}
|
||||
softmodem_params_t *get_softmodem_params(void) {return 0;}
|
||||
static softmodem_params_t softmodem_params;
|
||||
softmodem_params_t *get_softmodem_params(void) {
|
||||
return &softmodem_params;
|
||||
}
|
||||
//Fixme: Uniq dirty DU instance, by global var, datamodel need better management
|
||||
instance_t DUuniqInstance=0;
|
||||
instance_t CUuniqInstance=0;
|
||||
@@ -138,13 +141,12 @@ void processSlotTX(void *arg) {}
|
||||
int NB_UE_INST = 1;
|
||||
|
||||
int main(int argc, char **argv){
|
||||
|
||||
get_softmodem_params()->sl_mode = 0;
|
||||
char c;
|
||||
|
||||
double sigma2, sigma2_dB = 0, SNR, snr0 = -2.0, snr1 = 0.0, ue_speed0 = 0.0, ue_speed1 = 0.0;
|
||||
double **s_re, **s_im, **r_re, **r_im, iqim = 0.0, delay_avg = 0, ue_speed = 0, fs=-1, bw;
|
||||
int i, l, aa, aarx, trial, n_frames = 1, prach_start, rx_prach_start; //, ntrials=1;
|
||||
c16_t **txdata;
|
||||
int N_RB_UL = 106, delay = 0, NCS_config = 13, rootSequenceIndex = 1, threequarter_fs = 0, mu = 1, fd_occasion = 0, loglvl = OAILOG_INFO, numRA = 0, prachStartSymbol = 0;
|
||||
uint8_t snr1set = 0, ue_speed1set = 0, transmission_mode = 1, n_tx = 1, n_rx = 1, awgn_flag = 0, msg1_frequencystart = 0, num_prach_fd_occasions = 1, prach_format=0;
|
||||
uint8_t config_index = 98, prach_sequence_length = 1, restrictedSetConfig = 0, N_dur, N_t_slot, start_symbol;
|
||||
@@ -596,7 +598,7 @@ int main(int argc, char **argv){
|
||||
|
||||
ue_prach_pdu = &UE->prach_vars[0]->prach_pdu;
|
||||
ue_prach_config = &UE->nrUE_config.prach_config;
|
||||
txdata = UE->common_vars.txdata;
|
||||
c16_t **txdata = UE->common_vars.txdata;
|
||||
|
||||
UE->prach_vars[0]->amp = AMP;
|
||||
ue_prach_pdu->root_seq_id = rootSequenceIndex;
|
||||
|
||||
645
openair1/SIMULATION/NR_PHY/psbchsim.c
Normal file
645
openair1/SIMULATION/NR_PHY/psbchsim.c
Normal file
@@ -0,0 +1,645 @@
|
||||
/*
|
||||
* 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 <string.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/load_module_shlib.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "PHY/types.h"
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "openair1/PHY/NR_REFSIG/refsig_defs_ue.h"
|
||||
#include "PHY/MODULATION/modulation_eNB.h"
|
||||
#include "PHY/MODULATION/modulation_UE.h"
|
||||
#include "PHY/MODULATION/nr_modulation.h"
|
||||
#include "PHY/INIT/nr_phy_init.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "PHY/NR_UE_ESTIMATION/nr_estimation.h"
|
||||
#include "PHY/phy_vars.h"
|
||||
#include "SCHED_NR/sched_nr.h"
|
||||
#include "openair1/SIMULATION/TOOLS/sim.h"
|
||||
#include "openair1/SIMULATION/RF/rf.h"
|
||||
#include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h"
|
||||
#include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c"
|
||||
#include "openair1/PHY/MODULATION/nr_modulation.h"
|
||||
#include "openair1/PHY/NR_REFSIG/pss_nr.h"
|
||||
#include <executables/softmodem-common.h>
|
||||
#include <executables/nr-uesoftmodem.h>
|
||||
#include "openair1/SCHED_NR_UE/defs.h"
|
||||
|
||||
//#define DEBUG_NR_PSBCHSIM
|
||||
double cpuf;
|
||||
uint16_t NB_UE_INST = 1;
|
||||
openair0_config_t openair0_cfg[MAX_CARDS];
|
||||
uint8_t const nr_rv_round_map[4] = {0, 2, 3, 1};
|
||||
|
||||
uint64_t get_softmodem_optmask(void) {return 0;}
|
||||
static softmodem_params_t softmodem_params;
|
||||
softmodem_params_t *get_softmodem_params(void) {
|
||||
return &softmodem_params;
|
||||
}
|
||||
|
||||
nrUE_params_t nrUE_params={0};
|
||||
nrUE_params_t *get_nrUE_params(void) {
|
||||
return &nrUE_params;
|
||||
}
|
||||
|
||||
void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {}
|
||||
|
||||
bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
NR_UE_DLSCH_t dlsch[2],
|
||||
int16_t* llr[2]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
NR_UE_DLSCH_t dlsch[2],
|
||||
int16_t *llr[2],
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int32_t pdcch_est_size,
|
||||
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
|
||||
nr_phy_data_t *phy_data,
|
||||
int n_ss,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind,
|
||||
fapi_nr_dci_indication_t *dci_ind,
|
||||
fapi_nr_rx_indication_t *rx_ind,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
void *phy_data) {}
|
||||
void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
|
||||
uint8_t pdu_type,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
NR_UE_DLSCH_t *dlsch0,
|
||||
NR_UE_DLSCH_t *dlsch1,
|
||||
uint16_t n_pdus,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
void *typeSpecific,
|
||||
uint8_t *b) {}
|
||||
|
||||
double cfo = 0;
|
||||
double snr0 =- 2.0;
|
||||
double snr1 = 2.0;
|
||||
uint8_t snr1set = 0;
|
||||
int n_trials = 1;
|
||||
uint8_t n_tx = 1;
|
||||
uint8_t n_rx = 1;
|
||||
uint16_t Nid_cell = 0;
|
||||
uint16_t Nid_SL = 336 + 10;
|
||||
uint64_t SSB_positions = 0x01;
|
||||
int ssb_subcarrier_offset = 0;
|
||||
FILE *input_fd = NULL;
|
||||
SCM_t channel_model = AWGN;
|
||||
int N_RB_DL = 273;
|
||||
int mu = 1;
|
||||
unsigned char psbch_phase = 0;
|
||||
int run_initial_sync = 0;
|
||||
int loglvl = OAILOG_WARNING;
|
||||
float target_error_rate = 0.01;
|
||||
int seed = 0;
|
||||
|
||||
void free_psbchsim_members(PHY_VARS_NR_UE *UE,
|
||||
double **s_re,
|
||||
double **s_im,
|
||||
double **r_re,
|
||||
double **r_im,
|
||||
c16_t **txdata,
|
||||
FILE *input_fd)
|
||||
{
|
||||
term_nr_ue_signal(UE, 1);
|
||||
if (UE->slss) free(UE->slss);
|
||||
if (UE) free(UE);
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (s_re[i]) free(s_re[i]);
|
||||
if (s_im[i]) free(s_im[i]);
|
||||
if (r_re[i]) free(r_re[i]);
|
||||
if (r_im[i]) free(r_im[i]);
|
||||
if (txdata[i]) free(txdata[i]);
|
||||
}
|
||||
if (s_re) free(s_re);
|
||||
if (s_im) free(s_im);
|
||||
if (r_re) free(r_re);
|
||||
if (r_im) free(r_im);
|
||||
if (txdata) free(txdata);
|
||||
|
||||
if (input_fd)
|
||||
fclose(input_fd);
|
||||
|
||||
loader_reset();
|
||||
logTerm();
|
||||
}
|
||||
|
||||
void nr_phy_config_request_sim_psbchsim(PHY_VARS_NR_UE *ue,
|
||||
int N_RB_DL,
|
||||
int N_RB_UL,
|
||||
int mu,
|
||||
int Nid_SL,
|
||||
uint64_t position_in_burst)
|
||||
{
|
||||
uint64_t rev_burst = 0;
|
||||
for (int i = 0; i < 64; i++)
|
||||
rev_burst |= (((SSB_positions >> (63-i))&0x01) << i);
|
||||
|
||||
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
fapi_nr_config_request_t *nrUE_config = &ue->nrUE_config;
|
||||
nrUE_config->cell_config.phy_cell_id = Nid_SL; // TODO
|
||||
nrUE_config->ssb_config.scs_common = mu;
|
||||
nrUE_config->ssb_table.ssb_subcarrier_offset = 0;
|
||||
nrUE_config->ssb_table.ssb_offset_point_a = 0;
|
||||
nrUE_config->ssb_table.ssb_mask_list[1].ssb_mask = (rev_burst)&(0xFFFFFFFF);
|
||||
nrUE_config->ssb_table.ssb_mask_list[0].ssb_mask = (rev_burst>>32)&(0xFFFFFFFF);
|
||||
nrUE_config->cell_config.frame_duplex_type = TDD;
|
||||
nrUE_config->ssb_table.ssb_period = 1; //10ms
|
||||
nrUE_config->carrier_config.dl_grid_size[mu] = N_RB_DL;
|
||||
nrUE_config->carrier_config.ul_grid_size[mu] = N_RB_UL;
|
||||
nrUE_config->carrier_config.num_tx_ant = fp->nb_antennas_tx;
|
||||
nrUE_config->carrier_config.num_rx_ant = fp->nb_antennas_rx;
|
||||
nrUE_config->tdd_table.tdd_period = 0;
|
||||
nrUE_config->carrier_config.dl_frequency = 450000;
|
||||
nrUE_config->carrier_config.uplink_frequency = 450000;
|
||||
nrUE_config->carrier_config.sl_frequency = 450000;
|
||||
fp->dl_CarrierFreq = 2600000000;
|
||||
fp->ul_CarrierFreq = 2600000000;
|
||||
fp->nb_antennas_tx = n_tx;
|
||||
fp->nb_antennas_rx = n_rx;
|
||||
fp->nb_antenna_ports_gNB = n_tx;
|
||||
fp->N_RB_DL = N_RB_DL;
|
||||
fp->Nid_cell = Nid_cell;
|
||||
fp->Nid_SL = Nid_SL;
|
||||
fp->nushift = 0; //No nushift in SL
|
||||
fp->ssb_type = nr_ssb_type_C; //Note: case c for NR SL???
|
||||
fp->freq_range = mu < 2 ? nr_FR1 : nr_FR2;
|
||||
fp->nr_band = 38; //Note: NR SL uses for n38 and n47
|
||||
fp->threequarter_fs = 0;
|
||||
fp->ofdm_offset_divisor = UINT_MAX;
|
||||
fp->first_carrier_offset = 0;
|
||||
fp->ssb_start_subcarrier = 12 * ue->nrUE_config.ssb_table.ssb_offset_point_a + ssb_subcarrier_offset;
|
||||
int bw_index = get_supported_band_index(mu, fp->nr_band, N_RB_DL);
|
||||
nrUE_config->carrier_config.dl_bandwidth = get_supported_bw_mhz(fp->nr_band > 256 ? FR2 : FR1, bw_index);
|
||||
nr_init_frame_parms_ue(fp, nrUE_config, fp->nr_band);
|
||||
init_timeshift_rotation(fp);
|
||||
init_symbol_rotation(fp);
|
||||
LOG_I(NR_PHY, "nrUE configured\n");
|
||||
}
|
||||
|
||||
|
||||
static void get_sim_cl_opts(int argc, char **argv)
|
||||
{
|
||||
char c;
|
||||
while ((c = getopt(argc, argv, "F:g:hIL:m:M:n:N:o:O:p:P:r:R:s:S:x:y:z:")) != -1) {
|
||||
switch (c) {
|
||||
case 'F':
|
||||
input_fd = fopen(optarg, "r");
|
||||
if (input_fd == NULL) {
|
||||
printf("Problem with filename %s. Exiting.\n", optarg);
|
||||
exit(-1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
switch((char)*optarg) {
|
||||
case 'A':
|
||||
channel_model=SCM_A;
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
channel_model=SCM_B;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
channel_model=SCM_C;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
channel_model=SCM_D;
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
channel_model=EPA;
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
channel_model=EVA;
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
channel_model=ETU;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Unsupported channel model! Exiting.\n");
|
||||
exit(-1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
run_initial_sync = 1;
|
||||
target_error_rate = 0.1;
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
loglvl = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
mu = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
SSB_positions = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
n_trials = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
Nid_cell = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
ssb_subcarrier_offset = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
cfo = atof(optarg);
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
psbch_phase = atoi(optarg);
|
||||
if (psbch_phase > 3)
|
||||
printf("Illegal PSBCH phase (0-3) got %d\n", psbch_phase);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
seed = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
N_RB_DL = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
snr0 = atof(optarg);
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
snr1 = atof(optarg);
|
||||
snr1set = 1;
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
n_tx = atoi(optarg);
|
||||
if ((n_tx == 0) || (n_tx > 2)) {
|
||||
printf("Unsupported number of TX antennas %d. Exiting.\n", n_tx);
|
||||
exit(-1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
n_rx = atoi(optarg);
|
||||
if ((n_rx == 0) || (n_rx > 2)) {
|
||||
printf("Unsupported number of RX antennas %d. Exiting.\n", n_rx);
|
||||
exit(-1);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
case 'h':
|
||||
printf("%s -F input_filename -g channel_mod -h(elp) -I(nitial sync) -L log_lvl -n n_frames -M SSBs -n frames -N cell_id -o FO -P phase -r seed -R RBs -s snr0 -S snr1 -y TXant -z RXant\n",
|
||||
argv[0]);
|
||||
printf("-F Input filename (.txt format) for RX conformance testing\n");
|
||||
printf("-g [A,B,C,D,E,F,G] Use 3GPP SCM (A,B,C,D) or 36-101 (E-EPA,F-EVA,G-ETU) models (ignores delay spread and Ricean factor)\n");
|
||||
printf("-h This message\n");
|
||||
printf("-I run initial sync with target error rate 0.1\n");
|
||||
printf("-L set the log level (-1 disable, 0 error, 1 warning, 2 info, 3 debug, 4 trace)\n");
|
||||
printf("-m Numerology index\n");
|
||||
printf("-M Multiple SSB positions in burst\n");
|
||||
printf("-n Number of frames to simulate\n");
|
||||
printf("-N Nid_cell\n");
|
||||
printf("-o Carrier frequency offset in Hz\n");
|
||||
printf("-O SSB subcarrier offset\n");
|
||||
printf("-p Conducting PSS and SSS testing\n");
|
||||
printf("-P PSBCH phase, allowed values 0-3\n");
|
||||
printf("-r set the random number generator seed (default: 0 = current time)\n");
|
||||
printf("-R N_RB_DL\n");
|
||||
printf("-s Starting SNR, runs from SNR0 to SNR0 + 10 dB if not -S given. If -n 1, then just SNR is simulated\n");
|
||||
printf("-S Ending SNR, runs from SNR0 to SNR1\n");
|
||||
printf("-x Transmission mode (1,2,6 for the moment)\n");
|
||||
printf("-y Number of TX antennas used in eNB\n");
|
||||
printf("-z Number of RX antennas used in UE\n");
|
||||
exit (-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
get_softmodem_params()->sa = 1;
|
||||
get_softmodem_params()->sl_mode = 2;
|
||||
if (load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY) == 0) {
|
||||
exit_fun("[NR_PSBCHSIM] Error, configuration module init failed\n");
|
||||
}
|
||||
get_sim_cl_opts(argc, argv);
|
||||
randominit(seed);
|
||||
logInit();
|
||||
set_glog(loglvl);
|
||||
|
||||
PHY_VARS_NR_UE *UE = malloc16_clear(sizeof(*UE));
|
||||
|
||||
printf("Initializing UE for mu %d, N_RB_DL %d\n", mu, N_RB_DL);
|
||||
snr1 = snr1set == 0 ? snr0 + 10 : snr1;
|
||||
nr_phy_config_request_sim_psbchsim(UE, N_RB_DL, N_RB_DL, mu, Nid_SL, SSB_positions);
|
||||
|
||||
double fs = 0;
|
||||
double scs = 30000;
|
||||
switch (mu) {
|
||||
case 1:
|
||||
scs = 30000;
|
||||
UE->frame_parms.Lmax = 1;
|
||||
if (N_RB_DL == 217) {
|
||||
fs = 122.88e6;
|
||||
}
|
||||
else if (N_RB_DL == 245) {
|
||||
fs = 122.88e6;
|
||||
}
|
||||
else if (N_RB_DL == 273) {
|
||||
fs = 122.88e6;
|
||||
}
|
||||
else if (N_RB_DL == 106) {
|
||||
fs = 61.44e6;
|
||||
}
|
||||
else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL);
|
||||
break;
|
||||
case 3:
|
||||
UE->frame_parms.Lmax = 64;
|
||||
scs = 120000;
|
||||
if (N_RB_DL == 66) {
|
||||
fs = 122.88e6;
|
||||
}
|
||||
else AssertFatal(1 == 0,"Unsupported numerology for mu %d, N_RB %d\n", mu, N_RB_DL);
|
||||
break;
|
||||
}
|
||||
|
||||
int frame_length_complex_samples = UE->frame_parms.samples_per_subframe * NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
|
||||
double **s_re = malloc(2 * sizeof(double*));
|
||||
double **s_im = malloc(2 * sizeof(double*));
|
||||
double **r_re = malloc(2 * sizeof(double*));
|
||||
double **r_im = malloc(2 * sizeof(double*));
|
||||
c16_t **txdata = calloc(2, sizeof(c16_t*));
|
||||
for (int i = 0; i < 2; i++) {
|
||||
s_re[i] = malloc16_clear(frame_length_complex_samples * sizeof(double));
|
||||
s_im[i] = malloc16_clear(frame_length_complex_samples * sizeof(double));
|
||||
r_re[i] = malloc16_clear(frame_length_complex_samples * sizeof(double));
|
||||
r_im[i] = malloc16_clear(frame_length_complex_samples * sizeof(double));
|
||||
printf("Allocating %d samples for txdata\n", frame_length_complex_samples);
|
||||
txdata[i] = malloc16_clear(2 * frame_length_complex_samples * sizeof(c16_t));
|
||||
}
|
||||
|
||||
UE->slss = calloc(1, sizeof(*UE->slss));
|
||||
int len = sizeof(UE->slss->sl_mib) / sizeof(UE->slss->sl_mib[0]);
|
||||
for (int i = 0; i < len; i++) {
|
||||
UE->slss->sl_mib[i] = 0;
|
||||
}
|
||||
UE->slss->sl_mib_length = 32;
|
||||
UE->slss->sl_numssb_withinperiod_r16 = 1;
|
||||
UE->slss->sl_timeinterval_r16 = 0;
|
||||
UE->slss->sl_timeoffsetssb_r16 = 0;
|
||||
UE->slss->slss_id = Nid_SL;
|
||||
UE->target_Nid_cell = -1;
|
||||
UE->is_synchronized_sl = run_initial_sync ? 0 : 1;
|
||||
UE->UE_fo_compensation = (cfo / scs) != 0.0 ? 1 : 0; // if a frequency offset is set then perform fo estimation and compensation
|
||||
|
||||
if (init_nr_ue_signal(UE, 1) != 0) {
|
||||
printf("Error at UE NR initialisation\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
nr_gold_psbch(UE);
|
||||
processingData_L1tx_t msgDataTx;
|
||||
AssertFatal(UE->frame_parms.Lmax < sizeof(msgDataTx.ssb) / sizeof(msgDataTx.ssb[0]), "Invalid index %d\n",
|
||||
UE->frame_parms.Lmax);
|
||||
AssertFatal(UE->frame_parms.nb_antennas_tx < 2, "Invalid index %d\n", UE->frame_parms.nb_antennas_tx);
|
||||
for (int i = 0; i < UE->frame_parms.Lmax; i++) {
|
||||
if((SSB_positions >> i) & 0x01) {
|
||||
for (int aa = 0; aa < UE->frame_parms.nb_antennas_tx; aa++)
|
||||
memset(UE->common_vars.txdataF[aa], 0, sizeof(*UE->common_vars.txdataF[aa]));
|
||||
|
||||
int frame = 0;
|
||||
int ssb_start_symbol_abs = (UE->slss->sl_timeoffsetssb_r16 + UE->slss->sl_timeinterval_r16 * i) * UE->frame_parms.symbols_per_slot;
|
||||
int slot = ssb_start_symbol_abs / 14;
|
||||
nr_sl_common_signal_procedures(UE, frame, slot);
|
||||
|
||||
const int sc_offset = UE->frame_parms.freq_range == nr_FR1 ? ssb_subcarrier_offset << mu : ssb_subcarrier_offset;
|
||||
const int prb_offset = UE->frame_parms.freq_range == nr_FR1 ? UE->nrUE_config.ssb_table.ssb_offset_point_a<<mu : UE->nrUE_config.ssb_table.ssb_offset_point_a << (mu - 2);
|
||||
msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.bchPayload = UE->psbch_vars[0]->psbch_a;
|
||||
msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = i;
|
||||
msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset = sc_offset;
|
||||
msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA = prb_offset;
|
||||
|
||||
int slot_timestamp = UE->frame_parms.get_samples_slot_timestamp(slot, &UE->frame_parms, 0);
|
||||
// UE->frame_parms.nb_prefix_samples0 = UE->is_synchronized_sl ? UE->frame_parms.nb_prefix_samples0 : UE->frame_parms.nb_prefix_samples;
|
||||
int max_symbol_size = slot_timestamp + UE->frame_parms.nb_prefix_samples0 + UE->frame_parms.ofdm_symbol_size;
|
||||
AssertFatal(max_symbol_size < frame_length_complex_samples, "Invalid index %d\n", max_symbol_size);
|
||||
for (int aa = 0; aa < UE->frame_parms.nb_antennas_tx; aa++) {
|
||||
apply_nr_rotation(&UE->frame_parms,
|
||||
UE->common_vars.txdataF[aa],
|
||||
slot, 0, 1, NR_LINK_TYPE_SL); // Conducts rotation on 0th symbol
|
||||
LOG_I(NR_PHY,"slot %d, symbol 0, nb_prefix_samples0 %d\n",slot,UE->frame_parms.nb_prefix_samples0);
|
||||
PHY_ofdm_mod((int*)UE->common_vars.txdataF[aa],
|
||||
(int*)&txdata[aa][slot_timestamp],
|
||||
UE->frame_parms.ofdm_symbol_size,
|
||||
1, // Takes IDFT of 1st symbol (first PSBCH)
|
||||
UE->frame_parms.nb_prefix_samples0,
|
||||
CYCLIC_PREFIX);
|
||||
|
||||
apply_nr_rotation(&UE->frame_parms,
|
||||
UE->common_vars.txdataF[aa],
|
||||
slot, 1, 13, NR_LINK_TYPE_SL); // Conducts rotation on symbols located 1 (PSS) to 13 (guard)
|
||||
|
||||
LOG_I(NR_PHY,"slot %d, symbols 1...13, nb_prefix_samples %d\n",slot,UE->frame_parms.nb_prefix_samples);
|
||||
PHY_ofdm_mod((int*)&UE->common_vars.txdataF[aa][UE->frame_parms.ofdm_symbol_size], // Starting at PSS (in freq)
|
||||
(int*)&txdata[aa][UE->frame_parms.ofdm_symbol_size +
|
||||
UE->frame_parms.nb_prefix_samples0 /*+
|
||||
UE->frame_parms.nb_prefix_samples*/], // Starting output offset at CP0 + PSBCH0 + CP1
|
||||
UE->frame_parms.ofdm_symbol_size,
|
||||
13, // Takes IDFT of remaining 13 symbols (PSS to guard)... Notice the offset of the input and output above
|
||||
UE->frame_parms.nb_prefix_samples,
|
||||
CYCLIC_PREFIX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char buffer[1024];
|
||||
printf("txdataF[0] = %s\n", hexdump(UE->common_vars.txdataF[0], sizeof(UE->common_vars.txdataF[0]), buffer, sizeof(buffer)));
|
||||
if (UE->frame_parms.nb_antennas_tx > 1)
|
||||
printf("txdataF[1] = %s\n", hexdump(UE->common_vars.txdataF[1], sizeof(UE->common_vars.txdataF[1]), buffer, sizeof(buffer)));
|
||||
|
||||
printf("txdata[0] = %s\n", hexdump(txdata[0], sizeof(txdata[0]), buffer, sizeof(buffer)));
|
||||
if (UE->frame_parms.nb_antennas_tx > 1)
|
||||
printf("txdata[0] = %s\n", hexdump(txdata[1], sizeof(txdata[1]), buffer, sizeof(buffer)));
|
||||
|
||||
AssertFatal((((frame_length_complex_samples - 1) << 1) + 1) < 2 * frame_length_complex_samples,
|
||||
"Invalid index %d >= %d\n", (((frame_length_complex_samples - 1)<< 1) + 1), 2 * frame_length_complex_samples);
|
||||
int n_errors = 0;
|
||||
int exitsim =0;
|
||||
for (double SNR = snr0; SNR < snr1; SNR += 0.2) {
|
||||
n_errors = 0;
|
||||
int n_errors_payload = 0;
|
||||
|
||||
for (int trial = 0; trial < n_trials; trial++) {
|
||||
for (int i = 0; i < frame_length_complex_samples; i++) {
|
||||
for (int aa = 0; aa < UE->frame_parms.nb_antennas_tx; aa++) {
|
||||
r_re[aa][i] = ((double)txdata[aa][i].r);
|
||||
r_im[aa][i] = ((double)txdata[aa][i].i);
|
||||
}
|
||||
}
|
||||
|
||||
//AWGN
|
||||
double ip = 0.0;
|
||||
if ((cfo / scs) != 0.0) {
|
||||
rf_rx(r_re, // real part of txdata
|
||||
r_im, // imag part of txdata
|
||||
NULL, // interference real part
|
||||
NULL, // interference imag part
|
||||
0, // interference power
|
||||
UE->frame_parms.nb_antennas_rx, // number of rx antennas
|
||||
frame_length_complex_samples, // number of samples in frame
|
||||
1.0e9/fs, //sampling time (ns)
|
||||
cfo, // frequency offset in Hz
|
||||
0.0, // drift (not implemented)
|
||||
0.0, // noise figure (not implemented)
|
||||
0.0, // rx gain in dB ?
|
||||
200, // 3rd order non-linearity in dB ?
|
||||
&ip, // initial phase
|
||||
30.0e3, // phase noise cutoff in kHz
|
||||
-500.0, // phase noise amplitude in dBc
|
||||
0.0, // IQ imbalance (dB),
|
||||
0.0); // IQ phase imbalance (rad)
|
||||
}
|
||||
|
||||
for (int i = 0; i < frame_length_complex_samples; i++) {
|
||||
double sigma2_dB = 20 * log10((double)AMP / 4) - SNR;
|
||||
double sigma2 = pow(10, sigma2_dB / 10);
|
||||
for (int aa = 0; aa < UE->frame_parms.nb_antennas_rx; aa++) {
|
||||
UE->common_vars.rxdata[aa][i].r = (short) (r_re[aa][i] + sqrt(sigma2 / 2) * gaussdouble(0.0,1.0));
|
||||
UE->common_vars.rxdata[aa][i].i = (short) (r_im[aa][i] + sqrt(sigma2 / 2) * gaussdouble(0.0,1.0));
|
||||
}
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
int n_frames = 1;
|
||||
if (UE->is_synchronized_sl == 0) {
|
||||
UE_nr_rxtx_proc_t proc = {0};
|
||||
LOG_I(NR_PHY,"Running initial synch\n");
|
||||
ret = nr_sl_initial_sync(&proc, UE, n_frames);
|
||||
if (ret != 0) {
|
||||
n_errors++;
|
||||
}
|
||||
} else {
|
||||
LOG_I(NR_PHY,"Already synched, running PSBCH receiver directly\n");
|
||||
UE_nr_rxtx_proc_t proc = {0};
|
||||
UE->rx_offset_sl = 0;
|
||||
uint8_t ssb_index = 0;
|
||||
const int estimateSz = 7 * 2 * sizeof(int) * UE->frame_parms.ofdm_symbol_size;
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates[UE->frame_parms.nb_antennas_rx][estimateSz];
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_time[UE->frame_parms.nb_antennas_rx][estimateSz];
|
||||
while (!((SSB_positions >> ssb_index) & 0x01)) {
|
||||
ssb_index++; // to select the first transmitted ssb
|
||||
}
|
||||
UE->symbol_offset = (UE->slss->sl_timeoffsetssb_r16 + UE->slss->sl_timeinterval_r16 * ssb_index) * UE->frame_parms.symbols_per_slot;
|
||||
uint8_t n_hf = 0;
|
||||
int ssb_slot = (UE->symbol_offset / 14) + (n_hf * (UE->frame_parms.slots_per_frame >> 1));
|
||||
const uint32_t rxdataF_sz = UE->frame_parms.samples_per_slot_wCP;
|
||||
__attribute__ ((aligned(32))) c16_t rxdataF[UE->frame_parms.nb_antennas_rx][rxdataF_sz];
|
||||
for (int i = UE->symbol_offset; i < UE->symbol_offset + 13; i++) {
|
||||
nr_slot_fep(UE, &proc, i % UE->frame_parms.symbols_per_slot, rxdataF);
|
||||
for (int aa=0;aa<UE->frame_parms.nb_antennas_rx;aa++)
|
||||
memcpy(UE->common_vars.rxdataF[aa],rxdataF,4*rxdataF_sz);
|
||||
nr_psbch_channel_estimation(UE, estimateSz, dl_ch_estimates, dl_ch_estimates_time, &proc,
|
||||
0, ssb_slot, i % UE->frame_parms.symbols_per_slot,
|
||||
i - (UE->symbol_offset), ssb_index % 8, n_hf);
|
||||
if (i==0) i=4;
|
||||
}
|
||||
fapiPsbch_t result;
|
||||
NR_UE_PDCCH_CONFIG phy_pdcch_config = {0};
|
||||
/* Side link rx PSBCH */
|
||||
ret = 0;
|
||||
ret = nr_rx_psbch(UE,
|
||||
&proc,
|
||||
estimateSz,
|
||||
dl_ch_estimates,
|
||||
UE->psbch_vars[0],
|
||||
&UE->frame_parms,
|
||||
0,
|
||||
ssb_index % 8,
|
||||
SISO,
|
||||
&phy_pdcch_config,
|
||||
&result);
|
||||
|
||||
if (ret == 0) {
|
||||
int payload_ret = 0;
|
||||
for (int i = 0; i < NR_POLAR_PSBCH_PAYLOAD_BITS >> 3; i++) {
|
||||
LOG_I(NR_PHY,"result.decoded_output[i] %d, msgDataTx.ssb[ssb_index].ssb_pdu.ssb_pdu_rel15.bchPayload %d,\n",
|
||||
result.decoded_output[i], ((msgDataTx.ssb[ssb_index].ssb_pdu.ssb_pdu_rel15.bchPayload >> (8 * (3-i))) & 0xff));
|
||||
payload_ret += (result.decoded_output[i] == ((msgDataTx.ssb[ssb_index].ssb_pdu.ssb_pdu_rel15.bchPayload >> (8 * (3-i))) & 0xff));
|
||||
}
|
||||
if (payload_ret != (NR_POLAR_PSBCH_PAYLOAD_BITS >> 3))
|
||||
n_errors_payload++;
|
||||
}
|
||||
if (ret != 0) {
|
||||
n_errors++;
|
||||
}
|
||||
}
|
||||
} //noise trials
|
||||
printf("SNR %f: trials %d, n_errors_crc = %d, n_errors_payload %d\n", SNR, n_trials, n_errors, n_errors_payload);
|
||||
if (((float)n_errors / (float)n_trials <= target_error_rate) && (n_errors_payload == 0)) {
|
||||
printf("PSBCH test OK\n");
|
||||
exitsim=1;
|
||||
break;
|
||||
}
|
||||
if (exitsim == 1) break;
|
||||
} // NSR
|
||||
|
||||
free_psbchsim_members(UE, s_re, s_im, r_re, r_im, txdata, input_fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
|
||||
THREAD_STRUCT thread_struct;
|
||||
PHY_VARS_gNB *gNB;
|
||||
@@ -67,7 +68,10 @@ const short conjugate2[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1};
|
||||
PHY_VARS_NR_UE * PHY_vars_UE_g[1][1]={{NULL}};
|
||||
|
||||
uint64_t get_softmodem_optmask(void) {return 0;}
|
||||
softmodem_params_t *get_softmodem_params(void) {return 0;}
|
||||
static softmodem_params_t softmodem_params;
|
||||
softmodem_params_t *get_softmodem_params(void) {
|
||||
return &softmodem_params;
|
||||
}
|
||||
|
||||
void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {}
|
||||
NR_IF_Module_t *NR_IF_Module_init(int Mod_id) { return (NULL); }
|
||||
|
||||
@@ -1278,7 +1278,8 @@ int main(int argc, char **argv)
|
||||
gNB->common_vars.rxdataF[aa],
|
||||
slot,
|
||||
0,
|
||||
gNB->frame_parms.Ncp == EXTENDED ? 12 : 14);
|
||||
gNB->frame_parms.Ncp == EXTENDED ? 12 : 14,
|
||||
NR_LINK_TYPE_UL);
|
||||
}
|
||||
|
||||
ul_proc_error = phy_procedures_gNB_uespec_RX(gNB, frame, slot);
|
||||
|
||||
@@ -220,15 +220,16 @@ void __attribute__ ((no_sanitize_address)) multipath_channel(channel_desc_t *des
|
||||
rx_tmp.r += (tx.r * chan[l].r) - (tx.i * chan[l].i);
|
||||
rx_tmp.i += (tx.i * chan[l].r) + (tx.r * chan[l].i);
|
||||
}
|
||||
#if 0
|
||||
#if 0 // Failing compilation on Ubuntu 16.04
|
||||
if (i==0 && log_channel == 1) {
|
||||
printf("channel[%d][%d][%d] = %f dB \t(%e, %e)\n",
|
||||
ii, j, l, 10 * log10(pow(chan[l].r, 2.0) + pow(chan[l].i, 2.0)), chan[l].r, chan[l].i);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
} //l
|
||||
} // j
|
||||
#if 0
|
||||
|
||||
#if 0 // Failing compilation on Ubuntu 16.04
|
||||
if (desc->max_Doppler != 0.0)
|
||||
rx_tmp = cdMul(rx_tmp, cexp_doppler[i]);
|
||||
#endif
|
||||
|
||||
@@ -451,6 +451,7 @@ typedef struct {
|
||||
/*!\brief LCID of Carrier component activation/deactivation */
|
||||
#define CC_ACT_DEACT 27
|
||||
//TTN (for D2D)
|
||||
#define MIBSLCH 8
|
||||
#define SL_DISCOVERY 8 //LCID (fake)
|
||||
#define MAX_NUM_DEST 10
|
||||
|
||||
|
||||
@@ -823,3 +823,88 @@ void nr_rrc_mac_config_req_scg(module_id_t module_id,
|
||||
// Setup the SSB to Rach Occasions mapping according to the config
|
||||
build_ssb_to_ro_map(mac);
|
||||
}
|
||||
void print_sl_preconf_params_mac(const NR_SL_PreconfigurationNR_r16_t* sl_preconfigurations,
|
||||
const NR_SL_FreqConfigCommon_r16_t* freq_conf_cmn)
|
||||
{
|
||||
LOG_D(NR_MAC, "sl_OffsetDFN: %lu\n", *(sl_preconfigurations->sidelinkPreconfigNR_r16.sl_OffsetDFN_r16)); // Integer (1 ..1000)
|
||||
LOG_D(NR_MAC, "sl_NumSSB_WithinPeriod: %lu\n", *(freq_conf_cmn->sl_SyncConfigList_r16->list.array[0]->sl_SSB_TimeAllocation1_r16->sl_NumSSB_WithinPeriod_r16));
|
||||
LOG_D(NR_MAC, "sl_TimeOffsetSSB: %lu\n", *(freq_conf_cmn->sl_SyncConfigList_r16->list.array[0]->sl_SSB_TimeAllocation1_r16->sl_TimeOffsetSSB_r16));
|
||||
LOG_D(NR_MAC, "sl_TimeInterval: %lu\n", *(freq_conf_cmn->sl_SyncConfigList_r16->list.array[0]->sl_SSB_TimeAllocation1_r16->sl_TimeInterval_r16));
|
||||
LOG_D(NR_MAC, "sl_NumSSB_WithinPeriod: %lu\n", *(freq_conf_cmn->sl_SyncConfigList_r16->list.array[0]->sl_SSB_TimeAllocation2_r16->sl_NumSSB_WithinPeriod_r16));
|
||||
LOG_D(NR_MAC, "sl_TimeOffsetSSB: %lu\n", *(freq_conf_cmn->sl_SyncConfigList_r16->list.array[0]->sl_SSB_TimeAllocation2_r16->sl_TimeOffsetSSB_r16));
|
||||
LOG_D(NR_MAC, "sl_TimeInterval: %lu\n", *(freq_conf_cmn->sl_SyncConfigList_r16->list.array[0]->sl_SSB_TimeAllocation2_r16->sl_TimeInterval_r16));
|
||||
LOG_D(NR_MAC, "sl_NumSSB_WithinPeriod: %lu\n", *(freq_conf_cmn->sl_SyncConfigList_r16->list.array[0]->sl_SSB_TimeAllocation3_r16->sl_NumSSB_WithinPeriod_r16));
|
||||
LOG_D(NR_MAC, "sl_TimeOffsetSSB: %lu\n", *(freq_conf_cmn->sl_SyncConfigList_r16->list.array[0]->sl_SSB_TimeAllocation3_r16->sl_TimeOffsetSSB_r16));
|
||||
LOG_D(NR_MAC, "sl_TimeInterval: %lu\n", *(freq_conf_cmn->sl_SyncConfigList_r16->list.array[0]->sl_SSB_TimeAllocation3_r16->sl_TimeInterval_r16));
|
||||
LOG_D(NR_MAC, "sl_SSID: %lu\n", *(freq_conf_cmn->sl_SyncConfigList_r16->list.array[0]->sl_SSID_r16));
|
||||
LOG_D(NR_MAC, "syncTxThreshIC: %lu\n", *(freq_conf_cmn->sl_SyncConfigList_r16->list.array[0]->txParameters_r16.syncTxThreshIC_r16));
|
||||
LOG_D(NR_MAC, "syncTxThreshOoC_r16: %lu\n", *(freq_conf_cmn->sl_SyncConfigList_r16->list.array[0]->txParameters_r16.syncTxThreshOoC_r16));
|
||||
LOG_D(NR_MAC, "buf: %p\n", freq_conf_cmn->sl_SyncConfigList_r16->list.array[0]->txParameters_r16.syncInfoReserved_r16->buf);
|
||||
LOG_D(NR_MAC, "size: %lu\n", freq_conf_cmn->sl_SyncConfigList_r16->list.array[0]->txParameters_r16.syncInfoReserved_r16->size);
|
||||
LOG_D(NR_MAC, "bits_unused: %d\n", freq_conf_cmn->sl_SyncConfigList_r16->list.array[0]->txParameters_r16.syncInfoReserved_r16->bits_unused);
|
||||
|
||||
LOG_D(NR_MAC, "referenceSubcarrierSpacing: %lu\n", sl_preconfigurations->sidelinkPreconfigNR_r16.sl_PreconfigGeneral_r16
|
||||
->sl_TDD_Configuration_r16->referenceSubcarrierSpacing);
|
||||
LOG_D(NR_MAC, "dl_UL_TransmissionPeriodicity: %lu\n", sl_preconfigurations->sidelinkPreconfigNR_r16.sl_PreconfigGeneral_r16
|
||||
->sl_TDD_Configuration_r16->pattern1.dl_UL_TransmissionPeriodicity);
|
||||
|
||||
LOG_D(NR_MAC, "sl_LengthSymbols: %lu\n", *(sl_preconfigurations->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16->list.array[0]
|
||||
->sl_BWP_List_r16->list.array[0]->sl_BWP_Generic_r16->sl_LengthSymbols_r16));
|
||||
LOG_D(NR_MAC, "sl_StartSymbol: %lu\n", *(sl_preconfigurations->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16->list.array[0]
|
||||
->sl_BWP_List_r16->list.array[0]->sl_BWP_Generic_r16->sl_StartSymbol_r16));
|
||||
LOG_D(NR_MAC, "sl_SubchannelSize: %lu\n", *(sl_preconfigurations->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16->list.array[0]
|
||||
->sl_BWP_List_r16->list.array[0]->sl_BWP_PoolConfigCommon_r16->sl_RxPool_r16->list.array[0]->sl_SubchannelSize_r16));
|
||||
LOG_D(NR_MAC, "sl_StartRB_Subchannel_r16: %lu\n", *(sl_preconfigurations->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16->list.array[0]
|
||||
->sl_BWP_List_r16->list.array[0]->sl_BWP_PoolConfigCommon_r16->sl_RxPool_r16->list.array[0]->sl_StartRB_Subchannel_r16));
|
||||
LOG_D(NR_MAC, "sl_NumSubchannel: %lu\n", *(sl_preconfigurations->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16->list.array[0]
|
||||
->sl_BWP_List_r16->list.array[0]->sl_BWP_PoolConfigCommon_r16->sl_RxPool_r16->list.array[0]->sl_NumSubchannel_r16));
|
||||
}
|
||||
|
||||
int nr_rrc_mac_config_req_ue_sl(module_id_t module_id,
|
||||
int cc_idP,
|
||||
const uint32_t * const sourceL2Id,
|
||||
const uint32_t * const destinationL2Id,
|
||||
const uint32_t * const groupL2Id,
|
||||
NR_SL_PreconfigurationNR_r16_t *SL_Preconfiguration_r16,
|
||||
uint32_t directFrameNumber_r16,
|
||||
long slotIndex_r16)
|
||||
{
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
|
||||
if (SL_Preconfiguration_r16) {
|
||||
|
||||
LOG_I(NR_MAC,"Getting SL parameters\n");
|
||||
|
||||
mac->SL_Preconfiguration = SL_Preconfiguration_r16;
|
||||
|
||||
struct NR_SidelinkPreconfigNR_r16__sl_PreconfigFreqInfoList_r16 *freq_info =
|
||||
SL_Preconfiguration_r16->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16;
|
||||
|
||||
//Assumption: Both NR-SL-FreqInfoList and NR-SL-SyncConfigList should have only one element (Spec. 38331 Release 16)
|
||||
AssertFatal(freq_info->list.count == 1, "Number of elements in NR-SL-FreqInfoList should be 1");
|
||||
for (int i = 0; i < freq_info->list.count; i++) {
|
||||
NR_SL_SyncConfigList_r16_t *sync_conf = freq_info->list.array[i]->sl_SyncConfigList_r16;
|
||||
AssertFatal(sync_conf->list.count == 1, "Number of elements in NR-SL-SyncConfigList should be 1");
|
||||
for (int j = 0; j < sync_conf->list.count; j++) {
|
||||
mac->slss.sl_numssb_withinperiod_r16 =
|
||||
*(sync_conf->list.array[j]->sl_SSB_TimeAllocation1_r16->sl_NumSSB_WithinPeriod_r16);
|
||||
mac->slss.sl_timeoffsetssb_r16 =
|
||||
*(sync_conf->list.array[j]->sl_SSB_TimeAllocation1_r16->sl_TimeOffsetSSB_r16);
|
||||
mac->slss.sl_timeinterval_r16 =
|
||||
*(sync_conf->list.array[j]->sl_SSB_TimeAllocation1_r16->sl_TimeInterval_r16);
|
||||
mac->slss.slss_id =
|
||||
*(sync_conf->list.array[j]->sl_SSID_r16);
|
||||
}
|
||||
}
|
||||
|
||||
NR_SL_FreqConfigCommon_r16_t *freq_conf_cmn = malloc16_clear(sizeof(NR_SL_FreqConfigCommon_r16_t));
|
||||
freq_conf_cmn->sl_SyncConfigList_r16 =
|
||||
mac->SL_Preconfiguration->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16->list.array[0]->sl_SyncConfigList_r16;
|
||||
print_sl_preconf_params_mac(mac->SL_Preconfiguration, freq_conf_cmn);
|
||||
// TO-DO:: Add discovery mode
|
||||
}
|
||||
if (directFrameNumber_r16 < 1025) mac->directFrameNumber_r16 = directFrameNumber_r16;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h"
|
||||
#include "LAYER2/MAC/mac.h"
|
||||
#include "NR_MAC_COMMON/nr_mac_extern.h"
|
||||
#include "NR_SL-PreconfigurationNR-r16.h"
|
||||
|
||||
/* RRC */
|
||||
#include "NR_DRX-Config.h"
|
||||
@@ -63,6 +64,9 @@
|
||||
#include "NR_MeasConfig.h"
|
||||
#include "NR_ServingCellConfigCommonSIB.h"
|
||||
|
||||
/* PHY */
|
||||
#include "openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h"
|
||||
|
||||
|
||||
// ==========
|
||||
// NR UE defs
|
||||
@@ -487,6 +491,14 @@ typedef struct {
|
||||
|
||||
pthread_mutex_t mutex_dl_info;
|
||||
|
||||
NR_SL_PreconfigurationNR_r16_t *SL_Preconfiguration;
|
||||
uint32_t sourceL2Id;
|
||||
uint32_t groupL2Id;
|
||||
uint32_t destinationL2Id;
|
||||
uint32_t directFrameNumber_r16;
|
||||
int slotIndex_r16;
|
||||
NR_SLSS_t slss;
|
||||
|
||||
} NR_UE_MAC_INST_t;
|
||||
|
||||
|
||||
|
||||
@@ -112,6 +112,17 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id,
|
||||
int cc_idP,
|
||||
NR_ServingCellConfigCommonSIB_t *scc);
|
||||
|
||||
int nr_rrc_mac_config_req_ue_sl(module_id_t module_id,
|
||||
int cc_idP,
|
||||
const uint32_t * const sourceL2Id,
|
||||
const uint32_t * const destinationL2Id,
|
||||
const uint32_t * const groupL2Id,
|
||||
NR_SL_PreconfigurationNR_r16_t *SL_Preconfiguration_r16,
|
||||
uint32_t directFrameNumber_r16,
|
||||
long slotIndex_r16);
|
||||
|
||||
NR_SLSS_t *nr_ue_get_slss(module_id_t Mod_id, int CC_id, frame_t frame_tx, int slot_tx);
|
||||
|
||||
/**\brief initialization NR UE MAC instance(s), total number of MAC instance based on NB_NR_UE_MAC_INST*/
|
||||
NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst);
|
||||
|
||||
|
||||
@@ -89,9 +89,22 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) {
|
||||
}
|
||||
else {
|
||||
LOG_I(MAC,"Running without CellGroupConfig\n");
|
||||
if(get_softmodem_params()->sa == 1) {
|
||||
if (get_softmodem_params()->sa == 1) {
|
||||
AssertFatal(rlc_module_init(0) == 0, "%s: Could not initialize RLC layer\n", __FUNCTION__);
|
||||
}
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
module_id_t module_id = 0;
|
||||
int cc_idP = 0;
|
||||
uint32_t sourceL2Id, groupL2Id, destinationL2Id;
|
||||
sourceL2Id = get_softmodem_params()->node_number;
|
||||
destinationL2Id = 2; //UPDATE it after implementing the ProSeApp connection
|
||||
groupL2Id = 3; //UPDATE it after implementing the ProSeApp connection
|
||||
uint32_t directFrameNumber_r16 = 1025; // Set greater than the valid directFrameNumber range (0-1023)
|
||||
long slotIndex_r16 = 21; // Set greater than the valid slotIndex_r16 range
|
||||
nr_rrc_mac_config_req_ue_sl(module_id, cc_idP, &sourceL2Id, &destinationL2Id, &groupL2Id,
|
||||
rrc_inst->SL_Preconfiguration[0],
|
||||
directFrameNumber_r16, slotIndex_r16);
|
||||
}
|
||||
}
|
||||
|
||||
return (nr_ue_mac_inst);
|
||||
|
||||
@@ -240,6 +240,28 @@ int get_rnti_type(NR_UE_MAC_INST_t *mac, uint16_t rnti)
|
||||
return rnti_type;
|
||||
}
|
||||
|
||||
void nr_ue_decode_si(module_id_t module_idP, int CC_id, frame_t frameP,
|
||||
uint8_t gNB_index, void *pdu, uint16_t len,
|
||||
NR_SLSS_t *slss, int *frame, int *slot)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
|
||||
|
||||
if (slss == NULL) { // this is not MIB-SL
|
||||
LOG_D(NR_MAC, "[UE %d] Frame %d Sending SI to RRC (LCID Id %d, len %d)\n",
|
||||
module_idP, frameP, NR_BCCH_BCH, len);
|
||||
|
||||
nr_mac_rrc_data_ind_ue(module_idP, CC_id, gNB_index, frameP, 0,
|
||||
SI_RNTI, NR_BCCH_BCH, (uint8_t *) pdu, len);
|
||||
} else {
|
||||
LOG_D(NR_MAC, "[UE %d] Frame %d Sending MIBSL to RRC (LCID Id %d, len %zu) : %x.%x.%x.%x.%x\n",
|
||||
module_idP, frameP, MIBSLCH, sizeof(slss->sl_mib), slss->sl_mib[0], slss->sl_mib[1], slss->sl_mib[2], slss->sl_mib[3], slss->sl_mib[4]);
|
||||
|
||||
nr_mac_rrc_data_ind_ue(module_idP, CC_id, gNB_index, frameP, 0,
|
||||
SI_RNTI, MIBSLCH, (uint8_t *) slss->sl_mib, sizeof(slss->sl_mib));
|
||||
|
||||
LOG_D(NR_MAC, "SL: Resetting SFN.SLOT to %d.%d\n", mac->directFrameNumber_r16, mac->slotIndex_r16);
|
||||
}
|
||||
}
|
||||
|
||||
int8_t nr_ue_decode_mib(module_id_t module_id,
|
||||
int cc_id,
|
||||
@@ -4189,3 +4211,22 @@ int16_t compute_nr_SSB_PL(NR_UE_MAC_INST_t *mac, short ssb_rsrp_dBm)
|
||||
|
||||
return pathloss;
|
||||
}
|
||||
|
||||
NR_SLSS_t *nr_ue_get_slss(module_id_t Mod_id, int CC_id, frame_t frame_tx, int slot_tx)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(Mod_id);
|
||||
NR_SLSS_t *slss = &(mac->slss);
|
||||
int slots = ((20 * frame_tx) + slot_tx);
|
||||
if ((slots % 40) != slss->sl_timeoffsetssb_r16) {
|
||||
slss->sl_mib_length = 0;
|
||||
} else slss->sl_mib_length = nr_mac_rrc_data_req_ue(Mod_id, CC_id, 0,
|
||||
slots, MIBCH, slss->sl_mib); // call RRC get check for SL-MIB
|
||||
|
||||
if (slss->sl_mib_length > 0) {
|
||||
LOG_D(NR_MAC, "frame_tx %d, slot %d, slss->sl_TimeOffsetSSB %lu, mib length %d, sl_mib %p\n",
|
||||
frame_tx, slot_tx, slss->sl_timeoffsetssb_r16, slss->sl_mib_length, slss->sl_mib);
|
||||
|
||||
LOG_D(NR_MAC, "MIB-SL : %x.%x.%x.%x.%x\n", slss->sl_mib[0], slss->sl_mib[1], slss->sl_mib[2], slss->sl_mib[3], slss->sl_mib[4]);
|
||||
}
|
||||
return(slss);
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "../nr_rrc_proto.h"
|
||||
#include "UTIL/OSA/osa_defs.h"
|
||||
#include "RRC/NR/nr_rrc_extern.h"
|
||||
#include "RRC/NR_UE/rrc_vars.h"
|
||||
#include "NR_DL-CCCH-Message.h"
|
||||
#include "NR_UL-CCCH-Message.h"
|
||||
#include "NR_DL-DCCH-Message.h"
|
||||
@@ -192,6 +193,59 @@ int xer_nr_sprint (char *string, size_t string_size, asn_TYPE_descriptor_t *td,
|
||||
return er.encoded;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//TTN for D2D
|
||||
// NR : 3GPP 38.331 (Section 5.8.5.3)
|
||||
uint8_t do_MIB_SL_NR(const protocol_ctxt_t* const ctxt_pP, int abs_slot, NR_UE_RRC_INST_t* UE)
|
||||
{
|
||||
asn_enc_rval_t enc_rval;
|
||||
uint16_t frame = abs_slot / 20;
|
||||
uint8_t slot = abs_slot % 20;
|
||||
|
||||
NR_SBCCH_SL_BCH_MessageType_t *sl_mib = &UE->SL_mib_tx;
|
||||
sl_mib->present = NR_SBCCH_SL_BCH_MessageType_PR_c1;
|
||||
sl_mib->choice.c1 = CALLOC(1, sizeof(struct NR_SBCCH_SL_BCH_MessageType__c1));
|
||||
sl_mib->choice.c1->present = NR_SBCCH_SL_BCH_MessageType__c1_PR_masterInformationBlockSidelink;
|
||||
sl_mib->choice.c1->choice.masterInformationBlockSidelink = CALLOC(1, sizeof(NR_MasterInformationBlockSidelink_t));
|
||||
NR_MasterInformationBlockSidelink_t *nr_sl_mib = sl_mib->choice.c1->choice.masterInformationBlockSidelink;
|
||||
if (get_softmodem_params()->sl_mode != 2) {
|
||||
nr_sl_mib->inCoverage_r16 = 1;
|
||||
AssertFatal(1 == 0, "Needs development for in %s %d.\n", __FUNCTION__, __LINE__);
|
||||
} else {
|
||||
nr_sl_mib->inCoverage_r16 = 0;
|
||||
nr_sl_mib->sl_TDD_Config_r16.size = 2;
|
||||
nr_sl_mib->sl_TDD_Config_r16.buf = CALLOC(1, nr_sl_mib->sl_TDD_Config_r16.size);
|
||||
nr_sl_mib->sl_TDD_Config_r16.bits_unused = 4;
|
||||
nr_sl_mib->reservedBits_r16.size = 1;
|
||||
nr_sl_mib->reservedBits_r16.buf = CALLOC(1, nr_sl_mib->reservedBits_r16.size);
|
||||
nr_sl_mib->reservedBits_r16.bits_unused = 6;
|
||||
}
|
||||
|
||||
nr_sl_mib->directFrameNumber_r16.size = 2;
|
||||
nr_sl_mib->directFrameNumber_r16.buf = CALLOC(1, nr_sl_mib->directFrameNumber_r16.size);
|
||||
nr_sl_mib->directFrameNumber_r16.buf[0] = frame & 255;
|
||||
nr_sl_mib->directFrameNumber_r16.buf[1] = (frame >> 8) & 3;
|
||||
nr_sl_mib->directFrameNumber_r16.bits_unused = 6;
|
||||
nr_sl_mib->slotIndex_r16.size = 1;
|
||||
nr_sl_mib->slotIndex_r16.buf = CALLOC(1, nr_sl_mib->slotIndex_r16.size);
|
||||
nr_sl_mib->slotIndex_r16.buf[0] = slot;
|
||||
nr_sl_mib->slotIndex_r16.bits_unused = 1;
|
||||
|
||||
if ((frame & 255) == 0)
|
||||
LOG_D(NR_RRC, "[MIB-SL] sfn %x, slot %x\n", frame, slot);
|
||||
|
||||
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_SBCCH_SL_BCH_Message,
|
||||
NULL,
|
||||
(void*)&UE->SL_mib_tx,
|
||||
UE->SL_MIB,
|
||||
sizeof(UE->SL_MIB));
|
||||
|
||||
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
|
||||
enc_rval.failed_type->name, enc_rval.encoded);
|
||||
|
||||
return ((enc_rval.encoded + 7) / 8);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
uint8_t do_SIB23_NR(rrc_gNB_carrier_data_t *carrier,
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
|
||||
#include "RRC/NR/nr_rrc_defs.h"
|
||||
#include "RRC/NR/nr_rrc_config.h"
|
||||
#include "RRC/NR_UE/rrc_defs.h"
|
||||
|
||||
|
||||
/*
|
||||
@@ -55,6 +56,8 @@
|
||||
*/
|
||||
int xer_sprint_NR(char *string, size_t string_size, struct asn_TYPE_descriptor_s *td, void *sptr);
|
||||
|
||||
uint8_t do_MIB_SL_NR(const protocol_ctxt_t* const ctxt_pP, int abs_slot, NR_UE_RRC_INST_t* UE);
|
||||
|
||||
uint8_t do_SIB23_NR(rrc_gNB_carrier_data_t *carrier,
|
||||
gNB_RrcConfigurationReq *configuration);
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#include "assertions.h"
|
||||
#include "rrc_vars.h"
|
||||
#include "MAC/mac.h"
|
||||
#include "NR_MAC_UE/mac_defs.h"
|
||||
#include "../NR/MESSAGES/asn1_msg.h"
|
||||
|
||||
typedef uint32_t channel_t;
|
||||
|
||||
@@ -50,6 +52,8 @@ nr_mac_rrc_data_ind_ue(
|
||||
const uint8_t* pduP,
|
||||
const sdu_size_t pdu_len){
|
||||
sdu_size_t sdu_size = 0;
|
||||
protocol_ctxt_t ctxt;
|
||||
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_id, 0, rnti, frame, sub_frame, gNB_index); // sub_frame is slot for SL
|
||||
|
||||
switch(channel){
|
||||
case NR_BCCH_BCH:
|
||||
@@ -108,6 +112,14 @@ nr_mac_rrc_data_ind_ue(
|
||||
}
|
||||
break;
|
||||
|
||||
case MIBSLCH:
|
||||
LOG_D(NR_RRC, "[UE %d] Received SDU for MIBSL\n", module_id);
|
||||
if (decode_MIB_SL_NR(&ctxt, (uint8_t* const) pduP, 5) >= 0)
|
||||
LOG_D(NR_RRC, "Received MIB_SL: %x.%x.%x.%x.%x\n", pduP[0], pduP[1], pduP[2], pduP[3], pduP[4]);
|
||||
else
|
||||
LOG_E(NR_RRC, "Received bogus MIB_SL\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -121,6 +133,9 @@ int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP,
|
||||
const frame_t frameP,
|
||||
const rb_id_t Srb_id,
|
||||
uint8_t *buffer_pP){
|
||||
protocol_ctxt_t ctxt;
|
||||
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, Mod_idP, GNB_FLAG_NO, NOT_A_RNTI, frameP / 20, frameP % 20, gNB_id);
|
||||
int ret_size = 0;
|
||||
|
||||
switch(Srb_id){
|
||||
|
||||
@@ -138,6 +153,13 @@ int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP,
|
||||
|
||||
return NR_UE_rrc_inst[Mod_idP].Srb0[gNB_id].Tx_buffer.payload_size;
|
||||
|
||||
case MIBCH:
|
||||
ret_size = do_MIB_SL_NR(&ctxt, frameP, &NR_UE_rrc_inst[Mod_idP]);
|
||||
memcpy((void*)buffer_pP, (void*)NR_UE_rrc_inst[Mod_idP].SL_MIB, ret_size);
|
||||
LOG_D(NR_RRC, "MIB-SL for %d.%d: %x.%x.%x.%x.%x\n",
|
||||
frameP / 10, frameP % 10, buffer_pP[0], buffer_pP[1], buffer_pP[2], buffer_pP[3], buffer_pP[4]);
|
||||
return (ret_size);
|
||||
|
||||
case DCCH:
|
||||
AssertFatal(1==0, "SRB1 not implemented yet!\n");
|
||||
case DCCH1:
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
|
||||
#include "nr_nas_msg_sim.h"
|
||||
#include <openair2/RRC/NR/nr_rrc_proto.h>
|
||||
#include "NR_SL-SyncConfig-r16.h"
|
||||
#include "NR_SL-ResourcePool-r16.h"
|
||||
#include "NR_SL-BWP-Config-r16.h"
|
||||
#include "NR_SL-SSB-TimeAllocation-r16.h"
|
||||
|
||||
NR_UE_RRC_INST_t *NR_UE_rrc_inst;
|
||||
/* NAS Attach request with IMSI */
|
||||
@@ -432,6 +436,157 @@ void process_nsa_message(NR_UE_RRC_INST_t *rrc, nsa_message_t nsa_message_type,
|
||||
|
||||
}
|
||||
|
||||
void print_sl_preconf_params(NR_SL_PreconfigurationNR_r16_t* sl_preconfigurations,
|
||||
NR_SL_SyncConfig_r16_t* sl_sync_config,
|
||||
NR_SL_BWP_ConfigCommon_r16_t* sl_bwp_conf_cmn,
|
||||
struct NR_SL_ResourcePool_r16* nr_sl_rxpool)
|
||||
{
|
||||
LOG_D(NR_RRC, "sl_OffsetDFN: %lu\n", *(sl_preconfigurations->sidelinkPreconfigNR_r16.sl_OffsetDFN_r16));
|
||||
LOG_D(NR_RRC, "sl_NumSSB_WithinPeriod: %lu\n", *(sl_sync_config->sl_SSB_TimeAllocation1_r16->sl_NumSSB_WithinPeriod_r16));
|
||||
LOG_D(NR_RRC, "sl_TimeOffsetSSB: %lu\n", *(sl_sync_config->sl_SSB_TimeAllocation1_r16->sl_TimeOffsetSSB_r16));
|
||||
LOG_D(NR_RRC, "sl_TimeInterval: %lu\n", *(sl_sync_config->sl_SSB_TimeAllocation1_r16->sl_TimeInterval_r16));
|
||||
LOG_D(NR_RRC, "sl_NumSSB_WithinPeriod: %lu\n", *(sl_sync_config->sl_SSB_TimeAllocation2_r16->sl_NumSSB_WithinPeriod_r16));
|
||||
LOG_D(NR_RRC, "sl_TimeOffsetSSB: %lu\n", *(sl_sync_config->sl_SSB_TimeAllocation2_r16->sl_TimeOffsetSSB_r16));
|
||||
LOG_D(NR_RRC, "sl_TimeInterval: %lu\n", *(sl_sync_config->sl_SSB_TimeAllocation2_r16->sl_TimeInterval_r16));
|
||||
LOG_D(NR_RRC, "sl_NumSSB_WithinPeriod: %lu\n", *(sl_sync_config->sl_SSB_TimeAllocation3_r16->sl_NumSSB_WithinPeriod_r16));
|
||||
LOG_D(NR_RRC, "sl_TimeOffsetSSB: %lu\n", *(sl_sync_config->sl_SSB_TimeAllocation3_r16->sl_TimeOffsetSSB_r16));
|
||||
LOG_D(NR_RRC, "sl_TimeInterval: %lu\n", *(sl_sync_config->sl_SSB_TimeAllocation3_r16->sl_TimeInterval_r16));
|
||||
LOG_D(NR_RRC, "sl_SSID: %lu\n", *(sl_sync_config->sl_SSID_r16));
|
||||
LOG_D(NR_RRC, "syncTxThreshIC: %lu\n", *(sl_sync_config->txParameters_r16.syncTxThreshIC_r16));
|
||||
LOG_D(NR_RRC, "syncTxThreshOoC_r16: %lu\n", *(sl_sync_config->txParameters_r16.syncTxThreshOoC_r16));
|
||||
LOG_D(NR_RRC, "buf: %p\n", sl_sync_config->txParameters_r16.syncInfoReserved_r16->buf);
|
||||
LOG_D(NR_RRC, "size: %lu\n", sl_sync_config->txParameters_r16.syncInfoReserved_r16->size);
|
||||
LOG_D(NR_RRC, "bits_unused: %d\n", sl_sync_config->txParameters_r16.syncInfoReserved_r16->bits_unused);
|
||||
LOG_D(NR_RRC, "referenceSubcarrierSpacing: %lu\n", sl_preconfigurations->sidelinkPreconfigNR_r16.sl_PreconfigGeneral_r16
|
||||
->sl_TDD_Configuration_r16->referenceSubcarrierSpacing);
|
||||
LOG_D(NR_RRC, "dl_UL_TransmissionPeriodicity: %lu\n", sl_preconfigurations->sidelinkPreconfigNR_r16.sl_PreconfigGeneral_r16
|
||||
->sl_TDD_Configuration_r16->pattern1.dl_UL_TransmissionPeriodicity);
|
||||
LOG_D(NR_RRC, "sl_LengthSymbols: %lu\n", *(sl_bwp_conf_cmn->sl_BWP_Generic_r16->sl_LengthSymbols_r16));
|
||||
LOG_D(NR_RRC, "sl_StartSymbol: %lu\n", *(sl_bwp_conf_cmn->sl_BWP_Generic_r16->sl_StartSymbol_r16));
|
||||
LOG_D(NR_RRC, "sl_SubchannelSize: %lu\n", *(nr_sl_rxpool->sl_SubchannelSize_r16));
|
||||
LOG_D(NR_RRC, "sl_StartRB_Subchannel_r16: %lu\n", *(nr_sl_rxpool->sl_StartRB_Subchannel_r16));
|
||||
LOG_D(NR_RRC, "sl_NumSubchannel: %lu\n", *(nr_sl_rxpool->sl_NumSubchannel_r16));
|
||||
}
|
||||
|
||||
void init_SL_preconfig_NR(NR_UE_RRC_INST_t *UE, const uint8_t gNB_index)
|
||||
{
|
||||
LOG_I(NR_RRC, "Initializing Sidelink Sync configuration for UE\n");
|
||||
UE->SL_Preconfiguration[gNB_index] = malloc16_clear(sizeof(NR_SL_PreconfigurationNR_r16_t));
|
||||
|
||||
UE->SL_Preconfiguration[gNB_index]->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16 =
|
||||
malloc16_clear(sizeof(struct NR_SidelinkPreconfigNR_r16__sl_PreconfigFreqInfoList_r16));
|
||||
struct NR_SidelinkPreconfigNR_r16__sl_PreconfigFreqInfoList_r16 *freq_info =
|
||||
UE->SL_Preconfiguration[gNB_index]->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16;
|
||||
|
||||
NR_SL_FreqConfigCommon_r16_t *freq_conf_cmn = malloc16_clear(sizeof(NR_SL_FreqConfigCommon_r16_t));
|
||||
freq_conf_cmn->sl_SyncConfigList_r16 = malloc16_clear(sizeof(struct NR_SL_SyncConfigList_r16));
|
||||
UE->SL_Preconfiguration[gNB_index]->sidelinkPreconfigNR_r16.sl_OffsetDFN_r16 = malloc16_clear(sizeof(long));
|
||||
*(UE->SL_Preconfiguration[gNB_index]->sidelinkPreconfigNR_r16.sl_OffsetDFN_r16) = 1; // Integer (1 ..1000)
|
||||
|
||||
/*IE SL-SyncConfig */
|
||||
NR_SL_SyncConfig_r16_t *sl_sync_config = malloc16_clear(sizeof(NR_SL_SyncConfig_r16_t));
|
||||
sl_sync_config->sl_SSB_TimeAllocation1_r16 = malloc16_clear(sizeof(NR_SL_SSB_TimeAllocation_r16_t));
|
||||
sl_sync_config->sl_SSB_TimeAllocation1_r16->sl_NumSSB_WithinPeriod_r16 = malloc16_clear(sizeof(long));
|
||||
sl_sync_config->sl_SSB_TimeAllocation1_r16->sl_TimeOffsetSSB_r16 = malloc16_clear(sizeof(long));
|
||||
sl_sync_config->sl_SSB_TimeAllocation1_r16->sl_TimeInterval_r16 = malloc16_clear(sizeof(long));
|
||||
|
||||
*(sl_sync_config->sl_SSB_TimeAllocation1_r16->sl_NumSSB_WithinPeriod_r16) = 1;
|
||||
*(sl_sync_config->sl_SSB_TimeAllocation1_r16->sl_TimeOffsetSSB_r16) = 1;
|
||||
*(sl_sync_config->sl_SSB_TimeAllocation1_r16->sl_TimeInterval_r16) = 2;
|
||||
|
||||
sl_sync_config->sl_SSB_TimeAllocation2_r16 = malloc16_clear(sizeof(NR_SL_SSB_TimeAllocation_r16_t));
|
||||
sl_sync_config->sl_SSB_TimeAllocation2_r16->sl_NumSSB_WithinPeriod_r16 = malloc16_clear(sizeof(long));
|
||||
sl_sync_config->sl_SSB_TimeAllocation2_r16->sl_TimeOffsetSSB_r16 = malloc16_clear(sizeof(long));
|
||||
sl_sync_config->sl_SSB_TimeAllocation2_r16->sl_TimeInterval_r16 = malloc16_clear(sizeof(long));
|
||||
|
||||
*(sl_sync_config->sl_SSB_TimeAllocation2_r16->sl_NumSSB_WithinPeriod_r16) = 1;
|
||||
*(sl_sync_config->sl_SSB_TimeAllocation2_r16->sl_TimeOffsetSSB_r16) = 1;
|
||||
*(sl_sync_config->sl_SSB_TimeAllocation2_r16->sl_TimeInterval_r16) = 2;
|
||||
|
||||
sl_sync_config->sl_SSB_TimeAllocation3_r16 = malloc16_clear(sizeof(NR_SL_SSB_TimeAllocation_r16_t));
|
||||
sl_sync_config->sl_SSB_TimeAllocation3_r16->sl_NumSSB_WithinPeriod_r16 = malloc16_clear(sizeof(long));
|
||||
sl_sync_config->sl_SSB_TimeAllocation3_r16->sl_TimeOffsetSSB_r16 = malloc16_clear(sizeof(long));
|
||||
sl_sync_config->sl_SSB_TimeAllocation3_r16->sl_TimeInterval_r16 = malloc16_clear(sizeof(long));
|
||||
|
||||
*(sl_sync_config->sl_SSB_TimeAllocation3_r16->sl_NumSSB_WithinPeriod_r16) = 1;
|
||||
*(sl_sync_config->sl_SSB_TimeAllocation3_r16->sl_TimeOffsetSSB_r16) = 1;
|
||||
*(sl_sync_config->sl_SSB_TimeAllocation3_r16->sl_TimeInterval_r16) = 2;
|
||||
|
||||
sl_sync_config->sl_SSID_r16 = malloc16_clear(sizeof(long));
|
||||
*(sl_sync_config->sl_SSID_r16) = 338 + get_softmodem_params()->node_number;
|
||||
|
||||
sl_sync_config->txParameters_r16.syncTxThreshIC_r16 = malloc16_clear(sizeof(long));
|
||||
*(sl_sync_config->txParameters_r16.syncTxThreshIC_r16) = 0; // INTEGER (0..13)
|
||||
|
||||
sl_sync_config->txParameters_r16.syncTxThreshOoC_r16 = malloc16_clear(sizeof(long));
|
||||
*(sl_sync_config->txParameters_r16.syncTxThreshOoC_r16) = 0; // INTEGER (0..13)
|
||||
|
||||
sl_sync_config->txParameters_r16.syncInfoReserved_r16 = malloc16_clear(sizeof(BIT_STRING_t));
|
||||
sl_sync_config->txParameters_r16.syncInfoReserved_r16->buf = malloc16_clear(sizeof(uint8_t));
|
||||
sl_sync_config->txParameters_r16.syncInfoReserved_r16->buf = NULL;
|
||||
sl_sync_config->txParameters_r16.syncInfoReserved_r16->size = 0;
|
||||
sl_sync_config->txParameters_r16.syncInfoReserved_r16->bits_unused = 1;
|
||||
|
||||
ASN_SEQUENCE_ADD(&freq_conf_cmn->sl_SyncConfigList_r16->list, sl_sync_config);
|
||||
ASN_SEQUENCE_ADD(&freq_info->list, freq_conf_cmn);
|
||||
|
||||
freq_info->list.array[0]->sl_BWP_List_r16 =
|
||||
malloc16_clear(sizeof(struct NR_SL_FreqConfigCommon_r16__sl_BWP_List_r16));
|
||||
struct NR_SL_FreqConfigCommon_r16__sl_BWP_List_r16 *sl_bwp_list =
|
||||
freq_info->list.array[0]->sl_BWP_List_r16;
|
||||
|
||||
/* TODO SL-PreconfigurationNR, Not all IEs needed for demo*/
|
||||
UE->SL_Preconfiguration[gNB_index]->sidelinkPreconfigNR_r16.sl_PreconfigGeneral_r16 =
|
||||
malloc16_clear(sizeof(struct NR_SL_PreconfigGeneral_r16));
|
||||
UE->SL_Preconfiguration[gNB_index]->sidelinkPreconfigNR_r16.sl_PreconfigGeneral_r16->sl_TDD_Configuration_r16 =
|
||||
malloc16_clear(sizeof(struct NR_TDD_UL_DL_ConfigCommon));
|
||||
UE->SL_Preconfiguration[gNB_index]->sidelinkPreconfigNR_r16.sl_PreconfigGeneral_r16
|
||||
->sl_TDD_Configuration_r16->referenceSubcarrierSpacing = 30;
|
||||
UE->SL_Preconfiguration[gNB_index]->sidelinkPreconfigNR_r16.sl_PreconfigGeneral_r16
|
||||
->sl_TDD_Configuration_r16->pattern1.dl_UL_TransmissionPeriodicity = 2;
|
||||
|
||||
NR_SL_BWP_ConfigCommon_r16_t *sl_bwp_conf_cmn =
|
||||
malloc16_clear(sizeof(NR_SL_BWP_ConfigCommon_r16_t));
|
||||
sl_bwp_conf_cmn->sl_BWP_Generic_r16 =
|
||||
malloc16_clear(sizeof(struct NR_SL_BWP_Generic_r16));
|
||||
sl_bwp_conf_cmn->sl_BWP_Generic_r16->sl_LengthSymbols_r16 =
|
||||
malloc16_clear(sizeof(long));
|
||||
|
||||
*(sl_bwp_conf_cmn->sl_BWP_Generic_r16->sl_LengthSymbols_r16) = 0; //sym7=0
|
||||
sl_bwp_conf_cmn->sl_BWP_Generic_r16->sl_StartSymbol_r16 =
|
||||
malloc16_clear(sizeof(long));
|
||||
*(sl_bwp_conf_cmn->sl_BWP_Generic_r16->sl_StartSymbol_r16) = 0;
|
||||
|
||||
sl_bwp_conf_cmn->sl_BWP_PoolConfigCommon_r16 =
|
||||
malloc16_clear(sizeof(struct NR_SL_BWP_PoolConfigCommon_r16));
|
||||
sl_bwp_conf_cmn->sl_BWP_PoolConfigCommon_r16->sl_RxPool_r16 =
|
||||
malloc16_clear(sizeof(struct NR_SL_BWP_PoolConfigCommon_r16__sl_RxPool_r16));
|
||||
struct NR_SL_BWP_PoolConfigCommon_r16__sl_RxPool_r16 *sl_rxpool_list =
|
||||
sl_bwp_conf_cmn->sl_BWP_PoolConfigCommon_r16->sl_RxPool_r16;
|
||||
struct NR_SL_ResourcePool_r16 *nr_sl_rxpool =
|
||||
malloc16_clear(sizeof(struct NR_SL_ResourcePool_r16));
|
||||
|
||||
nr_sl_rxpool->sl_SubchannelSize_r16 =
|
||||
malloc16_clear(sizeof(long));
|
||||
nr_sl_rxpool->sl_StartRB_Subchannel_r16 =
|
||||
malloc16_clear(sizeof(long));
|
||||
nr_sl_rxpool->sl_NumSubchannel_r16 =
|
||||
malloc16_clear(sizeof(long));
|
||||
|
||||
*(nr_sl_rxpool->sl_SubchannelSize_r16) = 10;
|
||||
*(nr_sl_rxpool->sl_StartRB_Subchannel_r16) = 2;
|
||||
*(nr_sl_rxpool->sl_NumSubchannel_r16) = 1;
|
||||
|
||||
ASN_SEQUENCE_ADD(&sl_rxpool_list->list, nr_sl_rxpool);
|
||||
ASN_SEQUENCE_ADD(&sl_bwp_list->list, sl_bwp_conf_cmn);
|
||||
|
||||
LOG_I(NR_RRC, "Initialization of Sidelink Sync Pre-configuration for UE ... Done\n");
|
||||
print_sl_preconf_params(UE->SL_Preconfiguration[gNB_index],
|
||||
sl_sync_config,
|
||||
sl_bwp_conf_cmn,
|
||||
nr_sl_rxpool);
|
||||
}
|
||||
|
||||
NR_UE_RRC_INST_t* openair_rrc_top_init_ue_nr(char* uecap_file, char* rrc_config_path){
|
||||
int nr_ue;
|
||||
if(NB_NR_UE_INST > 0){
|
||||
@@ -504,6 +659,8 @@ NR_UE_RRC_INST_t* openair_rrc_top_init_ue_nr(char* uecap_file, char* rrc_config_
|
||||
RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].CSI_SSB_ResourceSet_list, NR_maxNrofCSI_SSB_ResourceSets);
|
||||
RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].CSI_ResourceConfig_list, NR_maxNrofCSI_ResourceConfigurations);
|
||||
RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].CSI_ReportConfig_list, NR_maxNrofCSI_ReportConfigurations);
|
||||
if (get_softmodem_params()->sl_mode != 0)
|
||||
init_SL_preconfig_NR(&NR_UE_rrc_inst[nr_ue], 0);
|
||||
}
|
||||
|
||||
NR_UE_rrc_inst->uecap_file = uecap_file;
|
||||
@@ -2833,6 +2990,35 @@ void process_lte_nsa_msg(nsa_msg_t *msg, int msg_len)
|
||||
}
|
||||
}
|
||||
|
||||
int decode_MIB_SL_NR(const protocol_ctxt_t* const ctxt_pP,
|
||||
uint8_t* const sdu,
|
||||
const uint8_t sdu_len)
|
||||
{
|
||||
memcpy((void*)&NR_UE_rrc_inst[ctxt_pP->module_id].SL_MIB, (void*)sdu, sdu_len);
|
||||
|
||||
asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
|
||||
&asn_DEF_NR_SBCCH_SL_BCH_Message,
|
||||
(void **)&NR_UE_rrc_inst[ctxt_pP->module_id].mib_sl[0],
|
||||
(const void *)sdu,
|
||||
sdu_len);
|
||||
|
||||
if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
|
||||
LOG_E(NR_RRC, "[UE %d] Frame %d : Failed to decode SBCCH_SL_BCH_Message (%zu bytes)\n", ctxt_pP->module_id, ctxt_pP->frame, dec_rval.consumed);
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG_D(NR_RRC, "Decoded MIBSL SFN.SLOT %d.%d, InCoverage %d\n",
|
||||
*(NR_UE_rrc_inst[ctxt_pP->module_id].mib_sl[0]->choice.c1->choice.masterInformationBlockSidelink->directFrameNumber_r16.buf),
|
||||
*(NR_UE_rrc_inst[ctxt_pP->module_id].mib_sl[0]->choice.c1->choice.masterInformationBlockSidelink->slotIndex_r16.buf),
|
||||
(int)NR_UE_rrc_inst[ctxt_pP->module_id].mib_sl[0]->choice.c1->choice.masterInformationBlockSidelink->inCoverage_r16);
|
||||
|
||||
nr_rrc_mac_config_req_ue_sl(ctxt_pP->module_id, 0, 0, 0, 0,
|
||||
NULL,
|
||||
*(NR_UE_rrc_inst[ctxt_pP->module_id].mib_sl[0]->choice.c1->choice.masterInformationBlockSidelink->directFrameNumber_r16.buf),
|
||||
*(NR_UE_rrc_inst[ctxt_pP->module_id].mib_sl[0]->choice.c1->choice.masterInformationBlockSidelink->slotIndex_r16.buf));
|
||||
return(0);
|
||||
}
|
||||
|
||||
void *nr_rrc_timers_update() {
|
||||
|
||||
while (1) {
|
||||
|
||||
@@ -55,6 +55,10 @@
|
||||
#include "NR_DL-DCCH-Message.h"
|
||||
#include "../NR/nr_rrc_defs.h"
|
||||
|
||||
#include "NR_SBCCH-SL-BCH-Message.h"
|
||||
#include "NR_SBCCH-SL-BCH-MessageType.h"
|
||||
#include "NR_SL-PreconfigurationNR-r16.h"
|
||||
|
||||
#define NB_NR_UE_INST 1
|
||||
#define NB_CNX_UE 2//MAX_MANAGED_RG_PER_MOBILE
|
||||
#define NB_SIG_CNX_UE 2 //MAX_MANAGED_RG_PER_MOBILE
|
||||
@@ -155,6 +159,20 @@ typedef struct NR_UE_RRC_INST_s {
|
||||
|
||||
NR_MIB_t *mib;
|
||||
|
||||
NR_SBCCH_SL_BCH_MessageType_t SL_mib_tx;
|
||||
|
||||
NR_SBCCH_SL_BCH_MessageType_t *mib_sl[NB_CNX_UE];
|
||||
uint8_t SL_MIB[5];
|
||||
|
||||
NR_SL_PreconfigurationNR_r16_t *SL_Preconfiguration[NB_CNX_UE];
|
||||
|
||||
uint32_t sourceL2Id;
|
||||
uint32_t groupL2Id;
|
||||
uint32_t destinationL2Id;
|
||||
|
||||
//sl_discovery..
|
||||
NR_SRB_INFO SL_Discovery[NB_CNX_UE];
|
||||
|
||||
/* KeNB as computed from parameters within USIM card */
|
||||
uint8_t kgnb[32];
|
||||
/* Used integrity/ciphering algorithms */
|
||||
|
||||
@@ -173,6 +173,9 @@ void process_lte_nsa_msg(nsa_msg_t *msg, int msg_len);
|
||||
|
||||
int get_from_lte_ue_fd();
|
||||
|
||||
int decode_MIB_SL_NR(const protocol_ctxt_t* const ctxt_pP,
|
||||
uint8_t* const sdu,
|
||||
const uint8_t sdu_len);
|
||||
/** @}*/
|
||||
#endif
|
||||
|
||||
|
||||
@@ -188,11 +188,11 @@ void gen_usim_data(usim_data_conf_t *u, usim_data_t *usim_data,
|
||||
network_record_t record = networks.items[user_plmns->operators.items[i]].record;
|
||||
usim_data->pnn[i].fullname.type = USIM_PNN_FULLNAME_TAG;
|
||||
usim_data->pnn[i].fullname.length = strlen(record.fullname);
|
||||
strncpy((char*) usim_data->pnn[i].fullname.value, record.fullname,
|
||||
memcpy((char*) usim_data->pnn[i].fullname.value, record.fullname,
|
||||
usim_data->pnn[i].fullname.length);
|
||||
usim_data->pnn[i].shortname.type = USIM_PNN_SHORTNAME_TAG;
|
||||
usim_data->pnn[i].shortname.length = strlen(record.shortname);
|
||||
strncpy((char*) usim_data->pnn[i].shortname.value, record.shortname,
|
||||
memcpy((char*) usim_data->pnn[i].shortname.value, record.shortname,
|
||||
usim_data->pnn[i].shortname.length);
|
||||
usim_data->opl[i].plmn = record.plmn;
|
||||
usim_data->opl[i].start = record.tac_start;
|
||||
|
||||
Reference in New Issue
Block a user