Compare commits

...

341 Commits

Author SHA1 Message Date
J.Y
439bcdf9f8 reverse TDMA to hardcoded 2026-05-28 09:39:06 +02:00
J.Y
4d21f2fd3e add flag for sl-nas SLC control, by run with or without --sl-nas 2026-05-06 16:14:45 +02:00
J.Y
bcac6783da modify hardcoded QFI 2026-04-28 15:27:48 +02:00
J.Y
f35a75baa2 debug bearer 2026-04-19 10:20:16 +02:00
J.Y
ef201f1419 fix SLC bearer control 2026-04-09 15:18:04 +02:00
J.Y
eb38ab0a56 add SLC for resource pool 2026-04-07 15:26:53 +02:00
J.Y
26700cbb18 SLC modification for scheduler 2026-03-20 14:54:35 +01:00
J.Y
bbaf90c64d update Readme ASN 2026-03-17 14:09:15 +01:00
J.Y
5c0497c92a Enable support for >3 UEs 2026-03-06 14:11:15 +01:00
J.Y
13c035ef77 fix bug 2026-03-02 11:15:55 +01:00
Jérôme Härri
9c9e50391e PC5_S PC5_C controller revision 1 2026-02-20 15:56:37 +01:00
Jérôme Härri
801886c8d9 PC5_S PC5_C controller 2026-02-19 12:31:00 +01:00
J.Y
a957cc7b59 update manual 2026-02-17 15:04:51 +01:00
J.Y
6eba4d2abe Batman works! 2026-02-13 15:06:38 +01:00
J.Y
82af5bb27b SDAP reached, not batman 2026-02-13 12:10:04 +01:00
J.Y
7d0119efa6 PDCP patch, batman can show two neighbours, but not on routing table yet 2026-02-06 16:49:06 +01:00
J.Y
c67c11b380 updated TAP, unfinished, now second UE broke on PDCP layer 2026-02-06 14:11:51 +01:00
J.Y
92c5b04cdb TAP version1; problem with batman 2026-02-04 10:28:06 +01:00
J.Y
ad6e003ad3 clean log 2026-02-01 09:10:03 +01:00
J.Y
0a1d4ba709 working version multiple UEs 2026-01-30 18:23:45 +01:00
beraoudabdelkhalek
9ae927b862 Updated JSUC.md 2025-05-15 19:21:41 +02:00
beraoudabdelkhalek
fd54152a53 Added diagram 2025-05-15 19:20:12 +02:00
beraoudabdelkhalek
d01693b901 Added JSUC doc 2025-05-15 11:59:37 +02:00
beraoudabdelkhalek
cf65d02fd4 Added pubsub RFsim, enabled CSI reporting 2025-05-08 16:40:01 +02:00
Deokseong "David" Kim
3cc086821f Fix bugs in the sensing of available resources and ssb count in Syncref UE. 2025-02-13 19:06:24 -08:00
Ejaz Ahmed
a8b4080383 Updated sampling rate 2025-01-09 14:00:57 -05:00
Ejaz Ahmed
a32aba4ec5 Merge branch 'episys/sl-eurecom2' into sl-eurecom2 2025-01-09 13:24:46 -05:00
Ejaz Ahmed
41552c0ea8 Removed warnings; temporarily fixed timestamp issue 2025-01-09 10:13:57 -08:00
Ejaz Ahmed
762e68c327 Reverted the payload length based num_pssch_tx stats update
We have reverted the payload length based num_pssch_tx stats update because
on the receiver, the payload length information is not available at PHY
layer so we could not update the rx_ok based on payload length
information. Thats why tx stats and rx stats were not matching.
2025-01-08 10:32:53 -08:00
Ejaz Ahmed
737155131b Merge branch 'episys/ea/fixed_decoding_error' into 'episys/sl-eurecom2'
Addressed ldpc decoding problems; fixed formatting issues

See merge request aburger/openairinterface5g!310
2025-01-03 20:50:57 +00:00
Ejaz Ahmed
75cf67dcf2 Modified the ldpc number max iterations loop condition 2025-01-03 12:49:31 -08:00
Laurent THOMAS
ad2c7372e0 remove-cblas-oai-5g 2025-01-03 12:31:05 -08:00
Ejaz Ahmed
65f3dd803f fixed warning; reverted fixed mcs assignment code 2025-01-03 12:08:19 -08:00
Ejaz Ahmed
f1ee81c22e Merge branch 'episys/sl-eurecom2' into episys/ea/fixed_decoding_error 2025-01-03 11:55:00 -08:00
Ejaz Ahmed
56898c81d3 Merge branch 'episys/mel/fixing-build' into 'episys/sl-eurecom2'
Episys/mel/fixing build

See merge request aburger/openairinterface5g!309
2025-01-03 19:53:17 +00:00
Ejaz Ahmed
9b37a05a71 Addressed ldpc decoding problems; fixed formatting issues
Following updates are added:
1) Returned 0, if decoded data is zero
2) Set numIter to 2, if CRC checks passes
3) Fixed formatting issues
2024-12-27 18:49:37 -08:00
Melissa Cusack
b960ede044 Making MCS based on CL and decreasing sampling rate 2024-12-23 17:22:36 -05:00
Melissa Cusack
a60aa4250a Updating usrp_lib.cpp to match develop 2024-12-23 13:27:32 -05:00
Melissa Cusack
6bdcac9e0b Fixing warnings and cleaning up ulsch decoding 2024-12-23 12:51:36 -05:00
Melissa Cusack
50892fa07f Return min_rescource_counter in reselection counter.
Also, this commit adds the phrase "in error" in the NACK log,
in the case of a failed reception. We do this becasue this is
the standard log the team is used to searching for in the logs.
2024-11-27 10:39:49 -08:00
Ejaz Ahmed
6cb94c69bd Merge branch 'episys/mel/debugging-resource-selection' into 'episys/sl-eurecom2'
Passed selected resource in PSSCH scheduling function

See merge request aburger/openairinterface5g!308
2024-11-27 17:13:37 +00:00
Melissa
f44aa9b86e Passed selected resource in PSSCH scheduling function 2024-11-27 17:13:36 +00:00
Melissa
336db01213 Merge branch 'episys/mel/cleanup-ea-branch' into 'episys/sl-eurecom2'
Dynamically configuring TX/RX slot selections

See merge request aburger/openairinterface5g!307
2024-11-21 22:31:35 +00:00
Melissa
a6a6fe043e Dynamically configuring TX/RX slot selections 2024-11-21 22:31:35 +00:00
Melissa
41fc98eda5 Merge branch 'episys/ea/resource_selection' into 'episys/sl-eurecom2'
Implemented Resource Sensing for 5G Sidelink

See merge request aburger/openairinterface5g!302
2024-11-13 16:33:33 +00:00
Ejaz Ahmed
230ebaea70 Added sl_threshold rsrp computation code; removed sensing window duplicated code 2024-11-12 17:34:40 -08:00
Ejaz Ahmed
87348885b4 Added explanation for conditions; provided references; cleaned code 2024-11-12 15:31:51 -08:00
Ejaz Ahmed
9b60e7f4ec Merge branch 'episys/fixing-preconfig-params' into 'episys/ea/resource_selection'
This commit fixes the hardcoded values for the sl_preconfig parameters.

See merge request aburger/openairinterface5g!303
2024-11-12 18:03:34 +00:00
Melissa
ea14ae4a15 This commit fixes the hardcoded values for the sl_preconfig parameters. 2024-11-12 18:03:34 +00:00
Ejaz Ahmed
8c8408ba8f Cleaned code 2024-11-11 12:24:06 -08:00
Ejaz Ahmed
c8ec792c3e Merge branch 'episys/sl-eurecom2' into episys/ea/resource_selection 2024-11-11 08:42:13 -08:00
Ejaz Ahmed
c9486cb4f8 Fixed the issues with candidate resource list 2024-11-10 16:51:56 -08:00
Ejaz Ahmed
30cb74b96c Added TRIV and FRIV 2024-11-09 18:03:19 -08:00
Ejaz Ahmed
c608abe8a1 Completed resource selection function 2024-11-06 21:08:05 -08:00
Ejaz Ahmed
5831ceada3 Implemented initial candidate resource selection code 2024-11-05 19:49:38 -08:00
Melissa
174e39b417 Merge branch 'episys/ea/resource_selection' into 'episys/sl-eurecom2'
Initial implementation of Resource Sensing

See merge request aburger/openairinterface5g!301
2024-11-01 18:52:06 +00:00
Ejaz Ahmed
6ee1ed99a0 Used rsrp as local variable; made consistent variable name 2024-11-01 11:30:33 -07:00
Ejaz Ahmed
e766185363 Removed unused code 2024-11-01 09:18:00 -07:00
Ejaz Ahmed
7dbe690dcf Removed commented code 2024-11-01 09:14:21 -07:00
Ejaz Ahmed
b7e443a2ed Cleaned code 2024-11-01 09:08:24 -07:00
Ejaz Ahmed
95c143657f Added sensing window related configuration params and some functions 2024-10-31 20:18:52 -07:00
Ejaz Ahmed
98ea7cf8a8 Merge branch 'episys/sl-eurecom2' into episys/ea/resource_selection 2024-10-31 15:49:51 -07:00
Ejaz Ahmed
817aeb6e1b Implemented initial structures for sensing window 2024-10-30 19:53:15 -07:00
Melissa Cusack
aaccfe4beb Reverting change that caused traffic to not work
Specifically, there were changes to the dmrs_lowpaprtype1 where we
check if the ref signal exits before freeing. The compiler complained
and said the check was unnecessary, however, without this change
traffic would not work on the PSSCH!
2024-10-28 16:55:16 -04:00
Ejaz Ahmed
3cdd8e2221 Merge branch 'episys/ea/fix_pdu_in_case_of_cno_csirs' into 'episys/sl-eurecom2'
Added NULL value for CSI-RS PHY params in case of no CSI

See merge request aburger/openairinterface5g!300
2024-10-28 18:50:01 +00:00
Ejaz Ahmed
2b6e7e105e Merge branch 'episys/sl-eurecom2' into episys/ea/fix_pdu_in_case_of_cno_csirs 2024-10-28 11:48:58 -07:00
Melissa
39fb255189 Merge branch 'episys/ea/sdap_ip_traffic' into 'episys/sl-eurecom2'
IP traffic sent through 5G sidelink stack

See merge request aburger/openairinterface5g!299
2024-10-28 18:33:39 +00:00
Ejaz Ahmed
e9dd1d9bf0 IP traffic sent through 5G sidelink stack 2024-10-28 18:33:39 +00:00
Ejaz Ahmed
3bf811e903 Properly updated PSSCH stats
Previously, PSSCH stats were computed for both PSSCH and PSFCH.
Now, we look at the payload length to determine if PSSCH is
being transmitted (This can happen with or without PSFCH).
2024-10-28 13:12:15 -04:00
Ejaz Ahmed
3782926ae5 Added NULL value in case of no csi-rs to make the code more robust 2024-10-25 10:28:30 -07:00
Ejaz Ahmed
6ced256931 RMeasured SRP Mand sent it to the AC layer 2024-10-24 14:25:47 -07:00
Melissa
e5f6ec76ec Merge branch 'episys/ea/support_fixed_slots_all_psfch_periods' into 'episys/sl-eurecom2'
Fixed slot mapping; tested on B210; MCS(0-11) PSFCH PERIOD (0,1,2,4)

See merge request aburger/openairinterface5g!298
2024-10-14 23:50:51 +00:00
Ejaz Ahmed
c3b314ab67 Fixed CSI receiver side reporting ldu and padding slength subtractions 2024-10-14 12:34:22 -07:00
Ejaz Ahmed
16bd6d4421 Merge branch 'episys/sl-eurecom2' into episys/ea/support_fixed_slots_all_psfch_periods 2024-10-11 18:03:51 -07:00
Ejaz Ahmed
6e00505f98 Removed Data traffic generating code 2024-10-11 18:01:20 -07:00
Melissa Cusack
bb792807ab episys/fixing-more-warnings 2024-10-11 20:36:41 -04:00
Ejaz Ahmed
852d0dc2b9 Fixed slot mapping; tested on B210; MCS(0-11) PSFCH PERIOD (0,1,2,4)
There are several updates on this commit:
    1) Introduced fixed slot mapping
    2) Enabled support for PSFCH period of 0, 1, 2, and 4 based on fixed
    slot mapping
    3) Fixed Log statements issues
    4) One big difference, which enabled us to run on B210 for MCS from 7 to
    11, was to increase the sleep time in following code. Previously, it was
    100000.

    +    // len = read(nas_sock_fd[0], &rx_buf, NL_MAX_PAYLOAD);
    +#if 1
    +    usleep(1000000);
    +    char msg1[] = "Hello Nearby  UE (from SyncRef UE)";
    +    char msg2[] = "Hello SyncRef UE (from Nearby UE)";
    +    int len1 = sizeof(msg1)/sizeof(msg1[0]);
    +    int len2 = sizeof(msg2)/sizeof(msg2[0]);

    Though we are not pushing this piece of code to our internal master
    branch, it is important to note if we test next time to regenerate
    the same results, we should apply the above change in sleep time.

    The syncref was on 5g-tx, nearby UE was on 5g-Rx

    Attenuation 30 dB

    SyncRef does not receive the correct messages in most of the cases
    Nearby UE receives the correct SLSCH; however, there are higher errors
    for MCS 9-11.

    sci_pdu->mcs = sched_pssch->mcs;
    should be replaced with user provided mcs assignment

    commands:

    sudo LD_LIBRARY_PATH=$PWD/ran_build/build:$LD_LIBRARY_PATH -E ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf --sa --sl-mode 2 --sync-ref --ue-txgain 10 --ue-rxgain 100 --usrp-args "serial=3150361,type=b200" --thread-pool -1,-1 --mcs 0

    sudo LD_LIBRARY_PATH=$PWD/ran_build/build:$LD_LIBRARY_PATH ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/NR-SIDELINK/CONF/sl_ue1.conf --sa --sl-mode 2 --ue-txgain 10 --ue-rxgain 100 --usrp-args "serial=3150384,type=b200" --thread-pool -1,-1 --mcs 10
2024-10-11 17:27:31 -07:00
Ejaz Ahmed
1f47719f95 Fixed Log statements issues 2024-10-11 17:11:23 -07:00
Ejaz Ahmed
383a573665 Added more logs and updated AssertFatal conditions 2024-10-11 17:10:55 -07:00
Ejaz Ahmed
a376968ba4 Fixed slot mapping; tested on B210; MCS(0-11) PSFCH PERIOD (0,1,2,4)
There are several updates on this commit:
1) Introduced fixed slot mapping
2) Enabled support for PSFCH period of 0, 1, 2, and 4 based on fixed
slot mapping
3) One big difference, which enabled us to run on B210 for MCS from 7 to
11, was to increase the sleep time in following code. Previously, it was
100000.

+    // len = read(nas_sock_fd[0], &rx_buf, NL_MAX_PAYLOAD);
+#if 1
+    usleep(1000000);
+    char msg1[] = "Hello Nearby  UE (from SyncRef UE)";
+    char msg2[] = "Hello SyncRef UE (from Nearby UE)";
+    int len1 = sizeof(msg1)/sizeof(msg1[0]);
+    int len2 = sizeof(msg2)/sizeof(msg2[0]);
+    char *msg = (get_nrUE_params()->sync_ref) ? msg1 : msg2;
+    len = (get_nrUE_params()->sync_ref) ? len1 : len2;
+    memcpy(rx_buf, msg, len);
+    LOG_D(PDCP, "Sending %s\n", msg);
+#endif

Though we are not pushing this piece of code to our internal master
branch, it is important to note if we test next time to regenerate
the same results, we should apply the above change in sleep time.

The syncref was on 5g-tx, nearby UE was on 5g-Rx

Attenuation 30 dB

SyncRef does not receive the correct messages in most of the cases
Nearby UE receives the correct SLSCH; however, there are higher errors
for MCS 9-11.

sci_pdu->mcs = sched_pssch->mcs;
should be replaced with user provided mcs assignment

commands:

sudo LD_LIBRARY_PATH=$PWD/ran_build/build:$LD_LIBRARY_PATH -E ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf --sa --sl-mode 2 --sync-ref --ue-txgain 10 --ue-rxgain 100 --usrp-args "serial=3150361,type=b200" --thread-pool -1,-1 --mcs 0

sudo LD_LIBRARY_PATH=$PWD/ran_build/build:$LD_LIBRARY_PATH ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/NR-SIDELINK/CONF/sl_ue1.conf --sa --sl-mode 2 --ue-txgain 10 --ue-rxgain 100 --usrp-args "serial=3150384,type=b200" --thread-pool -1,-1 --mcs 10
2024-10-10 12:02:33 -07:00
Ejaz Ahmed
7f7c343856 Added assertion for feedback slot; updated feedback slot in table for period of 4 2024-10-09 14:24:52 -07:00
Ejaz Ahmed
98ae1a296a Fixed bugs with static slot mapping 2024-10-08 18:41:52 -07:00
Ejaz Ahmed
9bab4005fe Added more code for static slot mapping; Added psfch period 1 feedback reception 2024-10-08 11:45:55 -07:00
Ejaz Ahmed
e2746c9e62 Added code for disabling PSFCH 2024-10-08 08:08:10 -07:00
Ejaz Ahmed
20ae13fa41 Merge branch 'episys/sl-eurecom2' into episys/ea/static_feedback_slot_mapping 2024-10-07 15:59:38 -07:00
Ejaz Ahmed
3b520e933b Merge branch 'episys/warning-fixes' into 'episys/sl-eurecom2'
Fixing warnings fournd on episys/sl-eurecom2

See merge request aburger/openairinterface5g!297
2024-10-07 17:30:37 +00:00
Melissa
e214756682 Fixing warnings fournd on episys/sl-eurecom2 2024-10-07 17:30:37 +00:00
Ejaz Ahmed
fb5e590d44 Fixed bit_len_harq; updated ack_nack and nack only conditions 2024-10-07 10:22:57 -07:00
Ejaz Ahmed
bde50f2e63 Added static feedback slot mapping 2024-10-07 09:28:01 -07:00
Ejaz Ahmed
55042e7b9f Updated UE_iterator for Sidelink to SL_UE_iterator and reverted the gNB UE_iterator 2024-10-06 11:49:26 -07:00
Ejaz Ahmed
2fd7150702 Restricted harq bit length to less than or equal to 1
Following changes are incorporated:
1) Restricted harq bit length to less than or equal to 1
2) Removed unused variables to fix warning
3) Fixed Typo
4) Removed unnecessary harq bit length condition
2024-10-05 17:38:09 -07:00
Melissa Cusack
74adc9eeb5 Fixing warnings fournd on episys/sl-eurecom2 2024-10-05 17:40:02 -04:00
Melissa
419eb6c81f Merge branch 'episys/ea/fixed_available_harq_list_updating_procedures' into 'episys/sl-eurecom2'
Fixed available harq list updating procedures issue

See merge request aburger/openairinterface5g!296
2024-10-05 21:00:59 +00:00
Ejaz Ahmed
6873c38471 Fixed available harq list updating procedures issue 2024-10-05 21:00:59 +00:00
Ejaz Ahmed
70d1e6e52c Merge branch 'episys/ea/bler_based_mcs_selection' into 'episys/sl-eurecom2'
Included BLER value in MCS selection criteria; Fixed CSI-RS REs issue if no CSI-RS scheduled

See merge request aburger/openairinterface5g!294
2024-09-25 23:34:21 +00:00
Ejaz Ahmed
8216cbf79a Merge branch 'episys/sl-eurecom2' into episys/ea/bler_based_mcs_selection 2024-09-25 19:30:36 -04:00
Ejaz Ahmed
bd210f9961 Removed unnecessary logs 2024-09-24 22:33:22 -04:00
Ejaz Ahmed
c23170f895 Reverted the unnecessary line spacing 2024-09-23 21:31:58 -04:00
Ejaz Ahmed
ecc78c1bea Reverted debug condition 2024-09-23 21:22:08 -04:00
Ejaz Ahmed
aa57104123 Removed unused header file 2024-09-23 21:06:14 -04:00
Ejaz Ahmed
d09522d616 Removed testing data generating code; mac log dump code; cleaned code 2024-09-23 20:31:58 -04:00
Ejaz Ahmed
a522b2dcb5 Reverted second declaration of csi-rs related variable 2024-09-23 19:45:56 -04:00
Ejaz Ahmed
c53d66f140 Fixed CSI-RS REs issue if there is no CSI-RS scheduled 2024-09-23 19:45:43 -04:00
Ejaz Ahmed
c8b84b8e50 Added logs for testing; Added data code for testing only 2024-09-23 19:44:58 -04:00
Ejaz Ahmed
47a94020cd Included BLER value in MCS selection criteria 2024-09-23 19:42:42 -04:00
Melissa
95b9990ef5 Merge branch 'episys/ea/update_configuration_files' into 'episys/sl-eurecom2'
Updated  configuration files to add CSI reporting parameters

See merge request aburger/openairinterface5g!293
2024-09-19 12:42:06 +00:00
Ejaz Ahmed
16f75be9fd Added updated configuration files 2024-09-13 19:07:39 -04:00
Ejaz Ahmed
aed1eb1841 Merge branch 'episys/ea/updated_sinr_estimation_sinr_cqi_mapping' into 'episys/sl-eurecom2'
Updated sinr estimation function; upgraded sinr to cq mapping function

See merge request aburger/openairinterface5g!292
2024-09-13 21:43:08 +00:00
Ejaz Ahmed
f5511fec98 Adjusteddenominator for noise per sample computation in rfsim; updated comment 2024-09-13 17:41:53 -04:00
Ejaz Ahmed
5db24ade57 Merge branch 'episys/sl-eurecom2' into episys/ea/updated_sinr_estimation_sinr_cqi_mapping 2024-09-13 17:27:14 -04:00
Ejaz Ahmed
171ba6f765 Merge branch 'episys/ea/fixed_higher_mod_order_issue' into 'episys/sl-eurecom2'
Fixed higher mod order llr computation;

See merge request aburger/openairinterface5g!291
2024-09-13 21:25:57 +00:00
Ejaz Ahmed
d6dc49bc4a Added paranethesis for readability 2024-09-13 17:25:25 -04:00
Ejaz Ahmed
302b64cc07 Merge branch 'episys/sl-eurecom2' into episys/ea/fixed_higher_mod_order_issue 2024-09-13 17:17:25 -04:00
Ejaz Ahmed
19d1eb25ba Merge branch 'episys/ea/added_csi_reporting_with_harq' into 'episys/sl-eurecom2'
Implemented HARQ retransmission; Added CSI functionality with HARQ

See merge request aburger/openairinterface5g!290
2024-09-13 21:16:21 +00:00
Ejaz Ahmed
0bcbc7401c Added logs; cleaned code; removed hacked code 2024-09-13 17:15:44 -04:00
Ejaz Ahmed
d56d68332e Changed datatype of mcs, ri nd cqi to uint8_t from int8_t 2024-09-13 16:16:37 -04:00
Ejaz Ahmed
4600b1bba6 Merge branch 'episys/sl-eurecom2' into episys/ea/added_csi_reporting_with_harq 2024-09-13 16:04:22 -04:00
Ejaz Ahmed
c282e8700a Merge branch 'episys/ea/mac_initial_updates' into episys/ea/added_csi_reporting_with_harq 2024-09-13 16:01:58 -04:00
Ejaz Ahmed
5314c750e8 Updated Log filtering condition 2024-09-13 15:59:21 -04:00
Ejaz Ahmed
6e708111d9 Merge branch 'episys/ea/mac_initial_updates' into 'episys/sl-eurecom2'
Updated CSI reporting related initialization

See merge request aburger/openairinterface5g!289
2024-09-13 19:58:40 +00:00
Ejaz Ahmed
fd2ac5a881 Removed slot condition in printing cqi log 2024-09-13 15:30:53 -04:00
Ejaz Ahmed
8fdc275c98 updated default mcs value to 9 2024-09-13 15:28:43 -04:00
Ejaz Ahmed
ae692d25ac Removed commented code 2024-09-13 11:48:37 -04:00
Ejaz Ahmed
1d3b40a602 Reverted spacing 2024-09-13 11:26:21 -04:00
Ejaz Ahmed
e4508b1d01 Updated sinr estimation function; upgraded sinr to cq mapping function
Following features are added:
1) Updated sinr estimation function
2) Upgraded sinr to cq mapping function
2024-09-12 23:36:21 -04:00
Ejaz Ahmed
a2184d2430 Fixed higher mod order llr computation;
Following changes are made:
1) Fixed Higher order llr computation issue
2) Removed remains of PSFCH and CSI-RS concurrent transmission
3) Added default MCS in cqi mcs mapping function
4) Introduced Latency bound for CSI report
5) Cleaned code
2024-09-12 22:59:32 -04:00
Ejaz Ahmed
3645c75ba8 Added CSI functions with HARQ; Fixed bugs came from HARQ implementation
Following functions have been implemented:
1) Integrated CSI reporting with HARQ
2) Fixed feedback frame and slot issue introduced during HARQ implementation
3) Fixed buflen_remain variable condition in case of csi report
4) Removed PSFCH and CSI-RS concurrent transmission as 5g SL does not support it
5) Fixed N_REprime calculation
6) Added default mcs in get_mcs_from_cqi function
7) Code cleanup
2024-09-12 21:07:13 -04:00
Ejaz Ahmed
88032eaa6f MAC initial configuration updates 2024-09-12 19:16:28 -04:00
Melissa
eb7214ed1e Merge branch 'episys/david/using_harq_pid_specified_in_MAC_scheduler' into 'episys/sl-eurecom2'
Update harq pid in PHY layer and added locking mechanism.

See merge request aburger/openairinterface5g!286
2024-08-27 15:09:44 +00:00
Deokseong "David" Kim
9ebfc7df80 Update harq pid in PHY layer and added locking mechanism. 2024-08-27 15:09:44 +00:00
Melissa
c5dd477299 Merge branch 'episys/david/psfch_harq_retransmission' into 'episys/sl-eurecom2'
pssch scheduler update to handle retransmission for HARQ

See merge request aburger/openairinterface5g!285
2024-08-22 19:26:11 +00:00
Deokseong "David" Kim
de8bde2eb1 pssch scheduler update to handle retransmission for HARQ 2024-08-22 19:26:11 +00:00
Ejaz Ahmed
041a74ad55 Merge branch 'episys/sl-eurecom2' into eurecom-sl-eurecom2
Following updates are included in this MR:

1) Updated PSFCH scheduling to make it more flexible to support various SL slot configurations
2) Added channel configuration files for RFSIM
3) Updated sl_sync_ref and sl_ue1 configuration files
4) Fixed TDD initialization issues
5) malloc16_clear() is used instead of malloc()
6) uint16_t *temp_llr is replaced with int16_t *temp_llr
7) SCI1 and SCI2 are separately processed only in case of (qam_mod_order > 2)
8) Fixed argument order issue in nr_cyclic_shift_hopping()
9) Set slot offset to zero in nr_ue_decode_pucch0()
10) Used appropriate format specifiers in psbch_pscch_pssch_processing
11) Formatted logs
2024-08-22 07:33:25 -07:00
Ejaz Ahmed
dd4c1851f3 Merge branch 'episys/ea/psfch_ack_nack_scheduling_rx' into 'episys/sl-eurecom2'
Fixed PSFCH rx related issues

See merge request aburger/openairinterface5g!284
2024-08-21 01:38:25 +00:00
Ejaz Ahmed
665143e3f6 Fixed warnings 2024-08-19 11:43:01 -07:00
Ejaz Ahmed
1a904623e1 Fixed PSFCH rx side issues; Addressed formatting issues 2024-08-19 10:16:11 -07:00
Ejaz Ahmed
c9e48b8ce9 Merge branch 'episys/sl-eurecom2' into pisys/ea/psfch_ack_nack_scheduling_rx 2024-08-19 09:54:08 -07:00
Ejaz Ahmed
2abf30ad6e Merge branch 'episys/ea/psfch_ack_nack_scheduling_tx' into 'episys/sl-eurecom2'
Implementation of psfch tx ack nack scheduling

See merge request aburger/openairinterface5g!283
2024-08-19 16:45:51 +00:00
Ejaz Ahmed
d37bf06d39 Fixed typo in function name; Fixed declaration error 2024-08-19 12:35:07 -04:00
Ejaz Ahmed
eca4d6a572 Provided mcs value from command line; Updated variables and functions names 2024-08-19 12:34:48 -04:00
Ejaz Ahmed
b4b73f2dea Support is provided for MCS 1-16, multiple SLSCH feedbacks and basic HARQ
Updates in this MR are as follows:

1) Enabled support for MCS 1-16; Fixed SNR estimation
2) Added multiple SLSCH feedback support in PSFCH
3) Implemented HARQ process for first transmission and reception
4) Implemented sync notification from nearby to syncref
5) Fixed PSFCH issue in sci_payload in case of psfch_period zero
6) Fixed order of SL UE phy params initializations
7) Moved gNB specific list functions to common file
8) Developed thread lock functions for NR_UE_SL_SCHED
9) Included header files for common moved functions in gNB code
10) Fixed l value in computing alpha for pucch0
11) Fixed warnings
12) cleaned code
2024-08-16 18:34:42 -07:00
Ejaz Ahmed
bc316b1cec Removed worked around code in condition 2024-08-13 19:02:36 -04:00
Ejaz Ahmed
0ff70cc496 Removed worked around code in condition 2024-08-13 18:37:27 -04:00
Ejaz Ahmed
816bfec661 Used Stats appropriate format specifier; working in B210 with tx gain (SyncRef 10, NB 5), rx gain 80 atten. 15 2024-08-13 13:59:56 -07:00
Ejaz Ahmed
e8afaa8cca Removed unnecessary codition 2024-08-13 11:37:32 -04:00
Ejaz Ahmed
f94fe2ac80 Separated tx side functionality changes 2024-08-13 11:22:44 -04:00
Ejaz Ahmed
b1d76e157c Removed trailing spaces 2024-08-12 21:37:23 -04:00
Ejaz Ahmed
eea92750b0 Reverted original spacing 2024-08-12 21:33:17 -04:00
Ejaz Ahmed
3743e20f87 Updated harq feedback function 2024-08-12 20:54:24 -04:00
Ejaz Ahmed
497858ef37 Updated acknack_scheduling function 2024-08-12 18:08:50 -04:00
Ejaz Ahmed
c56f246dd1 Working version with MCS 1 with CBLAS on USRP B210 2024-08-12 17:41:19 -04:00
Ejaz Ahmed
0fae27e94c Updated default mcs value 2024-08-12 17:21:42 +00:00
Ejaz Ahmed
e12bf1500d Cleaned code and logs 2024-08-12 10:12:04 -07:00
Ejaz Ahmed
ba90296301 Updated is_ssynced condition; updated logs 2024-08-12 07:31:25 -07:00
Ejaz Ahmed
9530eefa24 Fixed compute_llr execution in case of Mod order 2 2024-08-08 18:05:10 +00:00
Ejaz Ahmed
ea4ed2abd8 Shift value reverted from 11 to 31 2024-08-08 16:45:14 +00:00
Ejaz Ahmed
aab3fd92f2 Setting ACK/NACK debug environment 2024-08-08 00:58:25 +00:00
Ejaz Ahmed
31985289a2 Added debug logs 2024-08-07 19:03:17 +00:00
Ejaz Ahmed
2c686dd805 Added noise 2024-08-06 20:22:16 +00:00
Laurent THOMAS
368a599dc7 remove-cblas-oai-5g 2024-08-06 20:20:00 +00:00
Ejaz Ahmed
8ab77553ad Fixed check_vcd error 2024-08-05 20:17:00 -04:00
David Kim
0788a62aaf Merge branch 'episys/sl-eurecom2' into episys/david/ack_nack_scheduling_for_USRP_test_gpio_change 2024-08-05 10:06:46 -07:00
Ejaz Ahmed
865df9eea6 Fixed compute_llr crash issue in first symbol code 2024-08-02 18:36:52 -07:00
David Kim
4aa058efd8 Fixed memory free issue. 2024-08-01 17:36:54 -04:00
David Kim
0aa31e7af2 Enabled some log for debug. 2024-08-01 17:19:11 -04:00
David Kim
4c065efd22 GPIO changed. 2024-08-01 16:34:37 -04:00
David Kim
2e5c6f7d8d Disabled LOG_I for USRP test. 2024-08-01 17:35:53 +00:00
Ejaz Ahmed
bb3fb6cbd0 Fixed previous index value of -1 2024-08-01 17:21:46 +00:00
David Kim
b6f04e3ccf Disabled LOG_I. 2024-08-01 17:20:05 +00:00
David Kim
92340ebd77 Disabled LOG_I for USRP test. 2024-07-31 18:50:48 -07:00
Ejaz Ahmed
8c9588739f Working version of HARQ feedback for first tx/rx in rfsim 2024-08-01 01:16:37 +00:00
Ejaz Ahmed
42112e849d Fix in the for multiple PSFCH period 2024-07-30 23:36:08 +00:00
Melissa
c40d0d1cb1 Merge branch 'episys/ea/harq_implementation' into 'episys/sl-eurecom2'
Implementation of HARQ first transmission and reception

See merge request aburger/openairinterface5g!282
2024-07-30 22:32:29 +00:00
Ejaz Ahmed
a1ec6c9ba2 First working version of tx/rx HARQ 2024-07-30 20:49:51 +00:00
Ejaz Ahmed
bcc632dbdd Merge branch 'episys/ea/harq_implementation' of gitlab.int-episci.com:aburger/openairinterface5g into episys/ea/harq_implementation 2024-07-29 15:32:10 +00:00
Ejaz Ahmed
a7f3cd98ec Merge branch 'episys/sl-eurecom2' into episys/ea/harq_implementation 2024-07-29 15:30:48 +00:00
Ejaz Ahmed
16f63c749d TDD memory allocation fixed 2024-07-27 02:21:19 +00:00
David Kim
7e8d791010 harq feedback slot scheduling update. 2024-07-26 15:38:59 -07:00
Ejaz Ahmed
7ed097874a Finding available feedback slot 2024-07-26 19:56:31 +00:00
Ejaz Ahmed
06bccb4087 Merge branch 'episys/sl-eurecom2' into episys/ea/harq_implementation 2024-07-26 19:55:02 +00:00
Melissa
f41b149a58 Merge branch 'episys/ea/rx_multiple_slsch_feedbacks' into 'episys/sl-eurecom2'
Implemented PSFCH RX with support for receiving multiple SLSCH's feedbacks

See merge request aburger/openairinterface5g!281
2024-07-26 18:26:32 +00:00
Ejaz Ahmed
5f829ddb35 Implemented PSFCH RX with support for receiving multiple SLSCH's feedbacks 2024-07-26 18:26:31 +00:00
Ejaz Ahmed
59a69b5020 Added PSFCH feedback slot computation method 2024-07-26 02:49:23 +00:00
Ejaz Ahmed
0845154ef8 Merge branch 'episys/ea/tx_multiple_slsch_feedbacks' into 'episys/sl-eurecom2'
Added Multiple SLSCH feedback support on PSFCH tx side

See merge request aburger/openairinterface5g!280
2024-07-24 20:41:01 +00:00
Ejaz Ahmed
34d2c4d917 Started code for ack nack scheduling 2024-07-24 00:32:52 +00:00
Ejaz Ahmed
9c6c8366af Updated memory allocation 2024-07-23 21:18:12 +00:00
Ejaz Ahmed
d9ede841a1 Fixed warnings 2024-07-23 16:33:19 +00:00
Ejaz Ahmed
47dc503ca6 Aligned code 2024-07-23 14:08:50 +00:00
Ejaz Ahmed
2516b5b3f1 Implemented HARQ process for first transmission and reception; cleaned code 2024-07-23 01:31:02 +00:00
Ejaz Ahmed
e6e925f9ab Removed HARQ related preconfigurations 2024-07-22 17:54:33 +00:00
Ejaz Ahmed
105f2b57ef Fixed slot conflicts in sidelink scheduler; Addressed formatting issues 2024-07-22 17:25:55 +00:00
Ejaz Ahmed
848e380cd0 Implemented PSFCH RX with support for receiving multiple SLSCH's feedbacks 2024-07-22 17:21:57 +00:00
Ejaz Ahmed
1cacd66352 Reverted line spacing 2024-07-22 16:42:17 +00:00
Ejaz Ahmed
286ef21839 Removed redudant slot from sidelink scheduler 2024-07-22 16:31:48 +00:00
Ejaz Ahmed
e88f0f5539 Fixed l value in computing alpha for pucch0 2024-07-22 16:28:47 +00:00
Ejaz Ahmed
b1d830adc2 Added multiple SLSCH feedback support in PSFCH 2024-07-22 16:25:37 +00:00
Ejaz Ahmed
36a29714ff Merge branch 'episys/ea/harq_structures_and_initialization' into 'episys/sl-eurecom2'
Created initial data structures for HARQ

See merge request aburger/openairinterface5g!278
2024-07-19 22:55:34 +00:00
Ejaz Ahmed
9fd148dedd Reverted MAX_SL_UE_CONNECTIONS default value 2024-07-11 20:12:45 +00:00
Ejaz Ahmed
378e6f5643 Merge branch 'episys/sl-eurecom2' into episys/ea/harq_structures_and_initialization 2024-07-11 20:01:13 +00:00
Melissa
15f8f5aeea Merge branch 'episys/ea/nearby_ue_sync_ref_ue_indication' into 'episys/sl-eurecom2'
Added code to send sync information from nearby to syncref

See merge request aburger/openairinterface5g!277
2024-07-11 19:08:35 +00:00
Ejaz Ahmed
f776b88d7f Created initial data structures for HARQ
Following changes are made:
1) Added essential data structures for HARQ
2) Moved gNB specific list functions to common file
3) Implemented preconfigurations for HARQ
4) Developed thread lock functions for NR_UE_SL_SCHED
5) Included header files for common moved functions in gNB code
2024-07-10 22:49:03 +00:00
Ejaz Ahmed
ea9289b2de Fixed order of SL UE phy params initializations 2024-07-10 20:11:10 +00:00
Ejaz Ahmed
30ce40cf03 Fixed PSFCH issue in sci_payload in case of psfch_period zero 2024-07-10 19:51:30 +00:00
Ejaz Ahmed
23300df806 Fixed line spacing 2024-07-10 18:10:03 +00:00
Ejaz Ahmed
d9acb85bfa Added PSFCH in sci_payload 2024-07-10 17:58:43 +00:00
Ejaz Ahmed
ec7b44e6dd Added code to send synchronization information from nearby to syncref
Added code to send synchronization information from nearby to syncref
within reserved bit of sci1. Syncref starts sending SLSCH once syncref
receives synchronization information.
2024-07-08 19:58:36 +00:00
Melissa
076c83b6f2 Merge branch 'episys/ea/Fixed_SNR_and_MCS_1_16_issues' into 'episys/sl-eurecom2'
Enabled support for MCS 1-16; Fixed SNR estimation

See merge request aburger/openairinterface5g!276
2024-06-20 13:49:47 +00:00
Ejaz Ahmed
616f759661 Enabled support for MCS 1-16; Fixed SNR estimation 2024-06-20 13:49:47 +00:00
matilde.costa
61e62abb7f Added non-ip types to ip_traffic_type_t 2024-06-06 14:06:28 +00:00
Ejaz Ahmed
281dc32c26 Updated confurations; formatted logs 2024-06-06 14:03:33 +00:00
Ejaz Ahmed
bb35caebed Fixed interface's name conflicts; restricted tx and rx operations in specific slots to fix an issue in USRP. 2024-06-06 13:56:59 +00:00
Melissa
1ff86924ff Merge branch 'episys/ea/usrp_debugging_psfch_csi_rs' into 'episys/sl-eurecom2'
Fixed interface's name conflicts; restricted tx and rx  operations in specific slots to fix an issue in USRP.

See merge request aburger/openairinterface5g!274
2024-05-30 22:38:11 +00:00
Ejaz Ahmed
e13e26759e Fixed interface's name conflicts; restricted tx and rx operations in specific slots to fix an issue in USRP. 2024-05-30 22:38:11 +00:00
matilde.costa
9588e10de0 Added non-ip types to ip_traffic_type_t 2024-05-17 14:58:54 +02:00
Ejaz Ahmed
885d5cd426 Updated logs & fixed spacing issues 2024-05-03 16:48:43 -07:00
Matilde Costa
6536425c4b rlc/pdcp threads with -1 affinity 2024-05-03 16:30:53 -07:00
Ejaz Ahmed
c7e08dffbe Added separate conf files for sync_ref & nearby ue; reverted tx scheduling conditions 2024-05-03 16:23:03 -07:00
Ejaz Ahmed
d2475e0dd6 Added separate conf files for sync_ref & nearby ue; reverted tx scheduling conditions 2024-05-01 16:46:52 -07:00
Ejaz Ahmed
c584baf9e1 Merge branch 'episys/sl-eurecom2' into eurecom/sl-eurecom2
Following modifications are included in this merge:
1) Implemented CSI reporting
2) Developed a measurement function of SNR and computed CQI based on
that
3) Simplified functions
4) Improved logging
5) Cleaned code
6) Fixed pointers issues
2024-04-30 10:52:54 -07:00
Melissa
6fcda3dcc0 Merge branch 'episys/ea/5g_sidelink_csi' into 'episys/sl-eurecom2'
Implemented measurement of SNR and computed CQI; Updated tx and rx code of CSI reporting

See merge request aburger/openairinterface5g!273
2024-04-30 15:50:27 +00:00
Ejaz Ahmed
3e81184deb Implemented measurement of SNR and computed CQI; Updated tx and rx code of CSI reporting 2024-04-30 15:50:27 +00:00
matilde.costa
4e2b8ddb92 fix nas_config in rrc sl preconfiguration for tun interface name 2024-04-25 15:39:15 +02:00
Matilde Costa
e8ca12049a rlc/pdcp threads with -1 affinity 2024-04-25 11:08:02 +02:00
Raymond Knopp
e9ff59611d check of PSFCH pointer in ue_scheduler 2024-04-28 21:42:27 +02:00
Raymond Knopp
fb6baf3f76 check for PSFCH pointer definition 2024-04-28 21:26:19 +02:00
Raymond Knopp
18e9694f31 more debugging removal 2024-04-22 16:19:47 +02:00
Raymond Knopp
183e029c8c removed some logging 2024-04-22 16:16:37 +02:00
Raymond Knopp
da97a8f016 debugging info 2024-04-22 15:47:24 +02:00
Raymond Knopp
1a470d5af6 logging for debug 2024-04-26 16:52:15 +02:00
Ejaz Ahmed
c4250dcd2b Fixed MAC subpdu header; fixed multiple interface issue 2024-04-19 11:56:47 -07:00
Ejaz Ahmed
4c4a667fd6 Bug fixed and freed memorey in case of no psfch; set two interfaces 2024-04-19 11:31:44 -07:00
Melissa
da6f3251f3 Merge branch 'episys/ea/fix_mac_subheaders_length_issue' into 'episys/sl-eurecom2'
Fixed NR_SLSCH_MAC_SUBHEADER processing issue

See merge request aburger/openairinterface5g!272
2024-04-19 16:53:50 +00:00
Raymond Knopp
c534570eec added srcid to nas_config for SL 2024-04-19 16:27:32 +02:00
Raymond Knopp
9642a70e6d testing and bugfixing 2024-04-19 16:10:35 +02:00
Raymond Knopp
1c84699e00 handled freeing of PSFCH information in case PSFCH_Period = 0 2024-04-23 06:07:18 +02:00
Ejaz Ahmed
9d8db83ebd Fixed spacing 2024-04-18 16:11:54 -07:00
Ejaz Ahmed
9ceb3ddf93 Merge branch 'episys/sl-eurecom2' into episys/ea/fix_mac_subheaders_length_issue 2024-04-18 16:08:07 -07:00
Melissa
289991b0fe Merge branch 'episys/ea/fix_errors_with_disabled_psfch' into 'episys/sl-eurecom2'
Enabled No PSFCH Support

See merge request aburger/openairinterface5g!271
2024-04-18 22:21:44 +00:00
Ejaz Ahmed
38a43f3be6 Updated comment 2024-04-18 13:06:40 -07:00
Ejaz Ahmed
6fc72eae0f Reverted the debugging logs 2024-04-18 13:00:58 -07:00
Ejaz Ahmed
14420f24cb Additional conditions on rx csi-rs scheduling 2024-04-18 11:59:50 -07:00
Ejaz Ahmed
53aa746075 Fixing errors in case of 12 PSSCH symbols and 3 PSCCH channels 2024-04-17 19:50:15 -07:00
Ejaz Ahmed
4e10e4fa2c Fixed MAC subPDU header length issue 2024-04-17 11:59:34 -07:00
Ejaz Ahmed
9879c13cd4 Added option in conf file to activate/deactivate csi-rs 2024-04-17 10:36:00 -07:00
Ejaz Ahmed
63454cebf8 Added option in conf file to activate/deactivate csi-rs 2024-04-17 10:30:31 -07:00
Ejaz Ahmed
813b600305 Implemented CSI-RS transmission and reception. 2024-04-16 19:26:01 -07:00
Ejaz Ahmed
9f9dadf621 Replaced slots per frame variable to use appropriate one 2024-04-16 19:25:23 -07:00
Melissa
bb13bfa195 Merge branch 'episys/ea/5g_sidelink_csi_rs' into 'episys/sl-eurecom2'
Implemented CSI-RS transmission and reception.

See merge request aburger/openairinterface5g!270
2024-04-16 22:43:25 +00:00
Ejaz Ahmed
ee7244ca05 Implemented CSI-RS transmission and reception. 2024-04-16 22:43:25 +00:00
Ejaz Ahmed
05604174e0 Replaced slots per frame variable to use appropriate one 2024-03-19 12:22:35 -07:00
Ejaz Ahmed
cbcd09cbca Merge branch 'episys/ea/mac_headers_validation' into episys/sl-eurecom2 2024-02-23 08:35:42 -08:00
Ejaz Ahmed
4af8be50bd Added condition to check remaining buffer before creating MAC CE 2024-02-23 08:34:43 -08:00
Ejaz Ahmed
ef9f804da7 Adjusted loop execution to fix muliple SDUs placement before MAC CEs and padding 2024-02-22 14:30:41 -08:00
Ejaz Ahmed
a465e39bb9 Fixed issue with multiple SDUs placement before MAC CEs 2024-02-22 14:14:56 -08:00
Melissa
3370570ecd Merge branch 'episys/ea/mac_headers_validation' into 'episys/sl-eurecom2'
Added SLSCH MAC sub-header, updated MAC sub-headers based on spec. 38321

See merge request aburger/openairinterface5g!269
2024-02-22 00:22:39 +00:00
Ejaz Ahmed
29b74e7410 Added SLSCH MAC sub-header, updated MAC sub-headers based on spec. 38321 2024-02-22 00:22:39 +00:00
Ejaz Ahmed
3fa03965a1 reverted some changes; added sec label, modified variable name 2024-02-21 11:49:31 -08:00
Ejaz Ahmed
d7b1a78e71 Merge branch 'episys/sl-eurecom2' into episys/ea/mac_headers_validation
Following changes are made:
1) Added instructions in rfsim README.md for running
rfsimulator with updated sl_preconfiguration.conf location
2024-02-21 11:32:25 -08:00
Ejaz Ahmed
a2e75e10d3 Merge branch 'eurecom/sl-eurecom2' into episys/sl-eurecom2 2024-02-21 11:30:54 -08:00
Ejaz Ahmed
714629c26f Added SLSCH MAC subheader, updated MAC subheaders based on spec. 38321
Following changes are made:
1) Added SLSCH MAC subheader
2) Validated MAC SDU subheader
3) Added SL_BSR subheader
4) Modified & validated MAC subheaders processing on tx and rx
2024-02-21 11:17:13 -08:00
Ejaz Ahmed
9e686e448d 5G sidelink PSFCH Tx implementation
Updates covered in this commit:
1) Computed feedback slot based on PSFCH time gap, PSFCH period and HARQ
	    feedback
2) Generated PSFCH pdu
3) Implemented PSFCH scheduling
4) Allocated PRBs based on slot and subchannel
5) Updated data structures accordingly
6) Modified configuration computation for PSFCH PRB set
7) Changed computation for number of PSFCH symbols
8) Moved sl_preconfiguration.conf under NR-SIDELINK/CONF
2024-02-16 10:50:02 -08:00
Melissa
5a88bb670a Merge branch 'episys/ea/psfch_configurations' into 'episys/sl-eurecom2'
Removed send_psfch_with_pucch command line argument

See merge request aburger/openairinterface5g!267
2024-02-16 09:13:22 -08:00
Melissa
b4a314b64e Updated prconfiguration code & Moved configuration file 2024-02-16 09:13:01 -08:00
Deokseong "David" Kim
6be609a59f picked 907130d9 2024-02-16 09:00:36 -08:00
Ejaz Ahmed
69c357655e Fixed spacing issue 2024-02-15 10:20:55 -08:00
Melissa
45dd2a7fb0 Merge branch 'episys/ea/tx_psfch' into 'episys/sl-eurecom2'
PSFCH Tx implementation: PSFCH PDU generation, scheduling and PRBs allocation

See merge request aburger/openairinterface5g!268
2024-02-15 16:30:42 +00:00
Ejaz Ahmed
b5dd8de98f PSFCH Tx implementation: PSFCH PDU generation, scheduling and PRBs allocation 2024-02-15 16:30:42 +00:00
Melissa
a42a4d1a06 Merge branch 'episys/ea/psfch_configurations' into 'episys/sl-eurecom2'
Removed send_psfch_with_pucch command line argument

See merge request aburger/openairinterface5g!267
2024-01-30 16:50:45 +00:00
Ejaz Ahmed
3c485239ba Removed resetting of psfch based on pucch based psfch transmission 2024-01-30 16:46:22 +00:00
Ejaz Ahmed
14b972e878 Removed header file 2024-01-30 16:44:25 +00:00
Ejaz Ahmed
aff9391806 Merge branch 'episys/sl-eurecom2' into episys/ea/psfch_configurations 2024-01-30 16:43:41 +00:00
Ejaz Ahmed
c734cfab93 Removed help MACRO for command line psfch argument 2024-01-30 16:30:14 +00:00
Ejaz Ahmed
3dd8395c8f Removed flag for send_psfch_with_pucch 2024-01-30 16:24:03 +00:00
Ejaz Ahmed
99a750d672 Merge branch 'episys/ea/psfch_configurations' of gitlab.int-episci.com:aburger/openairinterface5g into episys/ea/psfch_configurations 2024-01-30 15:09:46 +00:00
Ejaz Ahmed
82dfb5c4ec Reverteunnecessary changes 2024-01-30 15:09:13 +00:00
Melissa
7fd180f30b Merge branch 'episys/ea/psfch_configurations' into 'episys/sl-eurecom2'
Added functionality to read PSFCH configurations from conf file

See merge request aburger/openairinterface5g!266
2024-01-30 15:09:11 +00:00
Ejaz Ahmed
f52f258eec Added functionality to read PSFCH configurations from conf file 2024-01-30 15:09:11 +00:00
Melissa Elkadi
fdad2f7d17 Fixing more white space 2024-01-30 13:59:32 +00:00
Melissa Elkadi
1245c05385 Reverting whitespace changes 2024-01-30 13:58:00 +00:00
Melissa Elkadi
e534761719 updating the name of psfch_pucch variable and clean up 2024-01-30 13:54:13 +00:00
Ejaz Ahmed
2976628409 Added PSFCH configurations; Ignored number of psfch symbols
a) Added PSFCH configurations in conf file for TX resource pool;
b) In case of pucch based psfch transmission, ignored number of psfch
symbols for number of pssch symbols calculation
2024-01-30 02:59:55 +00:00
Ejaz Ahmed
34aede6ee5 Moved conf file to conf directory; long bit replace with hex numbers 2024-01-27 17:32:28 +00:00
Ejaz Ahmed
d2bbbb16ad Temporarily Removed number of PSFCH symbols from number of PSSCH symbhols computation 2024-01-26 21:05:49 +00:00
Ejaz Ahmed
7e83f75d21 Added functionality to take PSFCH Preconfigurations from conf file 2024-01-26 20:36:53 +00:00
Ejaz Ahmed
c4706eda69 Added further logs 2024-01-25 19:56:47 +00:00
Ejaz Ahmed
28f2129d3e Added harq_feedback condition; Added more logs 2024-01-25 17:14:57 +00:00
Ejaz Ahmed
238a7837cf Added updated configuration file for psfch 2024-01-24 20:25:40 +00:00
Ejaz Ahmed
e474090459 Added sl_preconfiguration file 2024-01-24 18:44:10 +00:00
Ejaz Ahmed
6f5205ec1c Commented out Rx to Tx notification mechanism; added configurations 2024-01-24 18:38:38 +00:00
Ejaz Ahmed
f5250c1ec4 Added but commented out due to issue with slsch reception 2024-01-23 21:22:43 +00:00
Ejaz Ahmed
156b806abb Updated code for psfch tx side 2024-01-15 22:49:53 +00:00
Ejaz Ahmed
d4e030cc3b Added more parameters in psfch pdu 2024-01-09 02:04:07 +00:00
Ejaz Ahmed
cb17a2530c Added Pre-configurations, created psfch pdu, scheduled psfch for transmission 2024-01-06 01:37:14 +00:00
Deokseong "David" Kim
907130d999 Merge branch 'episys/ea/fixed_pscch_slot_conflict_psbch' into 'episys/sl-eurecom2'
Fixed issue with reception of PSBCH

See merge request aburger/openairinterface5g!265
2023-12-21 18:03:08 +00:00
Ejaz Ahmed
d201d89c94 Fixed issue with reception of PSBCH 2023-12-21 18:03:08 +00:00
Raymond Knopp
5cc6d9e5c3 Merge branch 'sl-eurecom2' of https://gitlab.eurecom.fr/oai/openairinterface5g into sl-eurecom2 2023-10-14 07:19:44 +02:00
Raymond Knopp
1a815f7e15 warnings 2023-10-14 07:19:29 +02:00
ue1
05cb48d29c GPIO changes 2023-10-13 16:00:35 -04:00
Raymond Knopp
911bd2be5d removed some assertions after bogus reception of PSCCH 2023-10-13 16:34:24 +02:00
ue1
5ea68eb132 Merge branch 'sl-eurecom2' of https://gitlab.eurecom.fr/oai/openairinterface5g into sl-eurecom2 2023-10-13 09:36:05 -04:00
ue1
94188666ce removed some assertions 2023-10-13 09:35:43 -04:00
Raymond Knopp
a6d86ea8c9 Merge branch 'sl-eurecom2' of https://gitlab.eurecom.fr/oai/openairinterface5g into sl-eurecom2 2023-10-13 09:12:33 -04:00
Raymond Knopp
d3702751ec removal of logs 2023-10-13 09:12:13 -04:00
ue1
63b3d8a92f testing 2023-10-13 08:25:31 -04:00
Raymond Knopp
597c897977 improving stat 2023-10-13 06:33:18 -04:00
Raymond Knopp
d1bbbb5dd3 analytics of PSCCH/PSSCH 2023-10-12 11:50:16 +02:00
Raymond Knopp
18853ab6cc supression of logs 2023-10-12 08:11:06 +02:00
Raymond Knopp
9cc948635c Merge branch 'sl-eurecom2' of https://gitlab.eurecom.fr/oai/openairinterface5g into sl-eurecom2 2023-10-12 07:41:57 +02:00
Raymond Knopp
93d4a07932 TX path MAC PDU fix 2023-10-12 07:41:35 +02:00
Raymond Knopp
6bfe76b086 MAC pdu fixes, testing RX patch of rlc/pdcp/sdap 2023-10-12 07:40:39 +02:00
Raymond Knopp
e568b2c85a fix for MAC subheader handling in SL 2023-10-12 00:35:49 +02:00
Raymond Knopp
435b636d89 minor changes 2023-10-11 22:20:12 +02:00
Raymond Knopp
84504a38a0 small fixes for LCID/SLRB ids 2023-10-11 06:28:31 -04:00
ue1
4bd3007565 removal of many debugging logs, added pscch/pssch statistics, TX/RX switching time increase (3->4 slots 2023-10-11 05:25:12 -04:00
Raymond Knopp
dad4240016 merged pdcp/rlc components to current L1/L2 2023-10-09 23:08:11 +02:00
Raymond Knopp
2cda03b016 compilation ok 2023-10-09 22:44:08 +02:00
Raymond Knopp
198c319788 intermediate commit 2023-10-05 21:20:58 +02:00
Raymond Knopp
18d720f377 fixed issue with demux of SCI1/SCI2/SLSCH in SLSCH receiver. Added skeleton for MAC parsing on RX for SL. 2023-10-02 02:58:40 +02:00
Raymond Knopp
ba6a8554a3 minor changes 2023-09-28 21:14:48 +02:00
Raymond Knopp
ffda9c758a removed logs and added a bit more temporary debugging for SCI2 2023-09-18 15:49:13 +02:00
Raymond Knopp
60a7eb326c adding color defs for printing 2023-09-18 10:07:37 +02:00
Raymond Knopp
6a5a9f18bf testing sci2/slsch 2023-09-18 09:34:51 +02:00
Raymond Knopp
4bf5166aed integration of PSSCH with PUSCH TX 2023-09-07 21:38:38 +02:00
Raymond Knopp
d4e30b972b PSCCH RX testing 2 2023-08-25 09:19:13 +02:00
Raymond Knopp
858a13119b sci1a RX testing 2023-08-24 21:56:32 +02:00
Raymond Knopp
5b16b58496 debugging memory leaks 2023-08-22 00:27:26 +02:00
Raymond Knopp
0588003034 testing SCI1A 2023-08-21 21:02:30 +02:00
Raymond Knopp
b8d9da2e81 sci/slsch mac step1 2023-08-19 08:58:44 +02:00
Raymond Knopp
8199a1e093 fixes after merge with NR_SL_PSBCH_2 2023-08-03 23:26:54 +02:00
Raymond Knopp
7efe5880a1 Merge branch 'NR_SL_PSBCH_2' into sl-eurecom2 2023-08-03 15:50:49 +02:00
Raymond Knopp
b9caf3ecc4 Merge branch 'NR_SL_PSBCH_2' of https://gitlab.eurecom.fr/oai/openairinterface5g into NR_SL_PSBCH_2 2023-08-03 15:50:02 +02:00
Raghavendra Dinavahi
4ca508228f Enable SCOPE for PSBCH
- PSBCH LLR, PSBCH IQ, PSBCH RSRP, CIR added in scope.
	- use --dqt or --d  option to enable scope on the RX UE
	- -d option does not show RSRP
2023-08-03 14:55:16 +02:00
Raymond Knopp
9ecd473a41 Merge branch 'sl_eurecom_integration' into sl-eurecom2
Conflicts:
	CMakeLists.txt
2023-08-03 10:21:42 +02:00
Raymond Knopp
f32c759ecf modifications to allow running SL without --phy-test flag 2023-08-03 10:19:07 +02:00
Raghavendra Dinavahi
88b6cdd209 Changes for Sidelink RFSIM testing
- UE1 is a SYNC REFERENCE UE - TX PSBCH
	   started using command -
		sudo RFSIMULATOR=server ./nr-uesoftmodem --rfsim --phy-test --sl-mode 2 --sync-ref
	- UE2 syncs onto UE1 - RX PSBCH and continues to receive PSBCH
	   started using command -
		sudo ./nr-uesoftmodem --rfsim --phy-test --sl-mode 2
	- In the default use case 2 Sidelink SSBs sent over 16 frames.
2023-08-02 02:30:21 +02:00
Raghavendra Dinavahi
8bb2f3991b Sidelink SLSS SEARCH Procedure 2023-08-02 02:28:25 +02:00
Raghavendra Dinavahi
4d369a6993 Sidelink config MAC->PHY, PSBCH scheduler and supporting functions
- Phy config update and Sidelink frame parameters initialisation
	- PSBCH scheduler to trigger TX PSBCH/RX PSBCH actions
	- Sidelink indication with rx ind to trigger send SL-MIB to MAC
2023-08-02 02:28:25 +02:00
Raghavendra Dinavahi
70f586cb3c Sidelink configuration passed from RRC->MAC, defined interface functions
- Phy configuration will be prepared by MAC
	- Sidelink preconfiguration parameters passed from RRC->MAC
	- Only 1 SSB TA allocation used
	- psbch payload prepared by MAC after receiving the tx slss req
2023-08-02 02:28:25 +02:00
Raghavendra Dinavahi
745cc733ea PSBCH RX TX changes
- RX/TX Phy processing accg to 38.211, 38.212 Rel16
	- Rate matching fix from Ralf to address 1782 bits
		- do not try to group the last bits, process them manually
	- PSBCH simulator used to validate TX/RX phy processing
2023-08-02 02:28:25 +02:00
Raymond Knopp
ee7aacf2ca sci development 2023-07-26 21:08:48 +02:00
Raymond Knopp
fef6303cc9 initial commit of SCI encoding 2023-07-22 23:07:11 +02:00
159 changed files with 19721 additions and 2227 deletions

View File

@@ -163,8 +163,8 @@ set(CMAKE_CXX_FLAGS
add_boolean_option(SANITIZE_ADDRESS False "enable the address sanitizer (ASan)" ON)
if (SANITIZE_ADDRESS)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer -fno-common")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer -fno-common")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fstack-check -fno-omit-frame-pointer -fno-common")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fstack-check -fno-omit-frame-pointer -fno-common")
# There seems to be some incompatibility with pthread_create and the RT scheduler, which
# results in pthread_create hanging.
#
@@ -689,6 +689,7 @@ target_link_libraries(SCHED_UE_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
set(SCHED_SRC_NR_UE
${OPENAIR1_DIR}/SCHED_NR_UE/phy_procedures_nr_ue.c
${OPENAIR1_DIR}/SCHED_NR_UE/phy_procedures_nr_ue_sl.c
${OPENAIR1_DIR}/SCHED_NR_UE/fapi_nr_ue_l1.c
${OPENAIR1_DIR}/SCHED_NR_UE/phy_frame_config_nr_ue.c
${OPENAIR1_DIR}/SCHED_NR_UE/harq_nr.c
@@ -1060,8 +1061,20 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/sss_nr.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/cic_filter_nr.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_pbch.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_psbch_rx.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_psbch_tx.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_psfch_tx.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_pscch_tx.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ue_pucch_rx.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dci.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dci_tools.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
@@ -1081,11 +1094,14 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/NR_REFSIG/dmrs_nr.c
${OPENAIR1_DIR}/PHY/NR_REFSIG/ptrs_nr.c
${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold_ue.c
${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold.c
${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gen_mod_table.c
${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c
${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c
${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/nr_adjust_gain.c
${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_measurements_gNB.c
${OPENAIR1_DIR}/PHY/TOOLS/file_output.c
${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c
# ${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c
@@ -1120,8 +1136,8 @@ target_link_libraries(PHY_COMMON PRIVATE asn1_lte_rrc_hdrs)
add_library(PHY ${PHY_SRC})
target_link_libraries(PHY PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
pkg_check_modules(blas REQUIRED blas)
pkg_check_modules(lapacke REQUIRED lapacke)
#pkg_check_modules(blas REQUIRED blas)
#pkg_check_modules(lapacke REQUIRED lapacke)
add_library(PHY_UE ${PHY_SRC_UE})
target_link_libraries(PHY_UE PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
@@ -1352,7 +1368,7 @@ set (MAC_NR_SRC
set (MAC_SRC_UE
${PHY_INTERFACE_DIR}/phy_stub_UE.c
# ${PHY_INTERFACE_DIR}/phy_stub_UE.c
${PHY_INTERFACE_DIR}/queue_t.c
${MAC_DIR}/main_ue.c
${MAC_DIR}/ue_procedures.c
@@ -1366,13 +1382,17 @@ set (MAC_NR_SRC_UE
${NR_UE_PHY_INTERFACE_DIR}/NR_IF_Module.c
${NR_UE_PHY_INTERFACE_DIR}/NR_Packet_Drop.c
${NR_UE_MAC_DIR}/config_ue.c
${NR_UE_MAC_DIR}/config_ue_sl.c
${NR_UE_MAC_DIR}/mac_vars.c
${NR_UE_MAC_DIR}/main_ue_nr.c
${NR_UE_MAC_DIR}/nr_ue_procedures.c
${NR_UE_MAC_DIR}/nr_ue_procedures_sl.c
${NR_UE_MAC_DIR}/nr_ue_scheduler.c
${NR_UE_MAC_DIR}/nr_ue_dci_configuration.c
${NR_UE_MAC_DIR}/nr_ra_procedures.c
${NR_UE_MAC_DIR}/nr_ue_power_procedures.c
${NR_UE_MAC_DIR}/nr_ue_sci_slsch.c
${NR_UE_MAC_DIR}/nr_slsch_scheduler.c
)
set (ENB_APP_SRC
@@ -1876,8 +1896,6 @@ set (SIMUSRC
)
add_library(SIMU STATIC ${SIMUSRC} )
target_include_directories(SIMU PUBLIC ${OPENAIR1_DIR}/SIMULATION/TOOLS ${OPENAIR1_DIR}/SIMULATION/RF)
target_link_libraries(SIMU PRIVATE ${blas_LIBRARIES} ${cblas_LIBRARIES} ${lapacke_LIBRARIES})
target_include_directories(SIMU PRIVATE ${blas_INCLUDE_DIRS} ${lapacke_INCLUDE_DIRS})
# Qt-based scope
add_boolean_option(ENABLE_NRQTSCOPE OFF "Build the Qt-Scope" OFF)
@@ -2225,6 +2243,24 @@ target_link_libraries(nr_pbchsim PRIVATE
)
target_link_libraries(nr_pbchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_executable(nr_psbchsim
${OPENAIR1_DIR}/SIMULATION/NR_PHY/psbchsim.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
${OPENAIR_DIR}/executables/softmodem-common.c
${OPENAIR2_DIR}/RRC/NAS/nas_config.c
${NR_UE_RRC_DIR}/rrc_nsa.c
${NFAPI_USER_DIR}/nfapi.c
${NFAPI_USER_DIR}/gnb_ind_vars.c
${PHY_INTERFACE_DIR}/queue_t.c
${T_SOURCE}
${SHLIB_LOADER_SOURCES}
)
target_link_libraries(nr_psbchsim PRIVATE
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group
m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl shlib_loader
)
target_link_libraries(nr_psbchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
#PUCCH ---> Prashanth
add_executable(nr_pucchsim

376
README.md
View File

@@ -1,74 +1,330 @@
<h1 align="center">
<a href="https://openairinterface.org/"><img src="https://openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png" alt="OAI" width="550"></a>
</h1>
# OAI-SL-MultiUE-Broker
<p align="center">
<a href="https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-OAI--Public--V1.1-blue" alt="License"></a>
<a href="https://releases.ubuntu.com/18.04/"><img src="https://img.shields.io/badge/OS-Ubuntu18-Green" alt="Supported OS Ubuntu 18"></a>
<a href="https://releases.ubuntu.com/20.04/"><img src="https://img.shields.io/badge/OS-Ubuntu20-Green" alt="Supported OS Ubuntu 20"></a>
<a href="https://releases.ubuntu.com/22.04/"><img src="https://img.shields.io/badge/OS-Ubuntu22-Green" alt="Supported OS Ubuntu 22"></a>
<a href="https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux"><img src="https://img.shields.io/badge/OS-RHEL8-Green" alt="Supported OS RHEL8"></a>
<a href="https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux"><img src="https://img.shields.io/badge/OS-RHEL9-Green" alt="Supported OS RELH9"></a>
<a href="https://getfedora.org/en/workstation/"><img src="https://img.shields.io/badge/OS-Fedore37-Green" alt="Supported OS Fedora 37"></a>
</p>
<p align="center">
<a href="https://jenkins-oai.eurecom.fr/job/RAN-Container-Parent/"><img src="https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fjenkins-oai.eurecom.fr%2Fjob%2FRAN-Container-Parent%2F&label=build%20Images"></a>
</p>
<p align="center">
<a href="https://hub.docker.com/r/oaisoftwarealliance/oai-gnb"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/oaisoftwarealliance/oai-gnb?label=gNB%20docker%20pulls"></a>
<a href="https://hub.docker.com/r/oaisoftwarealliance/oai-nr-ue"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/oaisoftwarealliance/oai-nr-ue?label=NR-UE%20docker%20pulls"></a>
<a href="https://hub.docker.com/r/oaisoftwarealliance/oai-enb"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/oaisoftwarealliance/oai-enb?label=eNB%20docker%20pulls"></a>
<a href="https://hub.docker.com/r/oaisoftwarealliance/oai-lte-ue"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/oaisoftwarealliance/oai-lte-ue?label=LTE-UE%20docker%20pulls"></a>
</p>
## RFSim Broker based Multiple UEs Test
# OpenAirInterface License #
This part test is based on sl-eurecom4 branch on openairinterface5g.
(https://gitlab.eurecom.fr/oai/openairinterface5g.git)
* [OAI License Model](http://www.openairinterface.org/?page_id=101)
* [OAI License v1.1 on our website](http://www.openairinterface.org/?page_id=698)
It is distributed under **OAI Public License V1.1**.
The license information is distributed under [LICENSE](LICENSE) file in the same directory.
Please see [NOTICE](NOTICE.md) file for third party software that is included in the sources.
# Where to Start #
* [General overview of documentation](./doc/README.md)
* [The implemented features](./doc/FEATURE_SET.md)
* [How to build](./doc/BUILD.md)
* [How to run the modems](./doc/RUNMODEM.md)
Not all information is available in a central place, and information for
specific sub-systems might be available in the corresponding sub-directories.
To find all READMEs, this command might be handy:
## To start
First go to the correct repository :
```
find . -iname "readme*"
cd openairinterface5g/cmake_targets
```
To install zeroMQ :
```
apt-get install libzmq3-dev
```
Then start compilation :
```
sudo ./build_oai --nrUE -w SIMU --cmake-opt -DENABLE_T_TRACER=OFF
```
Or, to start a clean start compilation, do the clean up first then compile :
```
sudo ./build_oai -c -C
sudo ./build_oai -I --cmake-opt -DENABLE_T_TRACER=OFF
```
Now we need to create three UEs through namespaces:
```
cd openairinterface5g/cmake_targets
sudo ./multi-ue.sh -c1 -c2 -c3
```
* It is likely the new system would face the ASN.1 error, which is due to the wrong version of ASN.1. To fix it, please do the following:
* Remove the current wrong version :
```
sudo rm -rf /opt/asn1c
sudo rm -rf /tmp/asn1c
```
* Clone and checkout the exact same commit:
```
cd /tmp
git clone https://github.com/mouse07410/asn1c.git
cd asn1c
git checkout 657f5790
```
* Build and install the correct version :
```
git submodule update --init --recursive
autoreconf -iv
./configure --prefix=/opt/asn1c
make -j$(nproc)
sudo make install
```
* Then recompile. Do remember to delete the wrong /ran_build files :
```
cd ~/OAI-SL-Broker/openairinterface5g/cmake_targets
rm -rf ran_build
sudo ./build_oai --nrUE -w SIMU --cmake-opt -DENABLE_T_TRACER=OFF
```
## Start RFSim for Multiple UEs through Broker
### Launch Broker (outside namespace):
```
cd ran_build/build/
./broker
```
# RAN repository structure #
### Launch SYNC-REF (namespace 1):
```
sudo ./multi-ue.sh -o1
cd ran_build/build/
sudo RFSIMULATOR=server ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf --sl-mode 2 --sa --sync-ref --brokerip 10.201.1.100
```
The OpenAirInterface (OAI) software is composed of the following parts:
### Launch UE2 (namespace 2):
```
sudo ./multi-ue.sh -o2
cd ran_build/build/
sudo ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue1.conf --sl-mode 2 --sa --brokerip 10.202.1.100 --device_id 1 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
```
### Launch UE3 (namespace 3):
```
sudo ./multi-ue.sh -o3
cd ran_build/build/
sudo ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue2.conf --sl-mode 2 --sa --brokerip 10.203.1.100 --device_id 2 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
```
Optional : You can now quickly check the connection to sync-ref from two UEs :
```
ping -I oaitun_ue2 10.0.0.1
ping -I oaitun_ue3 10.0.0.1
```
Note: when restart the simulation, you might need to kill everything first by the following command :
```
sudo pkill -f nr-uesoftmodem
sudo pkill -f broker
sudo pkill -f rfsimulator
```
## Monitor route with Babel and Wireshark
You might need to first install Babel onto the local machine
```
openairinterface5g
├── charts
├── ci-scripts : Meta-scripts used by the OSA CI process. Contains also configuration files used day-to-day by CI.
├── CMakeLists.txt : Top-level CMakeLists.txt for building
├── cmake_targets : Build utilities to compile (simulation, emulation and real-time platforms), and generated build files.
├── common : Some common OAI utilities, some other tools can be found at openair2/UTILS.
├── doc : Documentation
├── docker : Dockerfiles to build for Ubuntu and RHEL
├── executables : Top-level executable source files (gNB, eNB, ...)
├── maketags : Script to generate emacs tags.
├── nfapi : (n)FAPI code for MAC-PHY interface
├── openair1 : 3GPP LTE Rel-10/12 PHY layer / 3GPP NR Rel-15 layer. A local Readme file provides more details.
├── openair2 : 3GPP LTE Rel-10 RLC/MAC/PDCP/RRC/X2AP + LTE Rel-14 M2AP implementation. Also 3GPP NR Rel-15 RLC/MAC/PDCP/RRC/X2AP.
├── openair3 : 3GPP LTE Rel10 for S1AP, NAS GTPV1-U for both ENB and UE.
├── openshift : OpenShift helm charts for some deployment options of OAI
├── radio : Drivers for various radios such as USRP, AW2S, RFsim, ...
└── targets : Some configuration files; only historical relevance, and might be deleted in the future
sudo apt update
sudo apt install babeld
```
### Launch SYNC-REF (namespace 1):
First go into the correct namespace :
```
sudo ./multi-ue.sh -o1
```
In order to have a readable address at the logside, we'll hardcode the IP address through following command, so sync-ref will be translate as 'fe80::1/64'
```
sudo ip netns exec ue1 ip -6 addr add fe80::1/64 dev oaitun_ue1 nodad
```
Then launch Babel on sync-ref :
```
ip netns exec ue1 bash -lc '
set -e
cat > /tmp/babeld-ue1.conf <<EOF
interface oaitun_ue1
redistribute local deny
pid-file /tmp/babeld-ue1.pid
EOF
babeld -d 1 -c /tmp/babeld-ue1.conf
'
```
For now, as no other UE is connected, sync-ref will simply print its local id.
### Launch UE2 (namespace 2):
First go into the correct namespace :
```
sudo ./multi-ue.sh -o2
```
To make it easier to observe, UE2 will be allocated address as 'fe80::2/64' by following command :
```
sudo ip netns exec ue2 ip -6 addr add fe80::2/64 dev oaitun_ue2 nodad
```
Then launch Babel on UE2 :
```
ip netns exec ue2 bash -lc '
set -e
cat > /tmp/babeld-ue2.conf <<EOF
interface oaitun_ue2
redistribute local deny
pid-file /tmp/babeld-ue2.pid
EOF
babeld -d 1 -c /tmp/babeld-ue2.conf
'
```
### Launch UE3 (namespace 3):
First go into the correct namespace :
```
sudo ./multi-ue.sh -o3
```
UE3 will be allocated address as 'fe80::3/64'
```
sudo ip netns exec ue3 ip -6 addr add fe80::3/64 dev oaitun_ue3 nodad
```
Then launch Babel on UE3 :
```
ip netns exec ue3 bash -lc '
set -e
cat > /tmp/babeld-ue3.conf <<EOF
interface oaitun_ue3
redistribute local deny
pid-file /tmp/babeld-ue3.pid
EOF
babeld -d 1 -c /tmp/babeld-ue3.conf
'
```
Note : On babel, it will show neighbour connection with 'Neighbour ... rxcost 96 txcost 65535...', when it's 96, it means perfect connection, 65535 means a bad connection, if the connection is bad when generating the UE3, try to kill and restart again.
### Wireshark monitor
Within the each namespace, you can start wireshark with filter on each node to check the Babel messages (example as for sync-ref, please update the oaitun_ueX name for each UE):
```
sudo wireshark -i oaitun_ue1 -k &
```
You should be able to see 'Babel Hello' message, and 'Babel Hello ihu'. ihu representing 'I hear you'.
When there are two UEs connecting to sync-ref at the same time, you should be able to see 'Babel Hello ihu ihu'
## Enable TAP in RFSim for Multiple UEs
This part is to switch from default TUN to TAP.
The baseline is, by default, system is running through TUN. In order to enable TAP, when you run each node simply add a flag at the begining: " OAI_TUNTAP_MODE=tap".
Optional : To disable the TAP (in case of an uncleaned restart...), do the following :
```
unset OAI_TUNTAP_MODE
```
### Launch Broker (outside namespace):
```
cd ran_build/build/
./broker
```
### Launch SYNC-REF (namespace 1):
```
sudo ./multi-ue.sh -o1
cd ran_build/build/
sudo OAI_TUNTAP_MODE=tap RFSIMULATOR=server ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf --sl-mode 2 --sa --sync-ref --brokerip 10.201.1.100
```
### Launch UE2 (namespace 2):
```
sudo ./multi-ue.sh -o2
cd ran_build/build/
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue1.conf --sl-mode 2 --sa --brokerip 10.202.1.100 --device_id 1 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
```
### Launch UE3 (namespace 3):
```
sudo ./multi-ue.sh -o3
cd ran_build/build/
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue2.conf --sl-mode 2 --sa --brokerip 10.203.1.100 --device_id 2 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
```
## Check connection with Batman
### Start Batman on sync-ref (namespace 1):
```
sudo ./multi-ue.sh -o1
ip link set oaitun_ue1 address 02:00:00:00:00:01
sudo batctl if add oaitun_ue1
```
### Start Batman on UE2 (namespace 2):
```
sudo ./multi-ue.sh -o2
ip link set oaitun_ue2 address 02:00:00:00:00:02
sudo batctl if add oaitun_ue2
```
### Start Batman on UE3 (namespace 3):
```
sudo ./multi-ue.sh -o3
ip link set oaitun_ue3 address 02:00:00:00:00:03
sudo batctl if add oaitun_ue3
```
### Batman command
To check the neighbour :
```
batctl n
```
To check the routing table :
```
batctl o
```
### Start wireshark with filter
You can check the current packets exchange with wireshark, please update the name 'oaitun_ueX' accordingly.
```
wireshark -k -i oaitun_ueX -Y "eth.type == 0x4305"
```
## HW with TAP
Similarly, we can start the HW with TAP with the following command
### Launch SYNC-REF (machine 1):
```
cd ran_build/build/
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf --sa -E --sl-mode 2 --sync-ref --usrp-args "type=b200,master_clock_rate=46.08e6,enable_gps=true" --ue-txgain 10 --ue-rxgain 100 --thread-pool -1,-1,-1,-1 --clock-source 2 --time-source 2
```
### Launch UE2 (machine 2):
```
cd ran_build/build/
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue1.conf --sa -E --sl-mode 2 --usrp-args "type=b200,master_clock_rate=46.08e6,enable_gps=true" --ue-txgain 10 --ue-rxgain 100 --thread-pool -1,-1,-1,-1 --clock-source 2 --time-source 2
```
### Launch UE3 (machine 3):
```
cd ran_build/build/
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue2.conf --sa -E --sl-mode 2 --usrp-args "type=b200,master_clock_rate=46.08e6,enable_gps=true" --ue-txgain 10 --ue-rxgain 100 --thread-pool -1,-1,-1,-1 --clock-source 2 --time-source 2
```
## More UEs generated with TAP
The newest update enables to generate more than 2 UEs along with one sync-ref. The following is an example of 3 UEs.
One would, first, need to create a new .conf file in openairinterface5g/targets/PROJECTS/NR-SIDELINK/, second, in file /openairinterface5g/openair2/LAYER2/NR_MAC_UE/mac_defs.h, the parameter of "#define CUR_SL_UE_CONNECTIONS" need to be updated to match the max number of UEs(Exclusive of sync-ref, this value is limited to 6 though)
### Launch Broker (outside namespace):
```
cd ran_build/build/
./broker
```
### Launch SYNC-REF (namespace 1):
```
sudo ./multi-ue.sh -o1
cd ran_build/build/
sudo OAI_TUNTAP_MODE=tap RFSIMULATOR=server ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf --sl-mode 2 --sa --sync-ref --brokerip 10.201.1.100 --thread-pool -1,-1
```
### Launch UE2 (namespace 2):
```
sudo ./multi-ue.sh -o2
cd ran_build/build/
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue1.conf --sl-mode 2 --sa --brokerip 10.202.1.100 --device_id 1 --thread-pool -1,-1 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
```
### Launch UE3 (namespace 3):
```
sudo ./multi-ue.sh -o3
cd ran_build/build/
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue2.conf --sl-mode 2 --sa --brokerip 10.203.1.100 --device_id 2 --thread-pool -1,-1 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
```
### Launch UE4 (namespace 4):
```
sudo ./multi-ue.sh -o4
cd ran_build/build/
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue3.conf --sl-mode 2 --sa --brokerip 10.204.1.100 --device_id 3 --thread-pool -1,-1 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
```

1
cmake_targets/babeld Submodule

Submodule cmake_targets/babeld added at 950992f282

View File

@@ -280,7 +280,7 @@ function main() {
;;
"SIMU")
HW="OAI_"$2
TARGET_LIST="$TARGET_LIST rfsimulator"
TARGET_LIST="$TARGET_LIST rfsimulator broker"
CMAKE_CMD="$CMAKE_CMD -DOAI_$2=ON"
;;
"AW2SORI")
@@ -315,7 +315,7 @@ function main() {
-P | --phy_simulators)
SIMUS_PHY=1
# TODO: fix: dlsim_tm4 pucchsim prachsim pdcchsim pbchsim mbmssim
TARGET_LIST="$TARGET_LIST dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim"
TARGET_LIST="$TARGET_LIST dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim nr_psbchsim"
echo_info "Will compile dlsim, ulsim, ..."
shift;;
-s | --check)
@@ -479,7 +479,7 @@ function main() {
# add some default libraries that should always be built
# for eNB, gNB, UEs, simulators
if [[ $gNB == 1 || $eNB == 1 || $UE == 1 || $nrUE == 1 || $SIMUS_PHY == 1 || $RU == 1 ]]; then
TARGET_LIST="$TARGET_LIST params_libconfig coding rfsimulator dfts"
TARGET_LIST="$TARGET_LIST params_libconfig coding rfsimulator dfts broker"
fi
mkdir -p $DIR/$BUILD_DIR/build
@@ -523,7 +523,7 @@ function main() {
echo_info "Doxygen generation log is located here: $doxygen_log"
echo_info "Generating Doxygen files....please wait"
(
cmake --build . --target doc
cmake3 --build . --target doc
) >& $doxygen_log
fi

67
cmake_targets/multi-ue.sh Executable file
View File

@@ -0,0 +1,67 @@
#!/bin/bash
ue_id=-1
create_namespace() {
ue_id=$1
local name="ue$ue_id"
echo "creating namespace for UE ID ${ue_id} name ${name}"
ip netns add $name
ip link add v-eth$ue_id type veth peer name v-ue$ue_id
ip link set v-ue$ue_id netns $name
BASE_IP=$((200+ue_id))
ip addr add 10.$BASE_IP.1.100/24 dev v-eth$ue_id
ip link set v-eth$ue_id up
iptables -t nat -A POSTROUTING -s 10.$BASE_IP.1.0/255.255.255.0 -o lo -j MASQUERADE
iptables -A FORWARD -i lo -o v-eth$ue_id -j ACCEPT
iptables -A FORWARD -o lo -i v-eth$ue_id -j ACCEPT
ip netns exec $name ip link set dev lo up
ip netns exec $name ip addr add 10.$BASE_IP.1.$ue_id/24 dev v-ue$ue_id
ip netns exec $name ip link set v-ue$ue_id up
}
delete_namespace() {
local ue_id=$1
local name="ue$ue_id"
echo "deleting namespace for UE ID ${ue_id} name ${name}"
ip link delete v-eth$ue_id
ip netns delete $name
}
list_namespaces() {
ip netns list
}
open_namespace() {
if [[ $ue_id -lt 1 ]]; then echo "error: no last UE processed"; exit 1; fi
local name="ue$ue_id"
echo "opening shell in namespace ${name}"
echo "type 'ip netns exec $name bash' in additional terminals"
ip netns exec $name bash
}
usage () {
echo "$1 -c <num>: create namespace \"ue<num>\""
echo "$1 -d <num>: delete namespace \"ue<num>\""
echo "$1 -e : execute shell in last processed namespace"
echo "$1 -l : list namespaces"
echo "$1 -o <num>: open shell in namespace \"ue<num>\""
}
prog_name=$(basename $0)
if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root"; exit 1; fi
if [[ $# -eq 0 ]]; then echo "error: no parameters given"; usage $prog_name; exit 1; fi
while getopts c:d:ehlo: cmd
do
case "${cmd}" in
c) create_namespace ${OPTARG};;
d) delete_namespace ${OPTARG};;
e) open_namespace; exit;;
h) usage ${prog_name}; exit;;
l) list_namespaces;;
o) ue_id=${OPTARG}; open_namespace;;
/?) echo "Invalid option"; usage ${prog_name}; exit;;
esac
done

8
common/utils/colors.h Normal file
View File

@@ -0,0 +1,8 @@
#define KNRM "\x1B[0m"
#define KRED "\x1B[31m"
#define KGRN "\x1B[32m"
#define KYEL "\x1B[33m"
#define KBLU "\x1B[34m"
#define KMAG "\x1B[35m"
#define KCYN "\x1B[36m"
#define KWHT "\x1B[37m"

View File

@@ -33,6 +33,8 @@
#include <stdint.h>
#include "assertions.h"
#include "nr_common.h"
#include "executables/nr-uesoftmodem.h"
#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h"
const char *duplex_mode[]={"FDD","TDD"};
@@ -232,6 +234,45 @@ int NRRIV2BW(int locationAndBandwidth,int N_RB) {
}
/* This function converts the FRIV to a start sub-channel and length in subchannels */
/* for sl_MaxNumPerReserve = 2, the sequence from 38.214 for Lsc = 1,2,3, ...
* goes like startsc + (0,N_subch,N_subch +(N_subch-1), N_subch + (N_subch-1) + (N_subch-2), ...)
*
* This is only done for sl_MaxNumPerReserve = 2
* */
void convNRFRIV(int FRIV,
int N_subch,
long sl_MaxNumPerReserve,
uint16_t *Lsc,
uint16_t *startsc,
uint16_t *startsc2) {
if (sl_MaxNumPerReserve == NR_SL_UE_SelectedConfigRP_r16__sl_MaxNumPerReserve_r16_n2) {
*Lsc=1;
int prevN=0;
int N=N_subch;
while (FRIV>N) {
*Lsc = *Lsc+1;
prevN = N;
N += (N_subch - *Lsc + 1);
}
if (startsc) *startsc = FRIV-prevN;
} else if (sl_MaxNumPerReserve == NR_SL_UE_SelectedConfigRP_r16__sl_MaxNumPerReserve_r16_n3) {
*Lsc=1;
int prevN=0;
int N=N_subch;
while (FRIV>N) {
*Lsc = *Lsc + 1;
prevN = N;
N += ((N_subch - *Lsc + 1)*(N_subch - *Lsc + 1));
}
int tmp1 = FRIV - prevN; // This holds startsc1 + startsc2*(N_subch - *Lsc + 1)
if (startsc2) *startsc2 = tmp1 / (N_subch - *Lsc + 1);
if (startsc) *startsc = tmp1 % (N_subch - *Lsc + 1);
} else {
AssertFatal(1 == 0, "sl_MaxNumPerReserve is configured with incorrect value");
}
}
int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB) {
int tmp = locationAndBandwidth/N_RB;
int tmp2 = locationAndBandwidth%N_RB;
@@ -351,7 +392,7 @@ int get_dmrs_port(int nl, uint16_t dmrs_ports)
}
}
}
AssertFatal(p>-1,"No dmrs port corresponding to layer %d found\n",nl);
if (p==-1) LOG_E(NR_PHY,"No dmrs port corresponding to layer %d found\n",nl);
return p;
}
@@ -733,3 +774,61 @@ uint32_t get_ssb_offset_to_pointA(uint32_t absoluteFrequencySSB,
AssertFatal(sco % scs_scaling == 0, "ssb offset %d can create frequency offset\n", sco);
return ssb_offset_point_a;
}
#define MAX_EL_213_9_3_2 19
const float tab38_213_9_3_2[MAX_EL_213_9_3_2] = {1.125,1.250,1.375,1.625,1.750,2.000,2.250,2.500,2.875,3.125,3.500,4.000,5.000,6.250,8.000,10.000,12.625,15.875,20.000};
int get_NREsci2(const int sci2_alpha,
const int sci2_payload_len,
const int sci2_beta_offset,
const int pssch_numsym,
const int pscch_numsym,
const int pscch_numrbs,
const int l_subch,
const int subchannel_size,
const int mcs,
const int mcs_tb_ind) {
float Osci2 = (float)sci2_payload_len;
AssertFatal(sci2_beta_offset < MAX_EL_213_9_3_2, "illegal sci2_beta_offset %d\n",sci2_beta_offset);
float beta_offset_sci2 = tab38_213_9_3_2[sci2_beta_offset];
uint32_t R10240 = nr_get_code_rate_ul(mcs,mcs_tb_ind);
uint32_t tmp = (uint32_t)ceil((Osci2 + 24)*beta_offset_sci2/((float)R10240/5120));
float tmp2 = 12.0*pssch_numsym;
int N_REsci1 = 12*pscch_numrbs*pscch_numsym;
tmp2 *= l_subch*subchannel_size;
tmp2 -= N_REsci1;
tmp2 *= ((float)sci2_alpha/100.0);
int min_val = min(tmp,(int)ceil(tmp2));
uint8_t gamma = 12 - (min_val % 12);
return min_val + (gamma % 12);
}
int get_NREsci2_2(const int sci2_alpha,
const int sci2_payload_len,
const int sci2_beta_offset,
const int pssch_numsym,
const int pscch_numsym,
const int pscch_numrbs,
const int l_subch,
const int subchannel_size,
const int target_coderate,
const int mcs_table_index) {
float Osci2 = (float)sci2_payload_len;
AssertFatal(sci2_beta_offset < MAX_EL_213_9_3_2, "illegal sci2_beta_offset %d\n",sci2_beta_offset);
float beta_offset_sci2 = tab38_213_9_3_2[sci2_beta_offset];
uint32_t R10240 = get_softmodem_params()->sl_mode ? nr_get_code_rate_ul(1, mcs_table_index) : target_coderate;
uint32_t tmp = (uint32_t)ceil((Osci2 + 24)*beta_offset_sci2/((float)R10240/5120));
float tmp2 = 12.0*pssch_numsym;
int N_REsci1 = 12*pscch_numrbs*pscch_numsym;
tmp2 *= l_subch*subchannel_size;
tmp2 -= N_REsci1;
tmp2 *= ((float)sci2_alpha/100.0);
int min_val = min(tmp,(int)ceil(tmp2));
uint8_t gamma = 12 - (min_val % 12);
return min_val + (gamma % 12);
}

View File

@@ -90,6 +90,7 @@ frame_type_t get_frame_type(uint16_t nr_bandP, uint8_t scs_index);
uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex);
int NRRIV2BW(int locationAndBandwidth,int N_RB);
int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB);
void convNRFRIV(int FRIV, int N_subch, long sl_MaxNumPerReserve, uint16_t *Lsc, uint16_t *startsc, uint16_t *startsc2);
int PRBalloc_to_locationandbandwidth0(int NPRB,int RBstart,int BWPsize);
int PRBalloc_to_locationandbandwidth(int NPRB,int RBstart);
int get_subband_size(int NPRB,int size);
@@ -113,7 +114,21 @@ uint32_t get_ssb_offset_to_pointA(uint32_t absoluteFrequencySSB,
uint32_t absoluteFrequencyPointA,
int ssbSubcarrierSpacing,
int frequency_range);
int get_NREsci2(const int sci2_alpha,
const int sci2_payload_len,
const int sci2_beta_offset,
const int pssch_numsym,
const int pscch_numsym,
const int pscch_numrbs,
const int l_subch,
const int subchannel_size,
const int mcs,
const int mcs_tb_ind);
int get_ssb_subcarrier_offset(uint32_t absoluteFrequencySSB, uint32_t absoluteFrequencyPointA);
#define CEILIDIV(a,b) ((a+b-1)/b)
#define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1))

View File

@@ -231,8 +231,9 @@ void threadCreate(pthread_t* t, void * (*func)(void*), void * param, char* name,
int settingPriority = 1;
ret=pthread_attr_init(&attr);
AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno);
LOG_I(UTIL,"Creating thread %s with affinity %d and priority %d\n",name,affinity,priority);
size_t stacksize;
pthread_attr_getstacksize(&attr,&stacksize);
LOG_I(UTIL,"Creating thread %s with affinity %d and priority %d, stacksize %d\n",name,affinity,priority,(int) stacksize);
if (checkIfFedoraDistribution())
if (checkIfGenericKernelOnFedora())

49
doc/JSUC.md Normal file
View File

@@ -0,0 +1,49 @@
# Joint sidelink and Uu communication (JSUC)
This tutorial will discuss the setup for a hybrid communication mode using sidelink and Uu.
## Setup
The idea is to have 4 UEs, two running sidelink and two running normal mode. A logical UE (UE A and UE B) supporting hybrid communication mode is represented by 2 UEs, one running sidelink and the other running normal mode.
![Hybrid Communication Setup Diagram](doc/images/hybrid_communication_setup.png)
The following repos will be used for each technology:
- Uu: `mkdir normal-mode`, `cd normal-mode` then clone `https://github.com/beraoudabdelkhalek/rfsim-Uu-metrics`
- Sidelink: `mkdir sidelink`, `cd sidelink` then clone `https://gitlab.eurecom.fr/oai/openairinterface5g` and `git checkout sl-eurecom4`
- Build both projects, and build the telnet server for each project `./build_oai --build-lib telnetsrv`
- Run the OAI core network.
- Create 4 namespaces: `sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -c x` where x is from 1-4
- Run the gNB executable on the host using the project inside the `normal-mode` directory:
```sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --rfsim --rfsimulator.options chanmod --telnetsrv```
- Run the broker on the host using the project inside `sidelink` directory.
- Run UE 1 in NS 1 (normal mode) using `normal-mode` directory:
`sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -o 1`
```sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --rfsimulator.serveraddr 10.201.1.100 --uicc0.imsi 001010000000001 -O ../../../ci-scripts/conf_files/nrue.uicc.conf --rfsimulator.options chanmod --telnetsrv --telnetsrv.listenport 9091```
- Run UE 2 in NS 2 (sidelink mode) using `sidelink` directory:
`sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -o 2`
```sudo RFSIMULATOR=server ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf --sl-mode 2 --sa --sync-ref --brokerip 10.202.1.100```
- Run UE 3 in NS 3 (sidelink mode) using `sidelink` directory:
`sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -o 3`
```sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_ue1.conf --sl-mode 2 --sa --brokerip 10.203.1.100 --device_id 1```
- Run UE 4 in NS 4 (normal mode) using `normal-mode` directory:
`sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -o 4`
```sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --rfsimulator.serveraddr 10.204.1.100 --uicc0.imsi 001010000000002 -O ../../../ci-scripts/conf_files/nrue.uicc.conf --rfsimulator.options chanmod --telnetsrv --telnetsrv.listenport 9091```
## Connectivity test
### Uu Connectivity:
From UE 1 ping UE 4:
- `sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -o 1`
- `ping 10.0.0.3`
### Sidelink Connectivity:
From UE 2 ping UE 3:
- `sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -o 2`
- `ping 10.0.0.2`

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@@ -169,7 +169,7 @@ extern void *udp_eNB_task(void *args_p);
int transmission_mode=1;
int emulate_rf = 0;
int numerology = 0;
int numerology = 1; //Jin change to 1
static char *parallel_config = NULL;

View File

@@ -99,7 +99,8 @@
typedef enum {
pss = 0,
pbch = 1,
si = 2
si = 2,
psbch = 3
} sync_mode_t;
static void *NRUE_phy_stub_standalone_pnf_task(void *arg);
@@ -161,6 +162,9 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue,
// initialize all signal buffers
init_nr_ue_signal(ue, nb_connected_gNB);
if (ue->sl_mode)
sl_ue_phy_init(ue);
// intialize transport
init_nr_ue_transport(ue);
@@ -314,7 +318,7 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg)
uint8_t gNB_id = 0;
nr_uplink_indication_t ul_info;
int slots_per_frame = 20; //30 kHZ subcarrier spacing
int slot_ahead = 2; // TODO: Make this dynamic
int slot_ahead = 3; // TODO: Make this dynamic
ul_info.cc_id = CC_id;
ul_info.gNB_index = gNB_id;
ul_info.module_id = mod_id;
@@ -376,11 +380,12 @@ static void UE_synch(void *arg) {
int i, hw_slot_offset;
PHY_VARS_NR_UE *UE = syncD->UE;
sync_mode_t sync_mode = pbch;
if (UE->sl_mode == 2 && !get_nrUE_params()->sync_ref) sync_mode = psbch;
//int CC_id = UE->CC_id;
static int freq_offset=0;
UE->is_synchronized = 0;
if (UE->UE_scan == 0) {
if (UE->UE_scan == 0 && !UE->sl_mode) {
for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
@@ -493,6 +498,52 @@ static void UE_synch(void *arg) {
}
break;
case psbch:
LOG_I(PHY, "[UE thread Synch] Running Sidelink Initial Synch \n");
NR_DL_FRAME_PARMS *fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
dl_carrier = fp->sl_CarrierFreq;
ul_carrier = fp->sl_CarrierFreq;
if (sl_nr_slss_search(UE, &syncD->proc, 16) == 0) {
freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync
hw_slot_offset = ((UE->rx_offset<<1) / fp->samples_per_subframe * fp->slots_per_subframe) +
round((float)((UE->rx_offset<<1) % fp->samples_per_subframe)/fp->samples_per_slot0);
// rerun with new cell parameters and frequency-offset
// todo: the freq_offset computed on DL shall be scaled before being applied to UL
nr_rf_card_config_freq(&openair0_cfg[UE->rf_map.card], ul_carrier, dl_carrier, freq_offset);
LOG_I(PHY,"Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %f (DL %f Hz, UL %f Hz)\n",
hw_slot_offset,
freq_offset,
openair0_cfg[UE->rf_map.card].rx_gain[0],
openair0_cfg[UE->rf_map.card].rx_freq[0],
openair0_cfg[UE->rf_map.card].tx_freq[0]);
UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0]);
if (UE->UE_scan_carrier == 1) {
UE->UE_scan_carrier = 0;
} else {
UE->is_synchronized = 1;
}
} else {
if (UE->UE_scan_carrier == 1) {
if (freq_offset >= 0)
freq_offset += 100;
freq_offset *= -1;
nr_rf_card_config_freq(&openair0_cfg[UE->rf_map.card], ul_carrier, dl_carrier, freq_offset);
LOG_I(PHY, "Sidelink Initial sync failed: trying carrier off %d Hz\n", freq_offset);
UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0]);
}
}
break;
case si:
default:
break;
@@ -500,14 +551,18 @@ static void UE_synch(void *arg) {
}
}
static void RU_write(nr_rxtx_thread_data_t *rxtxD) {
static void RU_write(nr_rxtx_thread_data_t *rxtxD, int sl_tx_action) {
PHY_VARS_NR_UE *UE = rxtxD->UE;
UE_nr_rxtx_proc_t *proc = &rxtxD->proc;
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
if (UE->sl_mode == 2)
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
void *txp[NB_ANTENNAS_TX];
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
txp[i] = (void *)&UE->common_vars.txData[i][UE->frame_parms.get_samples_slot_timestamp(proc->nr_slot_tx, &UE->frame_parms, 0)];
for (int i=0; i<fp->nb_antennas_tx; i++)
txp[i] = (void *)&UE->common_vars.txData[i][fp->get_samples_slot_timestamp(proc->nr_slot_tx, fp, 0)];
radio_tx_burst_flag_t flags = TX_BURST_INVALID;
@@ -516,27 +571,34 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD) {
openair0_cfg[0].duplex_mode == duplex_mode_TDD &&
!get_softmodem_params()->continuous_tx) {
uint8_t tdd_period = mac->phy_config.config_req.tdd_table.tdd_period_in_slots;
int nrofUplinkSlots, nrofUplinkSymbols;
if (mac->scc) {
nrofUplinkSlots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
nrofUplinkSymbols = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols;
}
else {
nrofUplinkSlots = mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
nrofUplinkSymbols = mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols;
}
//Perform USRP write only in case SL Txn needs to be done.
if (UE->sl_mode == 2) {
flags = sl_tx_action ? TX_BURST_START_AND_END
: TX_BURST_INVALID;
} else {
int slot_tx_usrp = proc->nr_slot_tx;
uint8_t num_UL_slots = nrofUplinkSlots + (nrofUplinkSymbols != 0);
uint8_t first_tx_slot = tdd_period - num_UL_slots;
uint8_t tdd_period = mac->phy_config.config_req.tdd_table.tdd_period_in_slots;
int nrofUplinkSlots, nrofUplinkSymbols;
if (mac->scc) {
nrofUplinkSlots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
nrofUplinkSymbols = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols;
}
else {
nrofUplinkSlots = mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
nrofUplinkSymbols = mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols;
}
if (slot_tx_usrp % tdd_period == first_tx_slot)
flags = TX_BURST_START;
else if (slot_tx_usrp % tdd_period == first_tx_slot + num_UL_slots - 1)
flags = TX_BURST_END;
else if (slot_tx_usrp % tdd_period > first_tx_slot)
flags = TX_BURST_MIDDLE;
int slot_tx_usrp = proc->nr_slot_tx;
uint8_t num_UL_slots = nrofUplinkSlots + (nrofUplinkSymbols != 0);
uint8_t first_tx_slot = tdd_period - num_UL_slots;
if (slot_tx_usrp % tdd_period == first_tx_slot)
flags = TX_BURST_START;
else if (slot_tx_usrp % tdd_period == first_tx_slot + num_UL_slots - 1)
flags = TX_BURST_END;
else if (slot_tx_usrp % tdd_period > first_tx_slot)
flags = TX_BURST_MIDDLE;
}
} else {
flags = TX_BURST_MIDDLE;
}
@@ -547,10 +609,10 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD) {
proc->timestamp_tx,
txp,
rxtxD->writeBlockSize,
UE->frame_parms.nb_antennas_tx,
fp->nb_antennas_tx,
flags),"");
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
for (int i=0; i<fp->nb_antennas_tx; i++)
memset(txp[i], 0, rxtxD->writeBlockSize);
}
@@ -561,45 +623,77 @@ void processSlotTX(void *arg) {
UE_nr_rxtx_proc_t *proc = &rxtxD->proc;
PHY_VARS_NR_UE *UE = rxtxD->UE;
nr_phy_data_tx_t phy_data = {0};
int sl_tx_action = 0;
LOG_D(PHY,"%d.%d => slot type %d\n", proc->frame_tx, proc->nr_slot_tx, proc->tx_slot_type);
if (proc->tx_slot_type == NR_UPLINK_SLOT || proc->tx_slot_type == NR_MIXED_SLOT){
// wait for rx slots to send indication (if any) that DLSCH decoding is finished
for(int i=0; i < rxtxD->tx_wait_for_dlsch; i++) {
notifiedFIFO_elt_t *res = pullNotifiedFIFO(UE->tx_resume_ind_fifo[proc->nr_slot_tx]);
delNotifiedFIFO_elt(res);
}
if (proc->tx_slot_type == NR_SIDELINK_SLOT && UE->sl_mode == 2) {
// trigger L2 to run ue_scheduler thru IF module
// [TODO] mapping right after NR initial sync
if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) {
// trigger L2 to run ue_scheduler thru IF module
if(UE->if_inst != NULL && UE->if_inst->sl_indication != NULL) {
start_meas(&UE->ue_ul_indication_stats);
nr_uplink_indication_t ul_indication;
memset((void*)&ul_indication, 0, sizeof(ul_indication));
nr_sidelink_indication_t sl_indication;
memset((void*)&sl_indication, 0, sizeof(sl_indication));
ul_indication.module_id = UE->Mod_id;
ul_indication.gNB_index = proc->gNB_id;
ul_indication.cc_id = UE->CC_id;
ul_indication.frame_rx = proc->frame_rx;
ul_indication.slot_rx = proc->nr_slot_rx;
ul_indication.frame_tx = proc->frame_tx;
ul_indication.slot_tx = proc->nr_slot_tx;
ul_indication.phy_data = &phy_data;
sl_indication.module_id = UE->Mod_id;
sl_indication.gNB_index = proc->gNB_id;
sl_indication.cc_id = UE->CC_id;
sl_indication.frame_rx = proc->frame_rx;
sl_indication.slot_rx = proc->nr_slot_rx;
sl_indication.frame_tx = proc->frame_tx;
sl_indication.slot_tx = proc->nr_slot_tx;
sl_indication.phy_data = &phy_data;
sl_indication.slot_type = SIDELINK_SLOT_TYPE_TX;
LOG_D(NR_PHY,"Sending SL indication RX %d.%d TX %d.%d\n",proc->frame_rx,proc->nr_slot_rx,proc->frame_tx,proc->nr_slot_tx);
UE->if_inst->sl_indication(&sl_indication);
UE->if_inst->ul_indication(&ul_indication);
stop_meas(&UE->ue_ul_indication_stats);
}
phy_procedures_nrUE_TX(UE, proc, &phy_data);
sl_tx_action = phy_procedures_nrUE_SL_TX(UE, proc, &phy_data);
} else {
if (proc->tx_slot_type == NR_UPLINK_SLOT || proc->tx_slot_type == NR_MIXED_SLOT){
// wait for rx slots to send indication (if any) that DLSCH decoding is finished
for(int i=0; i < rxtxD->tx_wait_for_dlsch; i++) {
notifiedFIFO_elt_t *res = pullNotifiedFIFO(UE->tx_resume_ind_fifo[proc->nr_slot_tx]);
delNotifiedFIFO_elt(res);
}
// trigger L2 to run ue_scheduler thru IF module
// [TODO] mapping right after NR initial sync
if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) {
start_meas(&UE->ue_ul_indication_stats);
nr_uplink_indication_t ul_indication;
memset((void*)&ul_indication, 0, sizeof(ul_indication));
ul_indication.module_id = UE->Mod_id;
ul_indication.gNB_index = proc->gNB_id;
ul_indication.cc_id = UE->CC_id;
ul_indication.frame_rx = proc->frame_rx;
ul_indication.slot_rx = proc->nr_slot_rx;
ul_indication.frame_tx = proc->frame_tx;
ul_indication.slot_tx = proc->nr_slot_tx;
ul_indication.phy_data = &phy_data;
UE->if_inst->ul_indication(&ul_indication);
stop_meas(&UE->ue_ul_indication_stats);
}
phy_procedures_nrUE_TX(UE, proc, &phy_data);
}
}
RU_write(rxtxD);
RU_write(rxtxD, sl_tx_action);
}
nr_phy_data_t UE_dl_preprocessing(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc)
{
nr_phy_data_t phy_data = {0};
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
if (UE->sl_mode == 2)
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
if (IS_SOFTMODEM_NOS1 || get_softmodem_params()->sa) {
@@ -614,34 +708,48 @@ nr_phy_data_t UE_dl_preprocessing(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc)
}
/* send tick to RLC and PDCP every ms */
if (proc->nr_slot_rx % UE->frame_parms.slots_per_subframe == 0) {
if (proc->nr_slot_rx % fp->slots_per_subframe == 0) {
void nr_rlc_tick(int frame, int subframe);
void nr_pdcp_tick(int frame, int subframe);
nr_rlc_tick(proc->frame_rx, proc->nr_slot_rx / UE->frame_parms.slots_per_subframe);
nr_pdcp_tick(proc->frame_rx, proc->nr_slot_rx / UE->frame_parms.slots_per_subframe);
nr_rlc_tick(proc->frame_rx, proc->nr_slot_rx / fp->slots_per_subframe);
nr_pdcp_tick(proc->frame_rx, proc->nr_slot_rx / fp->slots_per_subframe);
}
}
if (proc->rx_slot_type == NR_DOWNLINK_SLOT || proc->rx_slot_type == NR_MIXED_SLOT) {
if (UE->sl_mode == 2) {
if (proc->rx_slot_type == NR_SIDELINK_SLOT) {
if(UE->if_inst != NULL && UE->if_inst->dl_indication != NULL) {
nr_downlink_indication_t dl_indication;
nr_fill_dl_indication(&dl_indication, NULL, NULL, proc, UE, &phy_data);
UE->if_inst->dl_indication(&dl_indication);
if(UE->if_inst != NULL && UE->if_inst->sl_indication != NULL) {
nr_sidelink_indication_t sl_indication;
nr_fill_sl_indication(&sl_indication, NULL, NULL, proc, UE, &phy_data);
UE->if_inst->sl_indication(&sl_indication);
}
uint64_t a=rdtsc_oai();
psbch_pscch_pssch_processing(UE, proc, &phy_data);
LOG_D(PHY, "In %s: slot %d:%d, time %llu\n", __FUNCTION__, proc->frame_rx, proc->nr_slot_rx, (rdtsc_oai()-a)/3500);
}
} else {
if (proc->rx_slot_type == NR_DOWNLINK_SLOT || proc->rx_slot_type == NR_MIXED_SLOT){
if(UE->if_inst != NULL && UE->if_inst->dl_indication != NULL) {
nr_downlink_indication_t dl_indication;
nr_fill_dl_indication(&dl_indication, NULL, NULL, proc, UE, &phy_data);
UE->if_inst->dl_indication(&dl_indication);
}
uint64_t a=rdtsc_oai();
pbch_pdcch_processing(UE, proc, &phy_data);
if (phy_data.dlsch[0].active) {
// indicate to tx thread to wait for DLSCH decoding
const int ack_nack_slot = (proc->nr_slot_rx + phy_data.dlsch[0].dlsch_config.k1_feedback) % UE->frame_parms.slots_per_frame;
UE->tx_wait_for_dlsch[ack_nack_slot]++;
}
LOG_D(PHY, "In %s: slot %d, time %llu\n", __FUNCTION__, proc->nr_slot_rx, (rdtsc_oai()-a)/3500);
}
uint64_t a=rdtsc_oai();
pbch_pdcch_processing(UE, proc, &phy_data);
if (phy_data.dlsch[0].active) {
// indicate to tx thread to wait for DLSCH decoding
const int ack_nack_slot = (proc->nr_slot_rx + phy_data.dlsch[0].dlsch_config.k1_feedback) % UE->frame_parms.slots_per_frame;
UE->tx_wait_for_dlsch[ack_nack_slot]++;
}
LOG_D(PHY, "In %s: slot %d, time %llu\n", __FUNCTION__, proc->nr_slot_rx, (rdtsc_oai()-a)/3500);
ue_ta_procedures(UE, proc->nr_slot_tx, proc->frame_tx);
}
ue_ta_procedures(UE, proc->nr_slot_tx, proc->frame_tx);
return phy_data;
}
@@ -651,14 +759,20 @@ void UE_dl_processing(void *arg) {
PHY_VARS_NR_UE *UE = rxtxD->UE;
nr_phy_data_t *phy_data = &rxtxD->phy_data;
pdsch_processing(UE, proc, phy_data);
if (UE->sl_mode == 0)
pdsch_processing(UE, proc, phy_data);
}
void dummyWrite(PHY_VARS_NR_UE *UE,openair0_timestamp timestamp, int writeBlockSize) {
void *dummy_tx[UE->frame_parms.nb_antennas_tx];
int16_t dummy_tx_data[UE->frame_parms.nb_antennas_tx][2*writeBlockSize]; // 2 because the function we call use pairs of int16_t implicitly as complex numbers
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
if (UE->sl_mode == 2)
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
void *dummy_tx[fp->nb_antennas_tx];
int16_t dummy_tx_data[fp->nb_antennas_tx][2*writeBlockSize]; // 2 because the function we call use pairs of int16_t implicitly as complex numbers
memset(dummy_tx_data, 0, sizeof(dummy_tx_data));
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
for (int i=0; i<fp->nb_antennas_tx; i++)
dummy_tx[i]=dummy_tx_data[i];
AssertFatal( writeBlockSize ==
@@ -666,37 +780,45 @@ void dummyWrite(PHY_VARS_NR_UE *UE,openair0_timestamp timestamp, int writeBlockS
timestamp,
dummy_tx,
writeBlockSize,
UE->frame_parms.nb_antennas_tx,
fp->nb_antennas_tx,
4),"");
}
void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash) {
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
int num_frames = 2;
//In Sidelink worst case SL-SSB can be sent once in 16 frames
if (UE->sl_mode == 2) {
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
num_frames = SL_NR_PSBCH_REPETITION_IN_FRAMES;
}
void *rxp[NB_ANTENNAS_RX];
for(int x=0; x<20; x++) { // two frames for initial sync
for (int slot=0; slot<UE->frame_parms.slots_per_subframe; slot ++ ) {
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++) {
for(int x=0; x< num_frames*NR_NUMBER_OF_SUBFRAMES_PER_FRAME; x++) { // two frames for initial sync
for (int slot=0; slot<fp->slots_per_subframe; slot ++ ) {
for (int i=0; i<fp->nb_antennas_rx; i++) {
if (toTrash)
rxp[i]=malloc16(UE->frame_parms.get_samples_per_slot(slot,&UE->frame_parms)*4);
rxp[i]=malloc16(fp->get_samples_per_slot(slot,fp)*4);
else
rxp[i] = ((void *)&UE->common_vars.rxdata[i][0]) +
4*((x*UE->frame_parms.samples_per_subframe)+
UE->frame_parms.get_samples_slot_timestamp(slot,&UE->frame_parms,0));
4*((x*fp->samples_per_subframe)+
fp->get_samples_slot_timestamp(slot,fp,0));
}
AssertFatal( UE->frame_parms.get_samples_per_slot(slot,&UE->frame_parms) ==
AssertFatal( fp->get_samples_per_slot(slot,fp) ==
UE->rfdevice.trx_read_func(&UE->rfdevice,
timestamp,
rxp,
UE->frame_parms.get_samples_per_slot(slot,&UE->frame_parms),
UE->frame_parms.nb_antennas_rx), "");
fp->get_samples_per_slot(slot,fp),
fp->nb_antennas_rx), "");
if (IS_SOFTMODEM_RFSIM)
dummyWrite(UE,*timestamp, UE->frame_parms.get_samples_per_slot(slot,&UE->frame_parms));
dummyWrite(UE,*timestamp, fp->get_samples_per_slot(slot,fp));
if (toTrash)
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
for (int i=0; i<fp->nb_antennas_rx; i++)
free(rxp[i]);
}
}
@@ -707,21 +829,25 @@ void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) {
LOG_I(PHY,"Resynchronizing RX by %d samples\n",UE->rx_offset);
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
if (UE->sl_mode == 2)
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) {
// Resynchonize by slot (will work with numerology 1 only)
for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe/2 ) {
int unitTransfer=size>UE->frame_parms.samples_per_subframe/2 ? UE->frame_parms.samples_per_subframe/2 : size ;
for ( int size=UE->rx_offset ; size > 0 ; size -= fp->samples_per_subframe/2 ) {
int unitTransfer=size>fp->samples_per_subframe/2 ? fp->samples_per_subframe/2 : size ;
AssertFatal(unitTransfer ==
UE->rfdevice.trx_read_func(&UE->rfdevice,
timestamp,
(void **)UE->common_vars.rxdata,
unitTransfer,
UE->frame_parms.nb_antennas_rx),"");
fp->nb_antennas_rx),"");
}
} else {
*timestamp += UE->frame_parms.get_samples_per_slot(1,&UE->frame_parms);
for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe ) {
int unitTransfer=size>UE->frame_parms.samples_per_subframe ? UE->frame_parms.samples_per_subframe : size ;
*timestamp += fp->get_samples_per_slot(1,fp);
for ( int size=UE->rx_offset ; size > 0 ; size -= fp->samples_per_subframe ) {
int unitTransfer=size>fp->samples_per_subframe ? fp->samples_per_subframe : size ;
// we write before read because gNB waits for UE to write and both executions halt
// this happens here as the read size is samples_per_subframe which is very much larger than samp_per_slot
if (IS_SOFTMODEM_RFSIM) dummyWrite(UE,*timestamp, unitTransfer);
@@ -730,7 +856,7 @@ void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) {
timestamp,
(void **)UE->common_vars.rxdata,
unitTransfer,
UE->frame_parms.nb_antennas_rx),"");
fp->nb_antennas_rx),"");
*timestamp += unitTransfer; // this does not affect the read but needed for RFSIM write
}
}
@@ -761,6 +887,12 @@ void *UE_thread(void *arg)
void *rxp[NB_ANTENNAS_RX];
int start_rx_stream = 0;
fapi_nr_config_request_t *cfg = &UE->nrUE_config;
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
int is_sidelink = (UE->sl_mode == 2) ? 1 : 0;
if (is_sidelink) {
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
openair0_cfg[0].gpio_controller = RU_GPIO_CONTROL_GENERIC;
}
AssertFatal(0== openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]), "");
UE->rfdevice.host_type = RAU_HOST;
UE->is_synchronized = 0;
@@ -779,7 +911,7 @@ void *UE_thread(void *arg)
NR_UE_MAC_INST_t *mac = get_mac_inst(0);
bool syncRunning=false;
const int nb_slot_frame = UE->frame_parms.slots_per_frame;
const int nb_slot_frame = fp->slots_per_frame;
int absolute_slot=0, decoded_frame_rx=INT_MAX, trashed_frames=0;
initNotifiedFIFO(&UE->phy_config_ind);
@@ -790,6 +922,12 @@ void *UE_thread(void *arg)
initNotifiedFIFO(UE->tx_resume_ind_fifo[i]);
}
if (get_nrUE_params()->sync_ref &&
UE->sl_mode == 2) {
UE->is_synchronized = 1;
start_rx_stream = -1;
}
while (!oai_exit) {
if (syncRunning) {
@@ -798,7 +936,8 @@ void *UE_thread(void *arg)
if (res) {
syncRunning=false;
if (UE->is_synchronized) {
decoded_frame_rx = mac->mib_frame;
if (UE->sl_mode == 2) decoded_frame_rx = UE->SL_UE_PHY_PARAMS.sync_params.DFN;
else decoded_frame_rx = mac->mib_frame;
LOG_I(PHY,"UE synchronized decoded_frame_rx=%d UE->init_sync_frame=%d trashed_frames=%d\n",
decoded_frame_rx,
UE->init_sync_frame,
@@ -817,7 +956,7 @@ void *UE_thread(void *arg)
}
} else {
readFrame(UE, &timestamp, true);
trashed_frames+=2;
trashed_frames+=((UE->sl_mode)?SL_NR_PSBCH_REPETITION_IN_FRAMES:2);
}
continue;
}
@@ -843,21 +982,25 @@ void *UE_thread(void *arg)
UE->rx_offset=0;
UE->time_sync_cell=0;
// read in first symbol
AssertFatal (UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 ==
AssertFatal (fp->ofdm_symbol_size+fp->nb_prefix_samples0 ==
UE->rfdevice.trx_read_func(&UE->rfdevice,
&timestamp,
(void **)UE->common_vars.rxdata,
UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0,
UE->frame_parms.nb_antennas_rx),"");
fp->ofdm_symbol_size+fp->nb_prefix_samples0,
fp->nb_antennas_rx),"");
// we have the decoded frame index in the return of the synch process
// and we shifted above to the first slot of next frame
decoded_frame_rx++;
// we do ++ first in the regular processing, so it will be begin of frame;
absolute_slot = decoded_frame_rx * nb_slot_frame - 1;
if (UE->sl_mode == 2) {
//Set to the slot where the SL-SSB was decoded
absolute_slot += UE->SL_UE_PHY_PARAMS.sync_params.slot_offset;
}
continue;
}
absolute_slot++;
int slot_nr = absolute_slot % nb_slot_frame;
@@ -868,24 +1011,58 @@ void *UE_thread(void *arg)
curMsg.proc.nr_slot_tx = (absolute_slot + DURATION_RX_TO_TX) % nb_slot_frame;
curMsg.proc.frame_rx = (absolute_slot / nb_slot_frame) % MAX_FRAME_NUMBER;
curMsg.proc.frame_tx = ((absolute_slot + DURATION_RX_TO_TX) / nb_slot_frame) % MAX_FRAME_NUMBER;
if (mac->phy_config_request_sent) {
curMsg.proc.rx_slot_type = nr_ue_slot_select(cfg, curMsg.proc.frame_rx, curMsg.proc.nr_slot_rx);
curMsg.proc.tx_slot_type = nr_ue_slot_select(cfg, curMsg.proc.frame_tx, curMsg.proc.nr_slot_tx);
if (UE->phy_config_request_sent) {
if (is_sidelink) {
NR_UE_MAC_INST_t *mac = get_mac_inst(UE->Mod_id);
uint8_t pool_id = 0;
// Temporarily setting this to this initial NON_NR_SIDELINK_SLOT slot type.
// Later we should properly determine if the current slot is an NR_DOWNLINK_SLOT, NR_UPLINK_SLOT, or NR_MIXED_SLOT
curMsg.proc.tx_slot_type = NON_NR_SIDELINK_SLOT;
curMsg.proc.rx_slot_type = NON_NR_SIDELINK_SLOT;
SL_ResourcePool_params_t *sl_tx_rsrc_pool = mac->SL_MAC_PARAMS->sl_TxPool[pool_id];
uint16_t phy_map_sz_tx = ((sl_tx_rsrc_pool->phy_sl_bitmap.size << 3) - sl_tx_rsrc_pool->phy_sl_bitmap.bits_unused);
bool sl_tx_slot = is_sl_slot(mac, &sl_tx_rsrc_pool->phy_sl_bitmap, phy_map_sz_tx, absolute_slot + DURATION_RX_TO_TX);
if (sl_tx_slot) {
frameslot_t frame_slot_tx;
frame_slot_tx.frame = curMsg.proc.frame_tx;
frame_slot_tx.slot = curMsg.proc.nr_slot_tx;
validate_selected_sl_slot(true , false, mac->SL_MAC_PARAMS->sl_TDD_config, frame_slot_tx);
curMsg.proc.tx_slot_type = NR_SIDELINK_SLOT;
}
SL_ResourcePool_params_t *sl_rx_rsrc_pool = mac->SL_MAC_PARAMS->sl_RxPool[pool_id];
uint16_t phy_map_sz_rx = ((sl_rx_rsrc_pool->phy_sl_bitmap.size << 3) - sl_rx_rsrc_pool->phy_sl_bitmap.bits_unused);
bool sl_rx_slot = is_sl_slot(mac, &sl_rx_rsrc_pool->phy_sl_bitmap, phy_map_sz_rx, absolute_slot);
if (sl_rx_slot) {
frameslot_t frame_slot_rx;
frame_slot_rx.frame = curMsg.proc.frame_rx;
frame_slot_rx.slot = curMsg.proc.nr_slot_rx;
validate_selected_sl_slot(false , true, mac->SL_MAC_PARAMS->sl_TDD_config, frame_slot_rx);
curMsg.proc.rx_slot_type = NR_SIDELINK_SLOT;
}
LOG_D(NR_PHY,"Setting SL slot type to TX %d.%d %d, RX %d.%d %d\n",
curMsg.proc.frame_tx, curMsg.proc.nr_slot_tx, curMsg.proc.tx_slot_type, curMsg.proc.frame_rx, curMsg.proc.nr_slot_rx, curMsg.proc.rx_slot_type);
} else {
curMsg.proc.rx_slot_type = nr_ue_slot_select(cfg, curMsg.proc.frame_rx, curMsg.proc.nr_slot_rx);
curMsg.proc.tx_slot_type = nr_ue_slot_select(cfg, curMsg.proc.frame_tx, curMsg.proc.nr_slot_tx);
}
}
else {
curMsg.proc.rx_slot_type = NR_DOWNLINK_SLOT;
curMsg.proc.tx_slot_type = NR_DOWNLINK_SLOT;
}
int firstSymSamp = get_firstSymSamp(slot_nr, &UE->frame_parms);
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
int firstSymSamp = get_firstSymSamp(slot_nr, fp);
for (int i=0; i<fp->nb_antennas_rx; i++)
rxp[i] = (void *)&UE->common_vars.rxdata[i][firstSymSamp+
UE->frame_parms.get_samples_slot_timestamp(slot_nr,&UE->frame_parms,0)];
fp->get_samples_slot_timestamp(slot_nr,fp,0)];
int readBlockSize, writeBlockSize;
readBlockSize = get_readBlockSize(slot_nr, &UE->frame_parms);
writeBlockSize = UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX) % nb_slot_frame, &UE->frame_parms);
readBlockSize = get_readBlockSize(slot_nr, fp);
writeBlockSize = fp->get_samples_per_slot((slot_nr + DURATION_RX_TO_TX) % nb_slot_frame, fp);
if (UE->apply_timing_offset && (slot_nr == nb_slot_frame - 1)) {
const int sampShift = -(UE->rx_offset>>1);
readBlockSize -= sampShift;
@@ -898,11 +1075,11 @@ void *UE_thread(void *arg)
&timestamp,
rxp,
readBlockSize,
UE->frame_parms.nb_antennas_rx),"");
fp->nb_antennas_rx),"");
if(slot_nr == (nb_slot_frame - 1)) {
// read in first symbol of next frame and adjust for timing drift
int first_symbols = UE->frame_parms.ofdm_symbol_size + UE->frame_parms.nb_prefix_samples0; // first symbol of every frames
int first_symbols = fp->ofdm_symbol_size + fp->nb_prefix_samples0; // first symbol of every frames
if (first_symbols > 0) {
openair0_timestamp ignore_timestamp;
@@ -911,14 +1088,14 @@ void *UE_thread(void *arg)
&ignore_timestamp,
(void **)UE->common_vars.rxdata,
first_symbols,
UE->frame_parms.nb_antennas_rx),"");
fp->nb_antennas_rx),"");
} else
LOG_E(PHY,"can't compensate: diff =%d\n", first_symbols);
}
// use previous timing_advance value to compute writeTimestamp
writeTimestamp = timestamp +
UE->frame_parms.get_samples_slot_timestamp(slot_nr,&UE->frame_parms,DURATION_RX_TO_TX)
fp->get_samples_slot_timestamp(slot_nr,fp,DURATION_RX_TO_TX)
- firstSymSamp - openair0_cfg[0].tx_sample_advance -
UE->N_TA_offset - timing_advance;
@@ -963,16 +1140,20 @@ void *UE_thread(void *arg)
void init_NR_UE(int nb_inst,
char* uecap_file,
char* rrc_config_path) {
char* rrc_config_path,
ueinfo_t* ueinfo) {
int inst;
NR_UE_MAC_INST_t *mac_inst;
NR_UE_RRC_INST_t* rrc_inst;
for (inst=0; inst < nb_inst; inst++) {
AssertFatal((rrc_inst = nr_l3_init_ue(uecap_file,rrc_config_path)) != NULL, "can not initialize RRC module\n");
AssertFatal((mac_inst = nr_l2_init_ue(rrc_inst)) != NULL, "can not initialize L2 module\n");
AssertFatal((mac_inst = nr_l2_init_ue(rrc_inst, ueinfo)) != NULL, "can not initialize L2 module\n");
AssertFatal((mac_inst->if_module = nr_ue_if_module_init(inst)) != NULL, "can not initialize IF module\n");
}
if (get_softmodem_params()->sl_mode) {
configure_NR_SL_Preconfig(0, get_nrUE_params()->sync_ref);
}
}
void init_NR_UE_threads(int nb_inst) {

View File

@@ -86,6 +86,7 @@ unsigned short config_frames[4] = {2,9,11,13};
#include "nr_nas_msg_sim.h"
#include <openair1/PHY/MODULATION/nr_modulation.h>
#include "openair2/GNB_APP/gnb_paramdef.h"
#include "openair2/RRC/NR_UE/sl_preconfig_paramvalues.h"
extern const char *duplex_mode[];
THREAD_STRUCT thread_struct;
@@ -117,6 +118,8 @@ static int tx_max_power[MAX_NUM_CCs] = {0};
int single_thread_flag = 1;
int tddflag = 0;
int vcdflag = 0;
int sl_nas_enabled = 0; //SLC Flag
double rx_gain_off = 0.0;
char *usrp_args = NULL;
@@ -312,16 +315,18 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){
}
void init_openair0(void) {
void init_openair0(bool is_sidelink) {
int card;
int freq_off = 0;
NR_DL_FRAME_PARMS *frame_parms = &PHY_vars_UE_g[0][0]->frame_parms;
if (is_sidelink)
frame_parms = &PHY_vars_UE_g[0][0]->SL_UE_PHY_PARAMS.sl_frame_params;
for (card=0; card<MAX_CARDS; card++) {
uint64_t dl_carrier, ul_carrier, sl_carrier;
uint64_t dl_carrier, ul_carrier;
openair0_cfg[card].configFilename = NULL;
openair0_cfg[card].threequarter_fs = frame_parms->threequarter_fs;
openair0_cfg[card].sample_rate = frame_parms->samples_per_subframe * 1e3;
openair0_cfg[card].sample_rate = IS_SOFTMODEM_RFSIM ? frame_parms->samples_per_subframe * 1e3 : 46080000;
openair0_cfg[card].samples_per_frame = frame_parms->samples_per_frame;
if (frame_parms->frame_type==TDD)
@@ -344,15 +349,14 @@ void init_openair0(void) {
openair0_cfg[card].rx_num_channels,
duplex_mode[openair0_cfg[card].duplex_mode]);
nr_get_carrier_frequencies(PHY_vars_UE_g[0][0], &dl_carrier, &ul_carrier);
if (is_sidelink) {
dl_carrier = frame_parms->dl_CarrierFreq;
ul_carrier = frame_parms->ul_CarrierFreq;
} else
nr_get_carrier_frequencies(PHY_vars_UE_g[0][0], &dl_carrier, &ul_carrier);
nr_rf_card_config_freq(&openair0_cfg[card], ul_carrier, dl_carrier, freq_off);
if (get_softmodem_params()->sl_mode == 2) {
nr_get_carrier_frequencies_sl(PHY_vars_UE_g[0][0], &sl_carrier);
nr_rf_card_config_freq(&openair0_cfg[card], sl_carrier, sl_carrier, freq_off);
}
nr_rf_card_config_gain(&openair0_cfg[card], rx_gain_off);
openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file;
@@ -447,7 +451,6 @@ int main( int argc, char **argv ) {
// get options and fill parameters from configuration file
get_options (); //Command-line options specific for NRUE
get_common_options(SOFTMODEM_5GUE_BIT);
CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
#if T_TRACER
@@ -472,17 +475,28 @@ int main( int argc, char **argv ) {
#endif
LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
init_NR_UE(1,uecap_file,rrc_config_path);
ueinfo_t ueinfo;
char aprefix[MAX_OPTNAME_SIZE*2 + 8];
paramdef_t SL_UEINFO[] = SL_UEINFO_DESC(ueinfo);
paramlist_def_t SL_UEINFOList = {SL_CONFIG_STRING_UEINFO, NULL, 0};
sprintf(aprefix, "%s.[%d]", SL_CONFIG_STRING_SL_PRECONFIGURATION, 0);
config_getlist(&SL_UEINFOList, NULL, 0, aprefix);
sprintf(aprefix, "%s.[%i].%s.[%i]", SL_CONFIG_STRING_SL_PRECONFIGURATION, 0, SL_CONFIG_STRING_UEINFO, 0);
config_get(SL_UEINFO, sizeof(SL_UEINFO)/sizeof(paramdef_t), aprefix);
init_NR_UE(1, uecap_file, rrc_config_path, &ueinfo);
int mode_offset = get_softmodem_params()->nsa ? NUMBER_OF_UE_MAX : 1;
uint16_t node_number = get_softmodem_params()->node_number;
ue_id_g = (node_number == 0) ? 0 : node_number - 2;
AssertFatal(ue_id_g >= 0, "UE id is expected to be nonnegative.\n");
if(IS_SOFTMODEM_NOS1 || get_softmodem_params()->sa || get_softmodem_params()->nsa) {
if(node_number == 0) {
if(node_number == 0 && get_softmodem_params()->sl_mode == 0) {
init_pdcp(0);
}
else {
} else if (get_softmodem_params()->sl_mode == 2) {
init_pdcp(1+ueinfo.srcid);
} else {
init_pdcp(mode_offset + ue_id_g);
}
}
@@ -522,7 +536,7 @@ int main( int argc, char **argv ) {
get_softmodem_params()->numerology,
nr_band);
}
else{
else if (get_softmodem_params()->sl_mode != 2){
DevAssert(mac->if_module != NULL && mac->if_module->phy_config_request != NULL);
mac->if_module->phy_config_request(&mac->phy_config);
mac->phy_config_request_sent = true;
@@ -532,10 +546,34 @@ int main( int argc, char **argv ) {
*mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]);
}
UE[CC_id]->sl_mode = get_softmodem_params()->sl_mode;
if (UE[CC_id]->sl_mode) {
AssertFatal(UE[CC_id]->sl_mode == 2, "Only Sidelink mode 2 supported. Mode 1 not yet supported\n");
// starting the sockets between the PC5 Controller and the RRC and the PDCP
//nr_rrc_pc5_control_socket_init();
if (sl_nas_enabled) {
nr_rrc_pc5_control_socket_init();
LOG_I(RRC, "[SL-NAS] PC5 controller socket started\n");
} else {
LOG_I(RRC, "[SL-NAS] PC5 controller socket not started\n");
}
nr_pdcp_pc5_signaling_socket_init();
//
nr_UE_configure_Sidelink(0, get_nrUE_params()->sync_ref, &ueinfo);
DevAssert(mac->if_module != NULL && mac->if_module->sl_phy_config_request != NULL);
sl_nr_ue_phy_params_t *sl_phy = &UE[CC_id]->SL_UE_PHY_PARAMS;
mac->if_module->sl_phy_config_request(&mac->SL_MAC_PARAMS->sl_phy_config);
nr_init_frame_parms_ue_sl(&sl_phy->sl_frame_params,&sl_phy->sl_config,
get_nrUE_params()->threequarter_fs,
get_nrUE_params()->ofdm_offset_divisor);
}
init_nr_ue_vars(UE[CC_id], 0, abstraction_flag);
}
init_openair0();
bool is_sl = (get_softmodem_params()->sl_mode) ? 1 : 0;
init_openair0(is_sl);
// init UE_PF_PO and mutex lock
pthread_mutex_init(&ue_pf_po_mutex, NULL);
memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*NUMBER_OF_UE_MAX*MAX_NUM_CCs);

View File

@@ -5,13 +5,20 @@
#include "PHY/defs_nr_UE.h"
#include "SIMULATION/ETH_TRANSPORT/proto.h"
typedef struct ueinfo {
int srcid;
int thirdOctet;
int fourthOctet;
} ueinfo_t;
#define CONFIG_HLP_IF_FREQ "IF frequency for RF, if needed\n"
#define CONFIG_HLP_IF_FREQ_OFF "UL IF frequency offset for RF, if needed\n"
#define CONFIG_HLP_DLSCH_PARA "number of threads for dlsch processing 0 for no parallelization\n"
#define CONFIG_HLP_OFFSET_DIV "Divisor for computing OFDM symbol offset in Rx chain (num samples in CP/<the value>). Default value is 8. To set the sample offset to 0, set this value ~ 10e6\n"
#define CONFIG_HLP_MAX_LDPC_ITERATIONS "Maximum LDPC decoder iterations\n"
#define CONFIG_HLP_SL_SYNCSOURCEUE "Sidelink UE acts as SYNC REF UE"
#define CONFIG_HLP_SL_MAX_MCS "Sidelink initial max mcs value"
#define CONFIG_HLP_SL_SNR "Sets sidelink SNR value"
/***************************************************************************************************************************************/
/* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument
when calling config_get or config_getlist functions */
@@ -24,6 +31,7 @@
#define CALIBPRACH_OPT "calib-prach-tx"
#define DUMPFRAME_OPT "ue-dump-frame"
#define SL_UE_iterator(BaSe, VaR) NR_SL_UE_info_t ** VaR##pptr=BaSe, *VaR; while ((VaR=*(VaR##pptr++)))
/*------------------------------------------------------------------------------------------------------------------------------------------*/
/* command line parameters defining UE running mode */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
@@ -61,6 +69,10 @@
{"chest-time", CONFIG_HLP_CHESTTIME, 0, .iptr=&(nrUE_params.chest_time), .defintval=0, TYPE_INT, 0}, \
{"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, .iptr=&(nrUE_params.no_timing_correction), .defintval=0, TYPE_INT, 0}, \
{"SLC", CONFIG_HLP_SLF, 0, .u64ptr=&(sidelink_frequency[0][0]), .defuintval=2600000000,TYPE_UINT64,0}, \
{"sync-ref", CONFIG_HLP_SL_SYNCSOURCEUE, PARAMFLAG_BOOL, .uptr=&(nrUE_params.sync_ref), .defuintval=0, TYPE_UINT32, 0}, \
{"sl-nas", "Enable SL-NAS PC5 controller socket\n", PARAMFLAG_BOOL, .iptr=&sl_nas_enabled, .defintval=0, TYPE_INT, 0}, \
{"mcs", CONFIG_HLP_SL_MAX_MCS, 0, .u8ptr=&(nrUE_params.mcs), .defintval=9, TYPE_UINT8, 0}, \
{"snr", CONFIG_HLP_SL_SNR, 0, .dblptr=&(nrUE_params.snr), .defdblval=0.0, TYPE_DOUBLE, 0}, \
}
// clang-format on
@@ -82,6 +94,9 @@ typedef struct {
int threequarter_fs;
int N_RB_DL;
int ssb_start_subcarrier;
uint32_t sync_ref;
uint8_t mcs;
double snr;
} nrUE_params_t;
extern uint64_t get_nrUE_optmask(void);
extern uint64_t set_nrUE_optmask(uint64_t bitmask);
@@ -91,7 +106,7 @@ extern nrUE_params_t *get_nrUE_params(void);
// In nr-ue.c
extern int setup_nr_ue_buffers(PHY_VARS_NR_UE **phy_vars_ue, openair0_config_t *openair0_cfg);
extern void fill_ue_band_info(void);
extern void init_NR_UE(int, char*, char*);
extern void init_NR_UE(int, char*, char*, ueinfo_t*);
extern void init_NR_UE_threads(int);
extern void reset_opp_meas(void);
extern void print_opp_meas(void);
@@ -99,4 +114,6 @@ extern void start_oai_nrue_threads(void);
void *UE_thread(void *arg);
void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id, uint8_t abstraction_flag);
void init_nrUE_standalone_thread(int ue_idx);
extern int sl_nas_enabled; //SLC Flag
#endif

View File

@@ -119,6 +119,8 @@ typedef struct {
typedef struct {
uint8_t harq_pid;
uint8_t ack_nack;
uint8_t *ack_nack_rcvd;
uint8_t num_acks_rcvd;
uint32_t pdu_length;
uint8_t* pdu;
} fapi_nr_pdsch_pdu_t;

View File

@@ -942,6 +942,7 @@ typedef struct
uint16_t scramb_id; // ScramblingID of the CSI-RS [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->1023
uint8_t power_control_offset; // Ratio of PDSCH EPRE to NZP CSI-RSEPRE [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->23 representing -8 to 15 dB in 1dB steps; 255: L1 is configured with ProfileSSS
uint8_t power_control_offset_ss; // Ratio of NZP CSI-RS EPRE to SSB/PBCH block EPRE [3GPP TS 38.214, sec 5.2.2.3.1], Values: 0: -3dB; 1: 0dB; 2: 3dB; 3: 6dB; 255: L1 is configured with ProfileSSS
uint8_t measurement_bitmap;
} nfapi_nr_dl_tti_csi_rs_pdu_rel15_t;

View File

@@ -4,12 +4,31 @@
#include "fapi_nr_ue_interface.h"
#define SL_NR_RX_CONFIG_LIST_NUM 1
#define SL_NR_TX_CONFIG_LIST_NUM 1
#define SL_NR_RX_IND_MAX_PDU 1
#define SL_NR_TX_CONFIG_LIST_NUM 1 //Jin original 1, change to 2
#define SL_NR_RX_IND_MAX_PDU 2
#define SL_NR_SCI_IND_MAX_PDU 2
#define SL_NR_MAX_PSCCH_SCI_LENGTH_IN_BYTES 8
#define SL_NR_MAX_PSSCH_SCI_LENGTH_IN_BYTES 8
#define SL_NR_MAX_SCI_LENGTH_IN_BYTES 8
typedef struct sl_nr_tti_csi_rs_pdu {
uint8_t subcarrier_spacing; // subcarrierSpacing [3GPP TS 38.211, sec 4.2], Value:0->4
uint8_t cyclic_prefix; // Cyclic prefix type [3GPP TS 38.211, sec 4.2], 0: Normal; 1: Extended
uint16_t start_rb; // PRB where this CSI resource starts related to common resource block #0 (CRB#0). Only multiples of 4 are allowed. [3GPP TS 38.331, sec 6.3.2 parameter CSIFrequencyOccupation], Value: 0 ->274
uint16_t nr_of_rbs; // Number of PRBs across which this CSI resource spans. Only multiples of 4 are allowed. [3GPP TS 38.331, sec 6.3.2 parameter CSI-FrequencyOccupation], Value: 24 -> 276
uint8_t csi_type; // CSI Type [3GPP TS 38.211, sec 7.4.1.5], Value: 0:TRS; 1:CSI-RS NZP; 2:CSI-RS ZP
uint8_t row; // Row entry into the CSI Resource location table. [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 1-18
uint16_t freq_domain; // Bitmap defining the frequencyDomainAllocation [3GPP TS 38.211, sec 7.4.1.5.3] [3GPP TS 38.331 CSIResourceMapping], Value: Up to the 12 LSBs, actual size is determined by the Row parameter
uint8_t symb_l0; // The time domain location l0 and firstOFDMSymbolInTimeDomain [3GPP TS 38.211, sec 7.4.1.5.3], Value: 0->13
uint8_t symb_l1; // The time domain location l1 and firstOFDMSymbolInTimeDomain2 [3GPP TS 38.211, sec 7.4.1.5.3], Value: 2->12
uint8_t cdm_type; // The cdm-Type field [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 0: noCDM; 1: fd-CDM2; 2: cdm4-FD2-TD2; 3: cdm8-FD2-TD4
uint8_t freq_density; // The density field, p and comb offset (for dot5). [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 0: dot5 (even RB); 1: dot5 (odd RB); 2: one; 3: three
uint16_t scramb_id; // ScramblingID of the CSI-RS [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->1023
uint8_t power_control_offset; // Ratio of PDSCH EPRE to NZP CSI-RSEPRE [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->23 representing -8 to 15 dB in 1dB steps; 255: L1 is configured with ProfileSSS
uint8_t power_control_offset_ss; // Ratio of NZP CSI-RS EPRE to SSB/PBCH block EPRE [3GPP TS 38.214, sec 5.2.2.3.1], Values: 0: -3dB; 1: 0dB; 2: 3dB; 3: 6dB; 255: L1 is configured with ProfileSSS
uint8_t measurement_bitmap; // bit 0 RSRP, bit 1 RI, bit 2 LI, bit 3 PMI, bit 4 CQI, bit 5 i1
} sl_nr_tti_csi_rs_pdu_t;
typedef enum sl_sci_format_type_enum {
SL_SCI_INVALID_FORMAT,
SL_SCI_FORMAT_1A_ON_PSCCH,
@@ -20,7 +39,8 @@ typedef enum sl_sci_format_type_enum {
typedef enum sl_rx_pdu_type_enum {
SL_NR_RX_PDU_TYPE_NONE,
SL_NR_RX_PDU_TYPE_SSB,
SL_NR_RX_PDU_TYPE_SLSCH
SL_NR_RX_PDU_TYPE_SLSCH,
SL_NR_RX_PDU_TYPE_SLSCH_PSFCH,
} sl_rx_pdu_type_enum_t;
//Type of SL-RX CONFIG requests from MAC to PHY
@@ -29,6 +49,8 @@ typedef enum sl_nr_rx_config_type_enum {
SL_NR_CONFIG_TYPE_RX_PSCCH,
SL_NR_CONFIG_TYPE_RX_PSSCH_SCI,
SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH,
SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_PSFCH,
SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_CSI_RS,
SL_NR_CONFIG_TYPE_RX_MAXIMUM
} sl_nr_rx_config_type_enum_t;
@@ -36,7 +58,8 @@ typedef enum sl_nr_rx_config_type_enum {
typedef enum sl_nr_tx_config_type_enum {
SL_NR_CONFIG_TYPE_TX_PSBCH = SL_NR_CONFIG_TYPE_RX_MAXIMUM + 1,
SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH,
SL_NR_CONFIG_TYPE_TX_PSFCH,
SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH,
SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS,
SL_NR_CONFIG_TYPE_TX_MAXIMUM
} sl_nr_tx_config_type_enum_t;
@@ -68,7 +91,7 @@ typedef struct {
uint8_t sensing_result;
//in case pssch sensing is requested.
int16_t pssch_rsrp;
sl_nr_sci_indication_pdu_t sci_pdu;
sl_nr_sci_indication_pdu_t sci_pdu[SL_NR_SCI_IND_MAX_PDU];
} sl_nr_sci_indication_t;
// IF UE Rx PSBCH, PHY indicates MAC with received MIB and PSBCH RSRP
@@ -190,6 +213,22 @@ typedef struct sl_nr_rx_config_pssch_pdu {
uint8_t ndi;
} sl_nr_rx_config_pssch_pdu_t;
typedef struct sl_nr_tx_rx_config_psfch_pdu {
// These fields can be mapped directly to the same fields in nfapi_nr_ul_config_pucch_pdu
uint8_t freq_hop_flag;
uint8_t group_hop_flag;
uint8_t sequence_hop_flag;
uint16_t second_hop_prb;
uint8_t nr_of_symbols;
uint8_t start_symbol_index;
uint8_t hopping_id;
uint16_t prb;
uint16_t sl_bwp_start;
uint16_t initial_cyclic_shift;
uint8_t mcs;
uint8_t bit_len_harq;
} sl_nr_tx_rx_config_psfch_pdu_t;
typedef struct {
sl_nr_rx_config_type_enum_t pdu_type; // indicates the type of RX config request
union {
@@ -197,6 +236,9 @@ typedef struct {
sl_nr_rx_config_pssch_sci_pdu_t rx_sci2_config_pdu;
sl_nr_rx_config_pssch_pdu_t rx_pssch_config_pdu;
};
sl_nr_tti_csi_rs_pdu_t rx_csi_rs_config_pdu;
sl_nr_tx_rx_config_psfch_pdu_t *rx_psfch_pdu_list;
uint16_t num_psfch_pdus;
} sl_nr_rx_config_request_pdu_t;
// MAC commands PHY to perform an action on RX RESOURCE POOL or RX PSBCH using this RX CONFIG
@@ -243,6 +285,9 @@ typedef struct sl_nr_tx_config_pscch_pssch_pdu {
//Indicates the number of symbols for PSCCH+PSSCH txn
uint8_t pssch_numsym;
// start symbol of PSCCH/PSSCH (excluding AGC)
uint8_t pssch_startsym;
//.... Other Parameters for SCI-2 and PSSCH
// Used to determine number of SCI2 modulated symbols
@@ -265,14 +310,21 @@ typedef struct sl_nr_tx_config_pscch_pssch_pdu {
// Table from SPEC 38.211, Table 8.4.1.1.2-1
uint16_t dmrs_symbol_position;
// PSFCH related parameters
sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu_list;
uint16_t num_psfch_pdus;
//....TBD.. any additional parameters
// CSI-RS related parameters
sl_nr_tti_csi_rs_pdu_t nr_sl_csi_rs_pdu;
//TX Power for PSSCH in symbol without PSCCH.
// Power for PSCCH and power for PSSCH in symbol with PSCCH is calculated
// from this value according to 38.213 section 16
int16_t pssch_tx_power;
uint16_t slsch_payload_length;
uint8_t *slsch_payload;
} sl_nr_tx_config_pscch_pssch_pdu_t;
// MAC indicates PHY to send PSBCH.
@@ -351,7 +403,7 @@ typedef struct
uint16_t sl_bandwidth;
//Absolute frequency of SL point A in KHz
//n38 (2570-2620 Mhz), n47 (5855-5925 Mhz) are defined.
uint32_t sl_frequency;
uint64_t sl_frequency;
//Only 1 SCS-SpecificCarrier allowed for NR-SL communication
uint16_t sl_grid_size;// bandwidth for each numerology
@@ -363,7 +415,7 @@ typedef struct
uint8_t sl_frequency_shift_7p5khz;
//Indicates presence of +/-5Khz shift wrt FREF for V2X reference frequencies.
//Possible values: {-1,0,1}
uint8_t sl_value_N;
int8_t sl_value_N;
} sl_nr_carrier_config_t;
@@ -382,7 +434,26 @@ typedef struct {
//only 1 SL-BWP can be configured in REL16, REL17
sl_nr_bwp_config_t sl_bwp_config;
uint32_t sl_DMRS_ScrambleId;
} sl_nr_phy_config_request_t;
/* Dependencies */
typedef enum NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR {
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_NOTHING, /* No components present */
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots4,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots5,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots8,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots10,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots16,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots20,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots32,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots40,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots64,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots80,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots160,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots320,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots640
} NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR;
#endif

View File

@@ -339,6 +339,10 @@ int check_crc(uint8_t* decoded_bytes, uint32_t n, uint8_t crc_type)
for (int i=0; i<crc_len; i++)
oldcrc |= (decoded_bytes[(n>>3)-crc_len+i])<<((crc_len-1-i)<<3);
if (oldcrc == 0) {
return 0;
}
switch (crc_type) {
case CRC24_A:

View File

@@ -451,11 +451,15 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
// Parity Check not necessary here since it will fail
// because first 2 cols/BNs in BG are punctured and cannot be
// estimated after only one iteration
// Added 2 to numMaxIter to execute ldpc process five times (max. iterations);
// it is skipping first two iterations so, previously, it was iterating only three times
// In case of check_crc() pass, we subtracted 2 to consider upto 7 iterations (worst case) only; in case of iteration 8,
// it will still consider the ldpc decoding as abort
// First iteration finished
uint32_t numIter = 1;
int32_t pcRes = 1; // pcRes is 0 if the ldpc decoder is succesful
while ((numIter <= numMaxIter) && (pcRes != 0)) {
while ((numIter <= numMaxIter + 2) && (pcRes != 0)) {
// Increase iteration counter
numIter++;
if (check_abort(ab)) {
@@ -713,6 +717,7 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
nrLDPC_llr2bit(p_out, p_llrOut, numLLR);
if (check_crc((uint8_t*)p_out, p_decParams->block_length, p_decParams->crc_type)) {
LOG_D(PHY, "Segment CRC OK, exiting LDPC decoder\n");
numIter -= 2;
break;
}
}

View File

@@ -34,6 +34,8 @@
#define __NR_POLAR_DCI_DEFS__H__
#define NR_POLAR_DCI_MESSAGE_TYPE 1 //int8_t
#define NR_POLAR_SCI_MESSAGE_TYPE (NR_POLAR_PSBCH_MESSAGE_TYPE + 1) //int8_t
#define NR_POLAR_SCI2_MESSAGE_TYPE (NR_POLAR_SCI_MESSAGE_TYPE + 1) //int8_t
#define NR_POLAR_DCI_CRC_PARITY_BITS 24
#define NR_POLAR_DCI_CRC_ERROR_CORRECTION_BITS 3

View File

@@ -607,6 +607,7 @@ void init_polar_deinterleaver_table(t_nrPolar_params *polarParams) {
uint32_t polar_decoder_int16(int16_t *input,
uint64_t *out,
uint16_t *nid,
uint8_t ones_flag,
int8_t messageType,
uint16_t messageLength,
@@ -615,7 +616,7 @@ uint32_t polar_decoder_int16(int16_t *input,
t_nrPolar_params *polarParams=nr_polar_params(messageType, messageLength, aggregation_level, true);
#ifdef POLAR_CODING_DEBUG
printf("\nRX\n");
printf("\nRX N %d (messageType %d messageLength %d aggregation_level %d)\n",polarParams->N,messageType,messageLength,aggregation_level);
printf("rm:");
for (int i = 0; i < polarParams->N; i++) {
if (i % 4 == 0) {
@@ -794,5 +795,6 @@ uint32_t polar_decoder_int16(int16_t *input,
#endif
out[0]=Ar;
if (nid) *nid=crc&65535;
polarReturn crc^rxcrc;
}

View File

@@ -153,6 +153,7 @@ void polar_encoder_dci(uint32_t *in,
void polar_encoder_fast(uint64_t *A,
void *out,
uint32_t *crc,
int32_t crcmask,
uint8_t ones_flag,
int8_t messageType,
@@ -168,6 +169,7 @@ int8_t polar_decoder(double *input,
uint32_t polar_decoder_int16(int16_t *input,
uint64_t *out,
uint16_t *nid,
uint8_t ones_flag,
int8_t messageType,
uint16_t messageLength,

View File

@@ -304,6 +304,7 @@ void nr_polar_rm_interleaving_cb(void *in, void *out, uint16_t E)
static inline void polar_rate_matching(const t_nrPolar_params *polarParams,void *in,void *out) __attribute__((always_inline));
static inline void polar_rate_matching(const t_nrPolar_params *polarParams,void *in,void *out) {
int i = 0;
// handle rate matching with a single 128 bit word using bit shuffling
// can be done with SIMD intrisics if needed
@@ -343,15 +344,20 @@ static inline void polar_rate_matching(const t_nrPolar_params *polarParams,void
}
// These are based on LUTs for byte and short word groups
else if (polarParams->groupsize == 8)
for (int i=0; i<polarParams->encoderLength>>3; i++) ((uint8_t *)out)[i] = ((uint8_t *)in)[polarParams->rm_tab[i]];
for (i=0; i<polarParams->encoderLength>>3; i++) ((uint8_t *)out)[i] = ((uint8_t *)in)[polarParams->rm_tab[i]];
else // groupsize==16
for (int i=0; i<polarParams->encoderLength>>4; i++) {
for (i=0; i<polarParams->encoderLength>>4; i++) {
((uint16_t *)out)[i] = ((uint16_t *)in)[polarParams->rm_tab[i]];
}
if (polarParams->i_bil == 1) {
nr_polar_rm_interleaving_cb(out, out, polarParams->encoderLength);
}
// handle remaining bits which do not fill a full group
for(i=i*polarParams->groupsize; i<polarParams->encoderLength; i++) {
uint8_t pi = polarParams->rate_matching_pattern[i];
((uint8_t *)out)[i>>3] |= ( ((((uint8_t *)in)[pi >> 3] >> (pi & 7)) & 1) << (i&7));
}
}
void build_polar_tables(t_nrPolar_params *polarParams) {
@@ -448,8 +454,8 @@ void build_polar_tables(t_nrPolar_params *polarParams) {
}
#ifdef DEBUG_POLAR_ENCODER
groupcnt++;
#endif
if ((ccnt+1)<mingroupsize) mingroupsize=ccnt+1;
#endif
//if ((ccnt+1)<mingroupsize) mingroupsize=ccnt+1;
#ifdef DEBUG_POLAR_ENCODER
printf("group %d (size %d): (%d:%d) => (%d:%d)\n",groupcnt,ccnt+1,
firstingroup_in,firstingroup_in+ccnt,
@@ -477,8 +483,7 @@ void build_polar_tables(t_nrPolar_params *polarParams) {
break;
}
polarParams->rm_tab = (int *)malloc(sizeof(int) * (polarParams->encoderLength >> shift));
polarParams->rm_tab=(int *)malloc(sizeof(int)*((polarParams->encoderLength+mingroupsize-1)/mingroupsize));
// rerun again to create groups
int tcnt = 0;
for (int outpos = 0; outpos < polarParams->encoderLength; outpos += mingroupsize, tcnt++)
@@ -487,6 +492,7 @@ void build_polar_tables(t_nrPolar_params *polarParams) {
void polar_encoder_fast(uint64_t *A,
void *out,
uint32_t *crc,
int32_t crcmask,
uint8_t ones_flag,
int8_t messageType,
@@ -599,7 +605,7 @@ void polar_encoder_fast(uint64_t *A,
else if (polarParams->crcParityBits == 11)
tcrc = (uint64_t)((crcmask^(crc11(A128_flip,bitlen)>>21)))&0x7ff;
}
if (crc) *crc = (uint32_t)tcrc;
// this is number of quadwords in the bit string
int quadwlen = (polarParams->K+63)/64;
@@ -707,11 +713,12 @@ void polar_encoder_fast(uint64_t *A,
printf("\n");
#endif
memset((void*)out,0,polarParams->encoderLength>>3);
memset((void*)out,0,(polarParams->encoderLength + 7)>>3);
polar_rate_matching(polarParams,(void *)D, out);
#ifdef POLAR_CODING_DEBUG
uint64_t *out64 = (uint64_t *)out;
printf("N %d, encoderLength %d\n",polarParams->N,polarParams->encoderLength);
printf("rm:");
for (int n = 0; n < polarParams->encoderLength; n++) {
if (n % 4 == 0) {

View File

@@ -0,0 +1,57 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file /PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h
\brief Polar definitions required for Sidelink PSBCH
\author
\date
\version
\company: Fraunhofer
\email:
\note
\warning
*/
#ifndef __NR_POLAR_PSBCH_DEFS__H__
#define __NR_POLAR_PSBCH_DEFS__H__
//PSBCH related polar parameters.
//PSBCH symbols sent in 11RBS, 9 symbols. 11*9*(12-3(for DMRS))*2bits = 1782 bits
#define SL_NR_POLAR_PSBCH_E_NORMAL_CP 1782
//PSBCH symbols sent in 11RBS, 7 symbols. 11*7*(12-3(for DMRS))*2bits = 1386 bits
#define SL_NR_POLAR_PSBCH_E_EXT_CP 1386
// SL_NR_POLAR_PSBCH_E_NORMAL_CP/32
#define SL_NR_POLAR_PSBCH_E_DWORD 56
#define SL_NR_POLAR_PSBCH_MESSAGE_TYPE (NR_POLAR_UCI_PUCCH_MESSAGE_TYPE + 1)
#define SL_NR_POLAR_PSBCH_PAYLOAD_BITS 32
#define SL_NR_POLAR_PSBCH_AGGREGATION_LEVEL 0
#define SL_NR_POLAR_PSBCH_N_MAX 9
#define SL_NR_POLAR_PSBCH_I_IL 1
#define SL_NR_POLAR_PSBCH_I_SEG 0
#define SL_NR_POLAR_PSBCH_N_PC 0
#define SL_NR_POLAR_PSBCH_N_PC_WM 0
#define SL_NR_POLAR_PSBCH_I_BIL 0
#define SL_NR_POLAR_PSBCH_CRC_PARITY_BITS 24
#define SL_NR_POLAR_PSBCH_CRC_ERROR_CORRECTION_BITS 3
#endif

View File

@@ -32,6 +32,7 @@
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
#include "PHY/NR_TRANSPORT/nr_dci.h"
#include "nrPolar_tools/nr_polar_psbch_defs.h"
#define PolarKey ((messageType<<24)|(messageLength<<8)|aggregation_level)
static t_nrPolar_params * PolarList=NULL;
@@ -98,7 +99,7 @@ t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, ui
//Parse the list. If the node is already created, return without initialization.
while (currentPtr != NULL) {
//printf("currentPtr->idx %d, (%d,%d)\n",currentPtr->idx,currentPtr->payloadBits,currentPtr->encoderLength);
//LOG_D(PHY,"Looking for index %d\n",(messageType * messageLength * aggregation_prime));
LOG_D(NR_PHY,"Looking for index %d\n",(messageType * messageLength * aggregation_level));
if (currentPtr->busy == false && currentPtr->idx == PolarKey ) {
currentPtr->busy=true;
pthread_mutex_unlock(&PolarListMutex);
@@ -194,7 +195,39 @@ t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, ui
newPolarInitNode->payloadBits = messageLength;
newPolarInitNode->crcCorrectionBits = NR_POLAR_PUCCH_CRC_ERROR_CORRECTION_BITS;
//LOG_D(PHY,"New polar node, encoderLength %d, aggregation_level %d\n",newPolarInitNode->encoderLength,aggregation_level);
} else if (messageType == SL_NR_POLAR_PSBCH_MESSAGE_TYPE) { //PSBCH
newPolarInitNode->n_max = SL_NR_POLAR_PSBCH_N_MAX;
newPolarInitNode->i_il = SL_NR_POLAR_PSBCH_I_IL;
newPolarInitNode->i_seg = SL_NR_POLAR_PSBCH_I_SEG;
newPolarInitNode->n_pc = SL_NR_POLAR_PSBCH_N_PC;
newPolarInitNode->n_pc_wm = SL_NR_POLAR_PSBCH_N_PC_WM;
newPolarInitNode->i_bil = SL_NR_POLAR_PSBCH_I_BIL;
newPolarInitNode->crcParityBits = SL_NR_POLAR_PSBCH_CRC_PARITY_BITS;
newPolarInitNode->payloadBits = SL_NR_POLAR_PSBCH_PAYLOAD_BITS;
newPolarInitNode->encoderLength = SL_NR_POLAR_PSBCH_E_NORMAL_CP;
newPolarInitNode->crcCorrectionBits = SL_NR_POLAR_PSBCH_CRC_ERROR_CORRECTION_BITS;
newPolarInitNode->crc_generator_matrix = crc24c_generator_matrix(newPolarInitNode->payloadBits);//G_P
LOG_D(PHY,"SIDELINK: Initializing polar parameters for PSBCH (K %d, E %d)\n",newPolarInitNode->payloadBits,newPolarInitNode->encoderLength);
} else if (messageType == NR_POLAR_DCI_MESSAGE_TYPE || messageType == NR_POLAR_SCI_MESSAGE_TYPE || messageType == NR_POLAR_SCI2_MESSAGE_TYPE) {
newPolarInitNode->n_max = NR_POLAR_DCI_N_MAX;
newPolarInitNode->i_il = NR_POLAR_DCI_I_IL;
newPolarInitNode->i_seg = NR_POLAR_DCI_I_SEG;
newPolarInitNode->n_pc = NR_POLAR_DCI_N_PC;
newPolarInitNode->n_pc_wm = NR_POLAR_DCI_N_PC_WM;
newPolarInitNode->i_bil = NR_POLAR_DCI_I_BIL;
newPolarInitNode->crcParityBits = NR_POLAR_DCI_CRC_PARITY_BITS;
newPolarInitNode->payloadBits = messageLength;
if (messageType == NR_POLAR_DCI_MESSAGE_TYPE)
newPolarInitNode->encoderLength = aggregation_level * 108;
else if (messageType == NR_POLAR_SCI_MESSAGE_TYPE)
newPolarInitNode->encoderLength = aggregation_level * 18; // for SCI1A aggregartion_level helds the number of PRBs, so multiply by 9*2 bits per PRB (9 REs with PSCCH payload)
else if (messageType == NR_POLAR_SCI2_MESSAGE_TYPE)
newPolarInitNode->encoderLength = aggregation_level * 2; // for SCI2 aggregartion_level helds the number of REs so multiple by 2, QPSK )
newPolarInitNode->crcCorrectionBits = NR_POLAR_DCI_CRC_ERROR_CORRECTION_BITS;
newPolarInitNode->crc_generator_matrix = crc24c_generator_matrix(newPolarInitNode->payloadBits + newPolarInitNode->crcParityBits); // G_P
//printf("Initializing polar parameters for DCI (K %d, E %d, L %d)\n",newPolarInitNode->payloadBits,newPolarInitNode->encoderLength,aggregation_level);
} else if (messageType == NR_POLAR_UCI_PUCCH_MESSAGE_TYPE) {
} else {
AssertFatal(1 == 0, "[nr_polar_init] Incorrect Message Type(%d)", messageType);
}

View File

@@ -572,7 +572,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB)
nr_generate_modulation_table();
gNB->pdcch_gold_init = cfg->cell_config.phy_cell_id.value;
nr_init_pdcch_dmrs(gNB, cfg->cell_config.phy_cell_id.value);
nr_init_pdcch_dmrs(&gNB->frame_parms,gNB->nr_gold_pdcch_dmrs, cfg->cell_config.phy_cell_id.value);
nr_init_pbch_interleaver(gNB->nr_pbch_interleaver);
//PDSCH DMRS init

View File

@@ -28,6 +28,7 @@
#include "PHY/MODULATION/nr_modulation.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
#include "PHY/NR_REFSIG/pss_nr.h"
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
@@ -35,6 +36,9 @@
#include "PHY/MODULATION/nr_modulation.h"
#include "openair2/COMMON/prs_nr_paramdef.h"
#include "SCHED_NR_UE/harq_nr.h"
#include "PHY/NR_REFSIG/nr_mod_table.h"
#include <math.h>
#include <complex.h>
void RCconfig_nrUE_prs(void *cfg)
{
@@ -296,8 +300,12 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
// init RX buffers
common_vars->rxdata = malloc16(fp->nb_antennas_rx * sizeof(c16_t *));
int num_samples = 2 * fp->samples_per_frame + fp->ofdm_symbol_size;
if (ue->sl_mode == 2)
num_samples = (SL_NR_PSBCH_REPETITION_IN_FRAMES * fp->samples_per_frame) + fp->ofdm_symbol_size;
for (i=0; i<fp->nb_antennas_rx; i++) {
common_vars->rxdata[i] = malloc16_clear((2 * (fp->samples_per_frame) + fp->ofdm_symbol_size) * sizeof(c16_t));
common_vars->rxdata[i] = malloc16_clear(num_samples * sizeof(c16_t));
}
// ceil(((NB_RB<<1)*3)/32) // 3 RE *2(QPSK)
@@ -384,6 +392,15 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
return 0;
}
static void sl_ue_free(PHY_VARS_NR_UE *UE) {
if (UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation) {
free_and_zero(UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation[0]);
free_and_zero(UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation[1]);
free_and_zero(UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation);
}
}
void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
{
const NR_DL_FRAME_PARMS* fp = &ue->frame_parms;
@@ -489,6 +506,8 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
free_and_zero(ue->prs_vars[idx]);
}
sl_ue_free(ue);
}
void free_nr_ue_dl_harq(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PROCESSES], int number_of_processes, int num_rb) {
@@ -540,8 +559,10 @@ void term_nr_ue_transport(PHY_VARS_NR_UE *ue)
{
const int N_RB_DL = ue->frame_parms.N_RB_DL;
const int N_RB_UL = ue->frame_parms.N_RB_UL;
const int N_RB_SL = ue->SL_UE_PHY_PARAMS.sl_frame_params.N_RB_SL;
free_nr_ue_dl_harq(ue->dl_harq_processes, NR_MAX_DLSCH_HARQ_PROCESSES, N_RB_DL);
free_nr_ue_ul_harq(ue->ul_harq_processes, NR_MAX_ULSCH_HARQ_PROCESSES, N_RB_UL, ue->frame_parms.nb_antennas_tx);
free_nr_ue_ul_harq(ue->sl_harq_processes, NR_MAX_SLSCH_HARQ_PROCESSES, N_RB_SL, ue->SL_UE_PHY_PARAMS.sl_frame_params.nb_antennas_tx);
}
void nr_init_dl_harq_processes(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PROCESSES], int number_of_processes, int num_rb) {
@@ -624,6 +645,7 @@ void init_nr_ue_transport(PHY_VARS_NR_UE *ue) {
nr_init_dl_harq_processes(ue->dl_harq_processes, NR_MAX_DLSCH_HARQ_PROCESSES, ue->frame_parms.N_RB_DL);
nr_init_ul_harq_processes(ue->ul_harq_processes, NR_MAX_ULSCH_HARQ_PROCESSES, ue->frame_parms.N_RB_UL, ue->frame_parms.nb_antennas_tx);
nr_init_ul_harq_processes(ue->sl_harq_processes, NR_MAX_SLSCH_HARQ_PROCESSES, ue->SL_UE_PHY_PARAMS.sl_frame_params.N_RB_SL, ue->frame_parms.nb_antennas_tx);
for(int i=0; i<5; i++)
ue->dl_stats[i] = 0;
@@ -634,7 +656,8 @@ void init_N_TA_offset(PHY_VARS_NR_UE *ue){
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
if (fp->frame_type == FDD) {
// No timing offset for Sidelink, refer to 3GPP 38.211 Section 8.5
if (fp->frame_type == FDD || ue->sl_mode == 2) {
ue->N_TA_offset = 0;
} else {
int N_TA_offset = fp->ul_CarrierFreq < 6e9 ? 400 : 431; // reference samples for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2
@@ -686,3 +709,364 @@ void phy_term_nr_top(void)
free_ul_reference_signal_sequences();
free_context_synchro_nr();
}
static void sl_init_psbch_dmrs_gold_sequences(PHY_VARS_NR_UE *UE)
{
unsigned int x1, x2;
uint16_t slss_id;
uint8_t reset;
for (slss_id = 0; slss_id < SL_NR_NUM_SLSS_IDs; slss_id++) {
reset = 1;
x2 = slss_id;
#ifdef SL_DEBUG_INIT
printf("\nPSBCH DMRS GOLD SEQ for SLSSID :%d :\n", slss_id);
#endif
for (uint8_t n=0; n<SL_NR_NUM_PSBCH_DMRS_RE_DWORD; n++) {
UE->SL_UE_PHY_PARAMS.init_params.psbch_dmrs_gold_sequences[slss_id][n] = lte_gold_generic(&x1, &x2, reset);
reset = 0;
#ifdef SL_DEBUG_INIT_DATA
printf("%x\n",SL_UE_INIT_PARAMS.sl_psbch_dmrs_gold_sequences[slss_id][n]);
#endif
}
}
}
static void sl_generate_psbch_dmrs_qpsk_sequences(PHY_VARS_NR_UE *UE,
struct complex16 *modulated_dmrs_sym,
uint16_t slss_id) {
uint8_t idx = 0;
uint32_t *sl_dmrs_sequence = UE->SL_UE_PHY_PARAMS.init_params.psbch_dmrs_gold_sequences[slss_id];
#ifdef SL_DEBUG_INIT
printf("SIDELINK INIT: PSBCH DMRS Generation with slss_id:%d\n", slss_id);
#endif
/// QPSK modulation
for (int m=0; m<SL_NR_NUM_PSBCH_DMRS_RE; m++) {
idx = (((sl_dmrs_sequence[(m<<1)>>5])>>((m<<1)&0x1f))&3);
modulated_dmrs_sym[m].r = nr_qpsk_mod_table[2*idx];
modulated_dmrs_sym[m].i = nr_qpsk_mod_table[(2*idx) + 1];
#ifdef SL_DEBUG_INIT_DATA
printf("m:%d gold seq: %d b0-b1: %d-%d DMRS Symbols: %d %d\n", m, sl_dmrs_sequence[(m<<1)>>5], (((sl_dmrs_sequence[(m<<1)>>5])>>((m<<1)&0x1f))&1),
(((sl_dmrs_sequence[((m<<1)+1)>>5])>>(((m<<1)+1)&0x1f))&1), modulated_dmrs_sym[m].r, modulated_dmrs_sym[m].i);
printf("idx:%d, qpsk_table.r:%d, qpsk_table.i:%d\n", idx, nr_qpsk_mod_table[2*idx], nr_qpsk_mod_table[(2*idx) + 1]);
#endif
}
#ifdef SL_DUMP_INIT_SAMPLES
char filename[40], varname[25];
sprintf(filename,"sl_psbch_dmrs_slssid_%d.m", slss_id);
sprintf(varname,"sl_dmrs_id_%d.m", slss_id);
LOG_M(filename, varname, (void*)modulated_dmrs_sym, SL_NR_NUM_PSBCH_DMRS_RE, 1, 1);
#endif
}
static void sl_generate_pss(SL_NR_UE_INIT_PARAMS_t *sl_init_params, uint8_t n_sl_id2, uint16_t scaling) {
int i = 0, m = 0;
int16_t x[SL_NR_PSS_SEQUENCE_LENGTH];
const int x_initial[7] = {0, 1, 1 , 0, 1, 1, 1};
int16_t *sl_pss = sl_init_params->sl_pss[n_sl_id2];
int16_t *sl_pss_for_sync = sl_init_params->sl_pss_for_sync[n_sl_id2];
LOG_D(PHY, "SIDELINK PSBCH INIT: PSS Generation with N_SL_id2:%d\n", n_sl_id2);
#ifdef SL_DEBUG_INIT
printf("SIDELINK: PSS Generation with N_SL_id2:%d\n", n_sl_id2);
#endif
/// Sequence generation
for (i=0; i < 7; i++)
x[i] = x_initial[i];
for (i=0; i < (SL_NR_PSS_SEQUENCE_LENGTH - 7); i++) {
x[i+7] = (x[i + 4] + x[i]) %2;
}
for (i=0; i < SL_NR_PSS_SEQUENCE_LENGTH; i++) {
m = (i + 22 + 43*n_sl_id2) % SL_NR_PSS_SEQUENCE_LENGTH;
sl_pss_for_sync[i] = (1 - 2*x[m]);
sl_pss[i] = sl_pss_for_sync[i] * scaling;
#ifdef SL_DEBUG_INIT_DATA
printf("m:%d, sl_pss[%d]:%d\n", m, i, sl_pss[i]);
#endif
}
#ifdef SL_DUMP_INIT_SAMPLES
LOG_M("sl_pss_seq.m", "sl_pss", (void*)sl_pss, SL_NR_PSS_SEQUENCE_LENGTH, 1, 0);
#endif
}
static void sl_generate_sss(SL_NR_UE_INIT_PARAMS_t *sl_init_params, uint16_t slss_id, uint16_t scaling) {
int i = 0;
int m0, m1;
int n_sl_id1, n_sl_id2;
int16_t *sl_sss = sl_init_params->sl_sss[slss_id];
int16_t *sl_sss_for_sync = sl_init_params->sl_sss_for_sync[slss_id];
int16_t x0[SL_NR_SSS_SEQUENCE_LENGTH], x1[SL_NR_SSS_SEQUENCE_LENGTH];
const int x_initial[7] = { 1, 0, 0, 0, 0, 0, 0 };
n_sl_id1 = slss_id % 336;
n_sl_id2 = slss_id / 336;
LOG_D(PHY, "SIDELINK INIT: SSS Generation with N_SL_id1:%d N_SL_id2:%d\n", n_sl_id1, n_sl_id2);
#ifdef SL_DEBUG_INIT
printf("SIDELINK: SSS Generation with slss_id:%d, N_SL_id1:%d, N_SL_id2:%d\n", slss_id, n_sl_id1, n_sl_id2);
#endif
for ( i=0 ; i < 7 ; i++) {
x0[i] = x_initial[i];
x1[i] = x_initial[i];
}
for ( i=0 ; i < SL_NR_SSS_SEQUENCE_LENGTH - 7 ; i++) {
x0[i+7] = (x0[i + 4] + x0[i]) % 2;
x1[i+7] = (x1[i + 1] + x1[i]) % 2;
}
m0 = 15*(n_sl_id1/112) + (5*n_sl_id2);
m1 = n_sl_id1 % 112;
for (i = 0; i < SL_NR_SSS_SEQUENCE_LENGTH ; i++) {
sl_sss_for_sync[i] = (1 - 2*x0[(i + m0) % SL_NR_SSS_SEQUENCE_LENGTH] ) * (1 - 2*x1[(i + m1) % SL_NR_SSS_SEQUENCE_LENGTH] );
sl_sss[i] = sl_sss_for_sync[i] * scaling;
#ifdef SL_DEBUG_INIT_DATA
printf("m0:%d, m1:%d, sl_sss_for_sync[%d]:%d, sl_sss[%d]:%d\n", m0, m1, i, sl_sss_for_sync[i], i, sl_sss[i]);
#endif
}
#ifdef SL_DUMP_PSBCH_TX_SAMPLES
LOG_M("sl_sss_seq.m", "sl_sss", (void*)sl_sss, SL_NR_SSS_SEQUENCE_LENGTH, 1, 0);
LOG_M("sl_sss_forsync_seq.m", "sl_sss_for_sync", (void*)sl_sss_for_sync, SL_NR_SSS_SEQUENCE_LENGTH, 1, 0);
#endif
}
// This cannot be done at init time as ofdm symbol size, ssb start subcarrier depends on configuration
// done at SLSS read time.
static void sl_generate_pss_ifft_samples(sl_nr_ue_phy_params_t *sl_ue_params, SL_NR_UE_INIT_PARAMS_t *sl_init_params) {
uint8_t id2 = 0;
int16_t *sl_pss = NULL;
NR_DL_FRAME_PARMS *sl_fp = &sl_ue_params->sl_frame_params;
int16_t scaling_factor = AMP;
int16_t *pss_F = NULL; // IQ samples in freq domain
int32_t *pss_T = NULL;
uint16_t k = 0;
pss_F = malloc16_clear(2*sizeof(int16_t) * sl_fp->ofdm_symbol_size);
LOG_I(PHY, "SIDELINK INIT: Generation of PSS time domain samples. scaling_factor:%d\n", scaling_factor);
for (id2 = 0; id2 < SL_NR_NUM_IDs_IN_PSS; id2++) {
k = sl_fp->first_carrier_offset + sl_fp->ssb_start_subcarrier + 2; // PSS in from REs 2-129
if (k >= sl_fp->ofdm_symbol_size) k -= sl_fp->ofdm_symbol_size;
pss_T = &sl_init_params->sl_pss_for_correlation[id2][0];
sl_pss = sl_init_params->sl_pss[id2];
memset(pss_T, 0, sl_fp->ofdm_symbol_size * sizeof(pss_T[0]));
memset(pss_F, 0, sl_fp->ofdm_symbol_size * 2 * sizeof(pss_F[0]));
for (int i=0; i < SL_NR_PSS_SEQUENCE_LENGTH; i++) {
pss_F[2*k] = (sl_pss[i] * scaling_factor) >> 15;
//pss_F[2*k] = (sl_pss[i]/23170) * 4192;
//pss_F[2*k+1] = 0;
#ifdef SL_DEBUG_INIT_DATA
printf("id:%d, k:%d, pss_F[%d]:%d, sl_pss[%d]:%d\n", id2, k, 2*k, pss_F[2*k], i, sl_pss[i]);
#endif
k++;
if (k == sl_fp->ofdm_symbol_size) k=0;
}
idft((int16_t)get_idft(sl_fp->ofdm_symbol_size),
pss_F, /* complex input */
(int16_t *)&pss_T[0], /* complex output */
1); /* scaling factor */
}
#ifdef SL_DUMP_PSBCH_TX_SAMPLES
LOG_M("sl_pss_TD_id0.m", "pss_TD_0", (void*)sl_init_params->sl_pss_for_correlation[0], sl_fp->ofdm_symbol_size, 1, 1);
LOG_M("sl_pss_TD_id1.m", "pss_TD_1", (void*)sl_init_params->sl_pss_for_correlation[1], sl_fp->ofdm_symbol_size, 1, 1);
#endif
free(pss_F);
}
void init_ul_delay_table(NR_DL_FRAME_PARMS *fp)
{
for (int delay = -MAX_UL_DELAY_COMP; delay <= MAX_UL_DELAY_COMP; delay++) {
for (int k = 0; k < fp->ofdm_symbol_size; k++) {
double complex delay_cexp = cexp(I * (2.0 * M_PI * k * delay / fp->ofdm_symbol_size));
fp->ul_delay_table[MAX_UL_DELAY_COMP + delay][k].r = (int16_t)round(256 * creal(delay_cexp));
fp->ul_delay_table[MAX_UL_DELAY_COMP + delay][k].i = (int16_t)round(256 * cimag(delay_cexp));
}
}
}
void sl_ue_phy_init(PHY_VARS_NR_UE *UE) {
uint16_t scaling_value = ONE_OVER_SQRT2_Q15;
NR_DL_FRAME_PARMS *sl_fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
if (!UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation) {
UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation = (int32_t **)malloc16_clear(SL_NR_NUM_IDs_IN_PSS *sizeof(int32_t *) );
UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation[0] = (int32_t *)malloc16_clear( sizeof(int32_t)*sl_fp->ofdm_symbol_size);
UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation[1] = (int32_t *)malloc16_clear( sizeof(int32_t)*sl_fp->ofdm_symbol_size);
}
LOG_I(PHY, "SIDELINK INIT: GENERATE PSS, SSS, GOLD SEQUENCES AND PSBCH DMRS SEQUENCES FOR ALL possible SLSS IDs 0- 671\n");
// Generate PSS sequences for IDs 0,1 used in PSS
sl_generate_pss(&UE->SL_UE_PHY_PARAMS.init_params,0, scaling_value);
sl_generate_pss(&UE->SL_UE_PHY_PARAMS.init_params,1, scaling_value);
// Generate psbch dmrs Gold Sequences and modulated dmrs symbols
sl_init_psbch_dmrs_gold_sequences(UE);
// Generate pscch dmrs Gold Sequences
UE->nr_gold_pscch_dmrs = (uint32_t ***)malloc16(sl_fp->slots_per_frame*sizeof(uint32_t **));
uint32_t ***pscch_dmrs = UE->nr_gold_pscch_dmrs;
AssertFatal(pscch_dmrs!=NULL, "NR init: pscch_dmrs malloc failed\n");
int pscch_dmrs_init_length = (((sl_fp->N_RB_UL<<1)*3)>>5)+1;
for (int slot=0; slot<sl_fp->slots_per_frame; slot++) {
pscch_dmrs[slot] = (uint32_t **)malloc16(sl_fp->symbols_per_slot*sizeof(uint32_t *));
AssertFatal(pscch_dmrs[slot]!=NULL, "NR SL UE init: pscch_dmrs for slot %d - malloc failed\n", slot);
for (int symb=0; symb<sl_fp->symbols_per_slot; symb++) {
pscch_dmrs[slot][symb] = (uint32_t *)malloc16(pscch_dmrs_init_length*sizeof(uint32_t));
LOG_D(PHY,"pscch_dmrs[%d][%d] %p\n",slot,symb,pscch_dmrs[slot][symb]);
AssertFatal(pscch_dmrs[slot][symb]!=NULL, "NR SL UE init: pscch_dmrs for slot %d symbol %d - malloc failed\n", slot, symb);
}
}
nr_init_pdcch_dmrs(sl_fp,UE->nr_gold_pscch_dmrs, UE->SL_UE_PHY_PARAMS.sl_config.sl_DMRS_ScrambleId);
// PSCCH DMRS RX
UE->nr_gold_pscch = malloc16(sl_fp->slots_per_frame * sizeof(uint32_t **));
uint32_t ***pscch_dmrs_rx = UE->nr_gold_pscch;
AssertFatal(pscch_dmrs_rx!=NULL, "NR init: pscch_dmrs malloc failed\n");
for (int slot=0; slot<sl_fp->slots_per_frame; slot++) {
pscch_dmrs_rx[slot] = malloc16(sl_fp->symbols_per_slot * sizeof(uint32_t *));
AssertFatal(pscch_dmrs_rx[slot]!=NULL, "NR init: pscch_dmrs for slot %d - malloc failed\n", slot);
for (int symb=0; symb<sl_fp->symbols_per_slot; symb++) {
pscch_dmrs_rx[slot][symb] = malloc16(pscch_dmrs_init_length * sizeof(uint32_t));
AssertFatal(pscch_dmrs[slot][symb]!=NULL, "NR init: pscch_dmrs for slot %d symbol %d - malloc failed\n", slot, symb);
}
}
nr_gold_pdcch(sl_fp, pscch_dmrs_rx,UE->SL_UE_PHY_PARAMS.sl_config.sl_DMRS_ScrambleId);
// SSS
for (int slss_id = 0; slss_id < SL_NR_NUM_SLSS_IDs; slss_id++) {
sl_generate_psbch_dmrs_qpsk_sequences(UE, UE->SL_UE_PHY_PARAMS.init_params.psbch_dmrs_modsym[slss_id], slss_id);
sl_generate_sss(&UE->SL_UE_PHY_PARAMS.init_params, slss_id, scaling_value);
}
// Generate PSS time domain samples used for correlation during SLSS reception.
sl_generate_pss_ifft_samples(&UE->SL_UE_PHY_PARAMS, &UE->SL_UE_PHY_PARAMS.init_params);
UE->max_nb_slsch = NR_SLSCH_RX_MAX;
UE->slsch = (NR_gNB_ULSCH_t *)malloc16(UE->max_nb_slsch * sizeof(NR_gNB_ULSCH_t));
for (int i = 0; i < UE->max_nb_slsch; i++) {
LOG_I(PHY, "Allocating Transport Channel Buffers for SLSCH %d/%d\n", i, UE->max_nb_slsch);
UE->slsch[i] = new_gNB_ulsch(UE->max_ldpc_iterations, sl_fp->N_RB_UL);
}
int Prx=sl_fp->nb_antennas_rx;
int N_RB_UL = sl_fp->N_RB_UL;
int n_buf = 2*Prx;
int nb_re_pusch = N_RB_UL * NR_NB_SC_PER_RB;
int nb_re_pusch2 = nb_re_pusch + (nb_re_pusch&7);
UE->pssch_thres = 10;
UE->pssch_vars = (NR_gNB_PUSCH *)malloc16_clear(UE->max_nb_slsch * sizeof(NR_gNB_PUSCH));
for (int SLSCH_id = 0; SLSCH_id < NR_SLSCH_RX_MAX; SLSCH_id++) {
NR_gNB_PUSCH *pssch = &UE->pssch_vars[SLSCH_id];
pssch->rxdataF_ext = (int32_t **)malloc16(Prx * sizeof(int32_t *));
pssch->ul_ch_estimates = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pssch->ul_ch_estimates_ext = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pssch->ptrs_phase_per_slot = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pssch->ul_ch_estimates_time = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pssch->rxdataF_comp = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pssch->ul_ch_mag0 = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pssch->ul_ch_magb0 = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pssch->ul_ch_magc0 = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pssch->ul_ch_mag = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pssch->ul_ch_magb = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pssch->ul_ch_magc = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pssch->rho = (int32_t ***)malloc16(Prx * sizeof(int32_t **));
pssch->llr_layers = (int16_t **)malloc16(2 * sizeof(int32_t *));
for (int i = 0; i < Prx; i++) {
pssch->rxdataF_ext[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
pssch->rho[i] = (int32_t **)malloc16_clear(2 * 2 * sizeof(int32_t *));
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
pssch->rho[i][j * 2 + k] =
(int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
}
}
}
for (int i = 0; i < n_buf; i++) {
pssch->ul_ch_estimates[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * sl_fp->ofdm_symbol_size * sl_fp->symbols_per_slot);
pssch->ul_ch_estimates_ext[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
pssch->ul_ch_estimates_time[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * sl_fp->ofdm_symbol_size);
pssch->ptrs_phase_per_slot[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * sl_fp->symbols_per_slot); // symbols per slot
pssch->rxdataF_comp[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
pssch->ul_ch_mag0[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
pssch->ul_ch_magb0[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
pssch->ul_ch_magc0[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
pssch->ul_ch_mag[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
pssch->ul_ch_magb[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
pssch->ul_ch_magc[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
}
for (int i=0; i< 2; i++) {
pssch->llr_layers[i] = (int16_t *)malloc16_clear((8 * ((3 * 8 * 6144) + 12))
* sizeof(int16_t)); // [hna] 6144 is LTE and (8*((3*8*6144)+12)) is not clear
}
pssch->llr = (int16_t *)malloc16_clear((8 * ((3 * 8 * 6144) + 12))
* sizeof(int16_t)); // [hna] 6144 is LTE and (8*((3*8*6144)+12)) is not clear
pssch->ul_valid_re_per_slot = (int16_t *)malloc16_clear(sizeof(int16_t) * sl_fp->symbols_per_slot);
} // ulsch_id
UE->sl_measurements = calloc(1,sizeof(struct PHY_MEASUREMENTS_gNB_s));
init_ul_delay_table(sl_fp);
}

View File

@@ -23,6 +23,7 @@
#include "common/utils/nr/nr_common.h"
#include "common/utils/LOG/log.h"
#include "executables/softmodem-common.h"
#include "PHY/MODULATION/nr_modulation.h"
/// Subcarrier spacings in Hz indexed by numerology index
static const uint32_t nr_subcarrier_spacing[MAX_NUM_SUBCARRIER_SPACING] = {15e3, 30e3, 60e3, 120e3, 240e3};
@@ -42,18 +43,6 @@ static const int nr_ssb_table[48][3] = {
{93, 15, nr_ssb_type_A}, {94, 15, nr_ssb_type_A}, {96, 30, nr_ssb_type_C}};
void set_Lmax(NR_DL_FRAME_PARMS *fp) {
if (get_softmodem_params()->sl_mode == 2) {
int sl_NumSSB_WithinPeriod = 1; //TODO: Needs to be updated from RRC parameters
int sl_TimeOffsetSSB = 1; //TODO: Needs to be updated from RRC parameters
int sl_TimeInterval = 1; //TODO: Needs to be updated from RRC parameters
if ((sl_NumSSB_WithinPeriod == 4) && ((sl_TimeOffsetSSB % fp->slots_per_frame) + 3 * sl_TimeInterval < NR_NUMBER_OF_SUBFRAMES_PER_FRAME * 2))
fp->Lmax = 4;
else if ((sl_NumSSB_WithinPeriod == 2) && ((sl_TimeOffsetSSB % fp->slots_per_frame) + sl_TimeInterval < NR_NUMBER_OF_SUBFRAMES_PER_FRAME))
fp->Lmax = 2;
else
fp->Lmax = 1;
return;
}
// definition of Lmax according to ts 38.213 section 4.1
if (fp->dl_CarrierFreq < 6e9) {
if(fp->frame_type && (fp->ssb_type==2))
@@ -115,23 +104,27 @@ void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, int N_RB_DL)
case NR_MU_0: //15kHz scs
fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_0];
fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_0];
fp->ssb_type = nr_ssb_type_A;
while(nr_ssb_table[idx][0]!=fp->nr_band)
idx++;
AssertFatal(nr_ssb_table[idx][1]==15,"SCS %d not applicable to band %d\n",
fp->subcarrier_spacing,fp->nr_band);
if (fp->nr_band != 47) {
fp->ssb_type = nr_ssb_type_A;
while(nr_ssb_table[idx][0]!=fp->nr_band)
idx++;
AssertFatal(nr_ssb_table[idx][1]==15,"SCS %d not applicable to band %d\n",
fp->subcarrier_spacing,fp->nr_band);
}
break;
case NR_MU_1: //30kHz scs
fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_1];
fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_1];
while(nr_ssb_table[idx][0]!=fp->nr_band ||
nr_ssb_table[idx][1]!=30) {
AssertFatal(nr_ssb_table[idx][0]<=fp->nr_band,"SCS %d not applicable to band %d\n",
fp->subcarrier_spacing,fp->nr_band);
idx++;
if (fp->nr_band != 47) {
while(nr_ssb_table[idx][0]!=fp->nr_band ||
nr_ssb_table[idx][1]!=30) {
AssertFatal(nr_ssb_table[idx][0]<=fp->nr_band,"SCS %d not applicable to band %d\n",
fp->subcarrier_spacing,fp->nr_band);
idx++;
}
fp->ssb_type = nr_ssb_table[idx][2];
}
fp->ssb_type = nr_ssb_table[idx][2];
break;
case NR_MU_2: //60kHz scs
@@ -164,9 +157,6 @@ void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, int N_RB_DL)
fp->ofdm_symbol_size <<= 1;
fp->first_carrier_offset = fp->ofdm_symbol_size - (N_RB_DL * 12 / 2);
// TODO: Temporarily setting fp->first_carrier_offset = 0 for SL until MAC is developed
if (get_softmodem_params()->sl_mode == 2)
fp->first_carrier_offset = 0;
fp->nb_prefix_samples = fp->ofdm_symbol_size / 128 * 9;
fp->nb_prefix_samples0 = fp->ofdm_symbol_size / 128 * (9 + (1 << mu));
LOG_W(PHY,"Init: N_RB_DL %d, first_carrier_offset %d, nb_prefix_samples %d,nb_prefix_samples0 %d, ofdm_symbol_size %d\n",
@@ -299,11 +289,6 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
LOG_D(PHY,"dl_bw_kHz %lu\n",dl_bw_khz);
LOG_D(PHY,"dl_CarrierFreq %lu\n",fp->dl_CarrierFreq);
if (get_softmodem_params()->sl_mode == 2) {
uint64_t sl_bw_khz = (12 * config->carrier_config.sl_grid_size[config->ssb_config.scs_common]) * (15 << config->ssb_config.scs_common);
fp->sl_CarrierFreq = ((sl_bw_khz >> 1) + config->carrier_config.sl_frequency) * 1000;
}
uint64_t ul_bw_khz = (12*config->carrier_config.ul_grid_size[config->ssb_config.scs_common])*(15<<config->ssb_config.scs_common);
fp->ul_CarrierFreq = ((ul_bw_khz>>1) + config->carrier_config.uplink_frequency)*1000 ;
@@ -329,7 +314,7 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
AssertFatal(fp->numerology_index == NR_MU_2,"Invalid cyclic prefix %d for numerology index %d\n", Ncp, fp->numerology_index);
fp->Ncp = Ncp;
int N_RB = (get_softmodem_params()->sl_mode == 2) ? fp->N_RB_SL : fp->N_RB_DL;
int N_RB = fp->N_RB_DL;
set_scs_parameters(fp, fp->numerology_index, N_RB);
fp->slots_per_frame = 10* fp->slots_per_subframe;
@@ -354,10 +339,6 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
}
fp->ssb_start_subcarrier = (12 * config->ssb_table.ssb_offset_point_a + sco);
// TODO: Temporarily setting fp->ssb_start_subcarrier = 0 for SL until MAC is developed
if (get_softmodem_params()->sl_mode == 2) {
fp->ssb_start_subcarrier = 0;
}
set_Lmax(fp);
fp->L_ssb = (((uint64_t) config->ssb_table.ssb_mask_list[0].ssb_mask)<<32) | config->ssb_table.ssb_mask_list[1].ssb_mask;
@@ -407,12 +388,6 @@ void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink
}
void nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *frame_parms, uint64_t sidelink_frequency, uint16_t nr_band) {
LOG_D(NR_PHY, "SL init parameters. SL freq %lu\n", sidelink_frequency);
frame_parms->sl_CarrierFreq = sidelink_frequency;
frame_parms->nr_band = nr_band;
}
void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp)
{
LOG_I(PHY,"fp->scs=%d\n",fp->subcarrier_spacing);
@@ -426,7 +401,109 @@ void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp)
LOG_I(PHY,"fp->samples_per_frame=%d\n",fp->samples_per_frame);
LOG_I(PHY,"fp->dl_CarrierFreq=%lu\n",fp->dl_CarrierFreq);
LOG_I(PHY,"fp->ul_CarrierFreq=%lu\n",fp->ul_CarrierFreq);
LOG_I(PHY,"fp->Nid_cell=%d\n",fp->Nid_cell);
LOG_I(PHY,"fp->first_carrier_offset=%d\n",fp->first_carrier_offset);
LOG_I(PHY,"fp->ssb_start_subcarrier=%d\n",fp->ssb_start_subcarrier);
LOG_I(PHY,"fp->Ncp=%d\n",fp->Ncp);
LOG_I(PHY,"fp->N_RB_DL=%d\n",fp->N_RB_DL);
LOG_I(PHY,"fp->numerology_index=%d\n",fp->numerology_index);
LOG_I(PHY,"fp->nr_band=%d\n",fp->nr_band);
LOG_I(PHY,"fp->ofdm_offset_divisor=%d\n",fp->ofdm_offset_divisor);
LOG_I(PHY,"fp->threequarter_fs=%d\n",fp->threequarter_fs);
LOG_I(PHY,"fp->sl_CarrierFreq=%lu\n",fp->sl_CarrierFreq);
LOG_I(PHY,"fp->N_RB_SL=%d\n",fp->N_RB_SL);
}
int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp,
sl_nr_phy_config_request_t* config,
int threequarter_fs,
uint32_t ofdm_offset_divisor)
{
//Set also these parameters here instead of some where else.
fp->ofdm_offset_divisor = ofdm_offset_divisor;
fp->threequarter_fs = threequarter_fs;
fp->nr_band = get_band(config->sl_carrier_config.sl_frequency*1000, 0);
fp->att_rx = config->sl_carrier_config.sl_num_rx_ant;
fp->att_tx = config->sl_carrier_config.sl_num_tx_ant;
fp->nb_antennas_rx = fp->att_rx;
fp->nb_antennas_tx = fp->att_tx;
fp->numerology_index = config->sl_bwp_config.sl_scs;
fp->N_RB_SL = config->sl_carrier_config.sl_grid_size;
fp->N_RB_DL = fp->N_RB_SL;
fp->N_RB_UL = fp->N_RB_SL;
fp->Ncp = config->sl_bwp_config.sl_cyclic_prefix;
fp->frame_type = get_frame_type(fp->nr_band, fp->numerology_index);
int32_t uplink_frequency_offset = get_delta_duplex(fp->nr_band, fp->numerology_index);
uplink_frequency_offset *= 1000;
uint64_t bw_khz = (12*config->sl_carrier_config.sl_grid_size)*(15<<config->sl_bwp_config.sl_scs);
//REfer to section 3GPP spec 38.101 5.4E.2.1
//FrefV2x = Fref + deltashift + valueN*5Khz
uint32_t deltashift = (config->sl_carrier_config.sl_frequency_shift_7p5khz) ? 7500 : 0; //In Hz
deltashift += config->sl_carrier_config.sl_value_N * 5000; //In Hz
fp->sl_CarrierFreq = ((bw_khz >> 1) + config->sl_carrier_config.sl_frequency)*1000 ;
fp->sl_CarrierFreq += (deltashift >> 1);
fp->dl_CarrierFreq = fp->sl_CarrierFreq;
fp->ul_CarrierFreq = fp->dl_CarrierFreq + uplink_frequency_offset;
LOG_D(PHY,"bw_kHz %lu, deltashift:%d Hz\n",bw_khz,deltashift);
LOG_D(PHY,"CarrierFreq %lu Hz\n",fp->sl_CarrierFreq);
LOG_I(PHY, "Initializing frame parms: DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %d Hz\n",
fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, uplink_frequency_offset);
AssertFatal(fp->frame_type==TDD, "Sidelink bands only support TDD");
AssertFatal(fp->ul_CarrierFreq == (fp->dl_CarrierFreq + uplink_frequency_offset),
"Disagreement in uplink frequency for band %d: ul_CarrierFreq = %lu Hz vs expected %lu Hz\n",
fp->nr_band, fp->ul_CarrierFreq, fp->dl_CarrierFreq + uplink_frequency_offset);
LOG_I(PHY,"Initializing frame parms for mu %d, N_RB %d, Ncp %d\n",fp->numerology_index, fp->N_RB_DL, fp->Ncp);
if (fp->Ncp == EXTENDED)
AssertFatal(fp->numerology_index == NR_MU_2,"Invalid cyclic prefix %d for numerology index %d\n",
fp->Ncp, fp->numerology_index);
set_scs_parameters(fp, fp->numerology_index, fp->N_RB_SL);
fp->slots_per_frame = 10* fp->slots_per_subframe;
fp->symbols_per_slot = ((fp->Ncp == NORMAL)? 14 : 12); // to redefine for different slot formats
fp->samples_per_subframe_wCP = fp->ofdm_symbol_size * fp->symbols_per_slot * fp->slots_per_subframe;
fp->samples_per_frame_wCP = 10 * fp->samples_per_subframe_wCP;
fp->samples_per_slot_wCP = fp->symbols_per_slot*fp->ofdm_symbol_size;
fp->samples_per_slotN0 = (fp->nb_prefix_samples + fp->ofdm_symbol_size) * fp->symbols_per_slot;
fp->samples_per_slot0 = fp->nb_prefix_samples0 + ((fp->symbols_per_slot-1)*fp->nb_prefix_samples) + (fp->symbols_per_slot*fp->ofdm_symbol_size);
fp->samples_per_subframe = (fp->nb_prefix_samples0 + fp->ofdm_symbol_size) * 2 +
(fp->nb_prefix_samples + fp->ofdm_symbol_size) * (fp->symbols_per_slot * fp->slots_per_subframe - 2);
fp->get_samples_per_slot = &get_samples_per_slot;
fp->get_samples_slot_timestamp = &get_samples_slot_timestamp;
fp->samples_per_frame = 10 * fp->samples_per_subframe;
fp->freq_range = (fp->dl_CarrierFreq < 6e9)? nr_FR1 : nr_FR2;
//ssb_offset_pointa points to the first RE where Sidelink-PSBCH starts
fp->ssb_start_subcarrier = config->sl_bwp_config.sl_ssb_offset_point_a;
init_symbol_rotation(fp);
init_timeshift_rotation(fp);
//Not used for Sidelink
fp->Lmax = 0;
fp->L_ssb = 0;
fp->N_ssb = 0;
fp->half_frame_bit = 0;
fp->ssb_index = 0;
fp->ssb_type = 0;
//#ifdef SL_DEBUG
LOG_I(PHY, "Dumping Sidelink Frame Parameters\n");
nr_dump_frame_parms(fp);
//#endif
return 0;
}

View File

@@ -29,7 +29,10 @@ int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp,uint8_t i_ssb);
int nr_init_frame_parms(nfapi_nr_config_request_scf_t *config, NR_DL_FRAME_PARMS *frame_parms);
int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *frame_parms, fapi_nr_config_request_t *config, uint16_t nr_band);
void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink_frequency, int32_t uplink_frequency_offset, uint8_t mu, uint16_t nr_band);
void nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *frame_parms, uint64_t sidelink_frequency, uint16_t nr_band);
int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp,
sl_nr_phy_config_request_t* config,
int threequarter_fs,
uint32_t ofdm_offset_divisor);
int init_nr_ue_signal(PHY_VARS_NR_UE *ue,int nb_connected_eNB);
void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB);
void init_nr_ue_transport(PHY_VARS_NR_UE *ue);
@@ -56,5 +59,6 @@ void free_nr_ue_ul_harq(NR_UL_UE_HARQ_t harq_list[NR_MAX_ULSCH_HARQ_PROCESSES],
void phy_init_nr_top(PHY_VARS_NR_UE *ue);
void phy_term_nr_top(void);
void sl_ue_phy_init(PHY_VARS_NR_UE *UE);
#endif

View File

@@ -49,9 +49,17 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue,
int reset_freq_est);
int nr_slot_fep(PHY_VARS_NR_UE *ue,
NR_DL_FRAME_PARMS *frame_parms,
UE_nr_rxtx_proc_t *proc,
unsigned char symbol,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
c16_t rxdataF[][frame_parms->samples_per_slot_wCP],
uint32_t linktype);
int sl_nr_slot_fep(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
unsigned char symbol,
unsigned char Ns,
uint32_t sample_offset,
c16_t rxdataF[][ue->SL_UE_PHY_PARAMS.sl_frame_params.samples_per_slot_wCP]);
int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,

View File

@@ -601,7 +601,7 @@ void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) {
uint64_t dl_CarrierFreq = fp->dl_CarrierFreq;
uint64_t ul_CarrierFreq = fp->ul_CarrierFreq;
uint64_t sl_CarrierFreq = fp->sl_CarrierFreq;
double f[2] = {(double)dl_CarrierFreq, (double)ul_CarrierFreq};
double f[3] = {(double)dl_CarrierFreq, (double)ul_CarrierFreq, (double)sl_CarrierFreq};
const int nsymb = fp->symbols_per_slot * fp->slots_per_frame/10;
const double Tc=(1/480e3/4096);
@@ -609,15 +609,12 @@ void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) {
const double Ncp0=16*64 + (144*64*(1/(float)(1<<fp->numerology_index)));
const double Ncp1=(144*64*(1/(float)(1<<fp->numerology_index)));
for (uint8_t ll = 0; ll < 2; ll++){
for (uint8_t ll = 0; ll < 3; ll++){
double f0 = f[ll];
LOG_D(PHY, "Doing symbol rotation calculation for gNB TX/RX, f0 %f Hz, Nsymb %d\n", f0, nsymb);
if (f0 == 0) continue;
LOG_I(NR_PHY, "Doing symbol rotation calculation for gNB TX/RX, f0 %f Hz, Nsymb %d\n", f0, nsymb);
c16_t *symbol_rotation = fp->symbol_rotation[ll];
if (get_softmodem_params()->sl_mode == 2) {
f0 = (double)sl_CarrierFreq;
symbol_rotation = fp->symbol_rotation[link_type_sl];
}
double tl = 0.0;
double poff = 0.0;
@@ -634,12 +631,12 @@ void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) {
}
poff = 2 * M_PI * (tl + (Ncp * Tc)) * f0;
exp_re = cos(poff);
exp_im = sin(-poff);
exp_re = 1.0;//cos(poff);
exp_im = 0.0;//sin(-poff);
symbol_rotation[l].r = (int16_t)floor(exp_re * 32767);
symbol_rotation[l].i = (int16_t)floor(exp_im * 32767);
LOG_D(PHY, "Symbol rotation %d/%d => tl %f (%d,%d) (%f)\n",
LOG_I(PHY, "Symbol rotation %d/%d => tl %f (%d,%d) (%f)\n",
l,
nsymb,
tl,

View File

@@ -45,7 +45,6 @@ void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRA
{
PHY_ofdm_mod((int *)txdataF, // input
(int *)txdata, // output
frame_parms->ofdm_symbol_size,
@@ -67,6 +66,7 @@ void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRA
void nr_normal_prefix_mod(c16_t *txdataF, c16_t *txdata, uint8_t nsymb, const NR_DL_FRAME_PARMS *frame_parms, uint32_t slot)
{
// This function works only slot wise. For more generic symbol generation refer nr_feptx0()
LOG_D(NR_PHY,"normal_prefix_mod: prefix0 %d, prefix %d, nsymb %d\n",frame_parms->nb_prefix_samples0,frame_parms->nb_prefix_samples,nsymb);
if (frame_parms->numerology_index != 0) { // case where numerology != 0
if (!(slot%(frame_parms->slots_per_subframe/2))) {
PHY_ofdm_mod((int *)txdataF,

View File

@@ -131,7 +131,7 @@ int slot_fep(PHY_VARS_UE *ue,
// (frame_parms->ofdm_symbol_size+nb_prefix_samples)*(l-1);
#ifdef DEBUG_FEP
// if (ue->frame <100)
LOG_I(PHY,"slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d, frame_length_samples %d\n",
LOG_D(PHY,"slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d, frame_length_samples %d\n",
ue->proc.proc_rxtx[(Ns>>1)&1].frame_rx,Ns, symbol,
nb_prefix_samples,nb_prefix_samples0,slot_offset,subframe_offset,sample_offset,rx_offset,frame_length_samples);
#endif
@@ -206,7 +206,7 @@ int slot_fep(PHY_VARS_UE *ue,
}
#ifdef DEBUG_FEP
printf("slot_fep: done\n");
printf("slot_fep: Ns %d l %d, done\n",Ns,l);
#endif
return(0);
}
@@ -316,7 +316,7 @@ int front_end_fft(PHY_VARS_UE *ue,
// (frame_parms->ofdm_symbol_size+nb_prefix_samples)*(l-1);
#ifdef DEBUG_FEP
// if (ue->frame <100)
LOG_I(PHY,
LOG_D(PHY,
"slot_fep: frame %d: slot %d, threadId %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d, frame_length_samples %d\n",
ue->proc.proc_rxtx[threadId].frame_rx,Ns, threadId,symbol,
nb_prefix_samples,nb_prefix_samples0,slot_offset,subframe_offset,sample_offset,rx_offset,frame_length_samples);

View File

@@ -34,12 +34,107 @@
#define LOG_I(A,B...) printf(A)
#endif*/
int nr_slot_fep(PHY_VARS_NR_UE *ue,
int sl_nr_slot_fep(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
unsigned char symbol,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
unsigned char Ns,
uint32_t sample_offset,
c16_t rxdataF[][ue->SL_UE_PHY_PARAMS.sl_frame_params.samples_per_slot_wCP])
{
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
NR_DL_FRAME_PARMS *frame_params = &ue->SL_UE_PHY_PARAMS.sl_frame_params;
NR_UE_COMMON *common_vars = &ue->common_vars;
AssertFatal(symbol < frame_params->symbols_per_slot, "slot_fep: symbol must be between 0 and %d\n", frame_params->symbols_per_slot-1);
AssertFatal(Ns < frame_params->slots_per_frame, "slot_fep: Ns must be between 0 and %d\n", frame_params->slots_per_frame-1);
unsigned int nb_prefix_samples = frame_params->nb_prefix_samples;
unsigned int nb_prefix_samples0 = frame_params->nb_prefix_samples0;
dft_size_idx_t dftsize = get_dft(frame_params->ofdm_symbol_size);
// This is for misalignment issues
int32_t tmp_dft_in[8192] __attribute__ ((aligned (32)));
unsigned int rx_offset = frame_params->get_samples_slot_timestamp(Ns,frame_params,0);
unsigned int abs_symbol = Ns * frame_params->symbols_per_slot + symbol;
rx_offset += sample_offset;
rx_offset += ue->rx_offset;
for (int idx_symb = Ns*frame_params->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++)
rx_offset += (idx_symb%(0x7<<frame_params->numerology_index)) ? nb_prefix_samples : nb_prefix_samples0;
rx_offset += frame_params->ofdm_symbol_size * symbol;
// use OFDM symbol from within 1/8th of the CP to avoid ISI
rx_offset -= (nb_prefix_samples / frame_params->ofdm_offset_divisor);
#ifdef SL_DEBUG_SLOT_FEP
// if (ue->frame <100)
LOG_I(PHY, "slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, rx_offset %u\n",
Ns, symbol, nb_prefix_samples, nb_prefix_samples0, rx_offset);
#endif
for (unsigned char aa=0; aa<frame_params->nb_antennas_rx; aa++) {
memset(&rxdataF[aa][frame_params->ofdm_symbol_size*symbol],0,frame_params->ofdm_symbol_size*sizeof(int32_t));
int16_t *rxdata_ptr = (int16_t *)&common_vars->rxdata[aa][rx_offset];
// if input to dft is not 256-bit aligned
if ((rx_offset & 7) != 0) {
memcpy((void *)&tmp_dft_in[0],
(void *)&common_vars->rxdata[aa][rx_offset],
frame_params->ofdm_symbol_size * sizeof(int32_t));
rxdata_ptr = (int16_t *)tmp_dft_in;
}
dft(dftsize,
rxdata_ptr,
(int16_t *)&rxdataF[aa][frame_params->ofdm_symbol_size*symbol],
1);
int symb_offset = (Ns%frame_params->slots_per_subframe)*frame_params->symbols_per_slot;
int32_t rot2 = ((uint32_t*)frame_params->symbol_rotation[1])[symbol+symb_offset];
((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1];
#ifdef SL_DEBUG_SLOT_FEP
// if (ue->frame <100)
LOG_I(PHY, "slot_fep: slot %d, symbol %d rx_offset %u, rotation symbol %d %d.%d\n", Ns,symbol, rx_offset,
symbol+symb_offset,((int16_t*)&rot2)[0],((int16_t*)&rot2)[1]);
#endif
rotate_cpx_vector((c16_t *)&rxdataF[aa][frame_params->ofdm_symbol_size*symbol],
(c16_t *)&rot2,
(c16_t *)&rxdataF[aa][frame_params->ofdm_symbol_size*symbol],
frame_params->ofdm_symbol_size,
15);
int16_t *shift_rot = (int16_t *)frame_params->timeshift_symbol_rotation;
multadd_cpx_vector((int16_t *)&rxdataF[aa][frame_params->ofdm_symbol_size*symbol],
shift_rot,
(int16_t *)&rxdataF[aa][frame_params->ofdm_symbol_size*symbol],
1,
frame_params->ofdm_symbol_size,
15);
}
LOG_D(PHY, "SIDELINK RX: Slot FEP: done for symbol:%d\n", symbol);
return 0;
}
int nr_slot_fep(PHY_VARS_NR_UE *ue,
NR_DL_FRAME_PARMS *frame_parms,
UE_nr_rxtx_proc_t *proc,
unsigned char symbol,
c16_t rxdataF[][frame_parms->samples_per_slot_wCP],
uint32_t linktype)
{
NR_UE_COMMON *common_vars = &ue->common_vars;
int Ns = proc->nr_slot_rx;
@@ -67,13 +162,14 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
rx_offset += frame_parms->ofdm_symbol_size * symbol;
// use OFDM symbol from within 1/8th of the CP to avoid ISI
rx_offset -= (nb_prefix_samples / frame_parms->ofdm_offset_divisor);
// rx_offset -= (nb_prefix_samples / frame_parms->ofdm_offset_divisor);
rx_offset += 1;
//#ifdef DEBUG_FEP
#ifdef DEBUG_FEP
// if (ue->frame <100)
LOG_D(PHY,"slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, rx_offset %u energy %d\n",
LOG_I(PHY,"slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, rx_offset %u energy %d\n",
Ns, symbol, nb_prefix_samples, nb_prefix_samples0, rx_offset, dB_fixed(signal_energy((int32_t *)&common_vars->rxdata[0][rx_offset],frame_parms->ofdm_symbol_size)));
//#endif
#endif
for (unsigned char aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
int16_t *rxdata_ptr = (int16_t *)&common_vars->rxdata[aa][rx_offset];
@@ -96,18 +192,22 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
stop_meas(&ue->rx_dft_stats);
/*
LOG_I(NR_PHY,"%d.%d Applying rotation for symbol %d, linktype %d\n",
proc->frame_rx,proc->nr_slot_rx,symbol,linktype);
apply_nr_rotation_RX(frame_parms,
rxdataF[aa],
frame_parms->symbol_rotation[0],
frame_parms->symbol_rotation[linktype],
Ns,
frame_parms->N_RB_DL,
0,
symbol,
1);
linktype);
*/
}
#ifdef DEBUG_FEP
printf("slot_fep: done\n");
LOG_I(NR_PHY,"slot_fep: done for Ns %d symbol %d\n",Ns,symbol);
#endif
return 0;
@@ -297,7 +397,6 @@ void apply_nr_rotation_RX(NR_DL_FRAME_PARMS *frame_parms,
c16_t rot2 = rot[symbol + symb_offset];
rot2.i = -rot2.i;
LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n", slot, symb_offset, rot2.r, rot2.i);
c16_t *shift_rot = frame_parms->timeshift_symbol_rotation;
c16_t *this_symbol = &rxdataF[soffset + (frame_parms->ofdm_symbol_size * symbol)];

View File

@@ -220,7 +220,8 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB,int slot, int first_symb,int num_symb
//
// Todo:
// - averaging IIR filter for RX power and noise
void nr_gnb_measurements(PHY_VARS_gNB *gNB,
void nr_gnb_measurements(PHY_MEASUREMENTS_gNB *meas,
NR_DL_FRAME_PARMS *fp,
NR_gNB_ULSCH_t *ulsch,
NR_gNB_PUSCH *pusch_vars,
unsigned char symbol,
@@ -232,8 +233,6 @@ void nr_gnb_measurements(PHY_VARS_gNB *gNB,
double rx_gain = openair0_cfg[0].rx_gain[0];
double rx_gain_offset = openair0_cfg[0].rx_gain_offset[0];
PHY_MEASUREMENTS_gNB *meas = &gNB->measurements;
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
int ch_offset = fp->ofdm_symbol_size * symbol;
int N_RB_UL = ulsch->harq_process->ulsch_pdu.rb_size;
ulsch_measurements_gNB *ulsch_measurements = &ulsch->ulsch_measurements;

View File

@@ -25,6 +25,7 @@
#include "nr_ul_estimation.h"
#include "PHY/sse_intrin.h"
#include "PHY/NR_REFSIG/nr_refsig.h"
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
#include "PHY/NR_REFSIG/dmrs_nr.h"
#include "PHY/NR_REFSIG/ptrs_nr.h"
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
@@ -117,34 +118,39 @@ int get_delay_idx(int delay) {
}
int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
PHY_VARS_NR_UE *ue,
int rxFSz,
c16_t rxdataF[][rxFSz],
unsigned char Ns,
unsigned short p,
unsigned char symbol,
int ul_id,
unsigned short bwp_start_subcarrier,
nfapi_nr_pusch_pdu_t *pusch_pdu,
sl_nr_rx_config_pssch_sci_pdu_t *pssch_pdu,
int *max_ch,
uint32_t *nvar) {
c16_t pilot[3280] __attribute__((aligned(32)));
const int chest_freq = gNB->chest_freq;
const int chest_freq = gNB ? gNB->chest_freq : ue->chest_freq;
#ifdef DEBUG_CH
FILE *debug_ch_est;
debug_ch_est = fopen("debug_ch_est.txt","w");
#endif
//uint16_t Nid_cell = (eNB_offset == 0) ? gNB->frame_parms.Nid_cell : gNB->measurements.adj_cell_id[eNB_offset-1];
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ul_id];
NR_gNB_PUSCH *pusch_vars = gNB ? &gNB->pusch_vars[ul_id] : &ue->pssch_vars[ul_id];
c16_t **ul_ch_estimates = (c16_t **)pusch_vars->ul_ch_estimates;
const int symbolSize = gNB->frame_parms.ofdm_symbol_size;
const int soffset = (Ns&3)*gNB->frame_parms.symbols_per_slot*symbolSize;
const int symbolSize = gNB ? gNB->frame_parms.ofdm_symbol_size : ue->SL_UE_PHY_PARAMS.sl_frame_params.ofdm_symbol_size;
const int soffset = 0;//(Ns&3)*(gNB?gNB->frame_parms.symbols_per_slot:(ue->SL_UE_PHY_PARAMS.sl_frame_params.symbols_per_slot)*symbolSize);
const int nushift = (p>>1)&1;
gNB->frame_parms.nushift = nushift;
if (gNB) gNB->frame_parms.nushift = nushift;
else ue->SL_UE_PHY_PARAMS.sl_frame_params.nushift = nushift;
int ch_offset = symbolSize*symbol;
const int symbol_offset = symbolSize*symbol;
const int k0 = bwp_start_subcarrier;
const int nb_rb_pusch = pusch_pdu->rb_size;
const int nb_rb_pusch = gNB ? pusch_pdu->rb_size : pssch_pdu->subchannel_size*pssch_pdu->l_subch;
LOG_D(PHY, "In %s: ch_offset %d, soffset %d, symbol_offset %d, OFDM size %d, Ns = %d, k0 = %d, symbol %d\n",
__FUNCTION__,
@@ -157,14 +163,23 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
//------------------generate DMRS------------------//
if(pusch_pdu->ul_dmrs_scrambling_id != gNB->pusch_gold_init[pusch_pdu->scid]) {
if(gNB && pusch_pdu->ul_dmrs_scrambling_id != gNB->pusch_gold_init[pusch_pdu->scid]) {
gNB->pusch_gold_init[pusch_pdu->scid] = pusch_pdu->ul_dmrs_scrambling_id;
nr_gold_pusch(gNB, pusch_pdu->scid, pusch_pdu->ul_dmrs_scrambling_id);
}
if (pusch_pdu->transform_precoding == transformPrecoder_disabled) {
nr_pusch_dmrs_rx(gNB, Ns, gNB->nr_gold_pusch_dmrs[pusch_pdu->scid][Ns][symbol], (int32_t *)pilot, (1000+p), 0, nb_rb_pusch,
(pusch_pdu->bwp_start + pusch_pdu->rb_start)*NR_NB_SC_PER_RB, pusch_pdu->dmrs_config_type);
if (ue || pusch_pdu->transform_precoding == transformPrecoder_disabled) {
if (gNB) nr_pusch_dmrs_rx(NORMAL, Ns, gNB->nr_gold_pusch_dmrs[pusch_pdu->scid][Ns][symbol], (int32_t *)pilot, (1000+p), 0, nb_rb_pusch,
(pusch_pdu->bwp_start + pusch_pdu->rb_start)*NR_NB_SC_PER_RB, pusch_pdu->dmrs_config_type);
else {
// compute gold sequence based on Nid from SCI1A
int nb_re = ue->SL_UE_PHY_PARAMS.sl_frame_params.N_RB_UL*12;
uint32_t pssch_dmrs[(nb_re>>5)+1];
nr_init_pssch_dmrs_oneshot(&ue->SL_UE_PHY_PARAMS.sl_frame_params,pssch_pdu->Nid,pssch_dmrs,Ns,symbol);
// call nr_pusch_dmrs_rx`
nr_pusch_dmrs_rx(NORMAL, Ns, pssch_dmrs, (int32_t *)pilot, (1000+p), 0, nb_rb_pusch,
(pssch_pdu->startrb)*NR_NB_SC_PER_RB, 0);
}
} else { // if transform precoding or SC-FDMA is enabled in Uplink
// NR_SC_FDMA supports type1 DMRS so only 6 DMRS REs per RB possible
const uint16_t index = get_index_for_dmrs_lowpapr_seq(nb_rb_pusch * (NR_NB_SC_PER_RB/2));
@@ -176,7 +191,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
AssertFatal(dmrs_seq != NULL, "DMRS low PAPR seq not found, check if DMRS sequences are generated");
nr_pusch_lowpaprtype1_dmrs_rx(gNB, Ns, dmrs_seq, (int32_t *)pilot, 1000, 0, nb_rb_pusch, 0, pusch_pdu->dmrs_config_type);
#ifdef DEBUG_PUSCH
printf ("NR_UL_CHANNEL_EST: index %d, u %d,v %d\n", index, u, v);
LOG_I(NR_PHY,"NR_UL_CHANNEL_EST: index %d, u %d,v %d\n", index, u, v);
LOG_M("gNb_DMRS_SEQ.m","gNb_DMRS_SEQ", dmrs_seq,6*nb_rb_pusch,1,1);
#endif
}
@@ -194,22 +209,23 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
uint64_t noise_amp2 = 0;
c16_t ul_ls_est[symbolSize] __attribute__((aligned(32)));
memset(ul_ls_est, 0, sizeof(c16_t) * symbolSize);
NR_ULSCH_delay_t *delay = &gNB->ulsch[ul_id].delay;
NR_ULSCH_delay_t *delay = gNB ? &gNB->ulsch[ul_id].delay : &ue->slsch[ul_id].delay;
memset(delay, 0, sizeof(*delay));
for (int aarx=0; aarx<gNB->frame_parms.nb_antennas_rx; aarx++) {
c16_t *rxdataF = (c16_t *)&gNB->common_vars.rxdataF[aarx][symbol_offset];
c16_t *ul_ch = &ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset];
NR_DL_FRAME_PARMS *fp = gNB ? &gNB->frame_parms : &ue->SL_UE_PHY_PARAMS.sl_frame_params;
int nrx = fp->nb_antennas_rx;
for (int aarx=0; aarx<nrx; aarx++) {
c16_t *rxdataF2 = (c16_t *)&rxdataF[aarx][symbol_offset];
c16_t *ul_ch = &ul_ch_estimates[p*nrx+aarx][ch_offset];
memset(ul_ch,0,sizeof(*ul_ch)*symbolSize);
#ifdef DEBUG_PUSCH
LOG_I(PHY, "In %s symbol_offset %d, nushift %d\n", __FUNCTION__, symbol_offset, nushift);
LOG_I(PHY, "In %s ch est pilot, N_RB_UL %d\n", __FUNCTION__, gNB->frame_parms.N_RB_UL);
LOG_I(PHY, "In %s bwp_start_subcarrier %d, k0 %d, first_carrier %d, nb_rb_pusch %d\n", __FUNCTION__, bwp_start_subcarrier, k0, gNB->frame_parms.first_carrier_offset, nb_rb_pusch);
LOG_I(PHY, "In %s ch est pilot, N_RB_UL %d\n", __FUNCTION__, fp->N_RB_UL);
LOG_I(PHY, "In %s bwp_start_subcarrier %d, k0 %d, first_carrier %d, nb_rb_pusch %d\n", __FUNCTION__, bwp_start_subcarrier, k0, fp->first_carrier_offset, nb_rb_pusch);
LOG_I(PHY, "In %s ul_ch addr %p nushift %d\n", __FUNCTION__, ul_ch, nushift);
#endif
if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1 && chest_freq == 0) {
if ((ue || pusch_pdu->dmrs_config_type == pusch_dmrs_type1) && chest_freq == 0) {
c16_t *pil = pilot;
int re_offset = k0;
LOG_D(PHY,"PUSCH estimation DMRS type 1, Freq-domain interpolation");
@@ -224,7 +240,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
for (int k_line = 0; k_line <= 1; k_line++) {
re_offset = (k0 + (n << 2) + (k_line << 1) + delta) % symbolSize;
ch = c32x16maddShift(*pil, rxdataF[soffset + re_offset], ch, 16);
ch = c32x16maddShift(*pil, rxdataF2[soffset + re_offset], ch, 16);
pil++;
}
@@ -238,13 +254,13 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
freq2time(symbolSize, (int16_t *)ul_ls_est, (int16_t *)pusch_vars->ul_ch_estimates_time[aarx]);
nr_est_timing_advance_pusch(&gNB->frame_parms, pusch_vars->ul_ch_estimates_time[aarx], delay);
nr_est_timing_advance_pusch(fp, pusch_vars->ul_ch_estimates_time[aarx], delay);
int pusch_delay = delay->pusch_est_delay;
int delay_idx = get_delay_idx(pusch_delay);
c16_t *ul_delay_table = gNB->frame_parms.ul_delay_table[delay_idx];
c16_t *ul_delay_table = fp->ul_delay_table[delay_idx];
#ifdef DEBUG_PUSCH
printf("Estimated delay = %i\n", pusch_delay >> 1);
LOG_I(NR_PHY,"Estimated delay = %i\n", pusch_delay >> 1);
#endif
pilot_cnt = 0;
@@ -259,9 +275,9 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
#ifdef DEBUG_PUSCH
re_offset = (k0 + (n << 2) + (k_line << 1)) % symbolSize;
c16_t *rxF = &rxdataF[soffset + re_offset];
printf("pilot %4d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d)\n",
pilot_cnt, pil->r, pil->i, rxF->r, rxF->i, ch.r, ch.i);
c16_t *rxF = &rxdataF2[soffset + re_offset];
LOG_I(NR_PHY,"pilot %4d: ul_delay` -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d)\n",
pilot_cnt, ul_delay_table[k].r, ul_delay_table[k].i, rxF->r, rxF->i, ch16.r, ch16.i);
#endif
if (pilot_cnt == 0) {
@@ -283,9 +299,9 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
// Revert delay
pilot_cnt = 0;
ul_ch = &ul_ch_estimates[p * gNB->frame_parms.nb_antennas_rx + aarx][ch_offset];
ul_ch = &ul_ch_estimates[p * nrx + aarx][ch_offset];
int inv_delay_idx = get_delay_idx(-pusch_delay);
c16_t *ul_inv_delay_table = gNB->frame_parms.ul_delay_table[inv_delay_idx];
c16_t *ul_inv_delay_table = fp->ul_delay_table[inv_delay_idx];
for (int n = 0; n < 3 * nb_rb_pusch; n++) {
for (int k_line = 0; k_line <= 1; k_line++) {
int k = pilot_cnt << 1;
@@ -296,18 +312,18 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
#ifdef DEBUG_PUSCH
re_offset = (k0 + (n << 2) + (k_line << 1)) % symbolSize;
c16_t *rxF = &rxdataF[soffset + re_offset];
printf("ch -> (%4d,%4d), ch_inter -> (%4d,%4d)\n", ul_ls_est[k].r, ul_ls_est[k].i, ul_ch[k].r, ul_ch[k].i);
c16_t *rxF = &rxdataF2[soffset + re_offset];
LOG_I(NR_PHY,"ch -> (%4d,%4d), ch_inter -> (%4d,%4d)\n", ul_ls_est[k].r, ul_ls_est[k].i, ul_ch[k].r, ul_ch[k].i);
#endif
pilot_cnt++;
nest_count += 2;
}
}
} else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type2 && chest_freq == 0) { // pusch_dmrs_type2 |p_r,p_l,d,d,d,d,p_r,p_l,d,d,d,d|
} else if (gNB && pusch_pdu->dmrs_config_type == pusch_dmrs_type2 && chest_freq == 0) { // pusch_dmrs_type2 |p_r,p_l,d,d,d,d,p_r,p_l,d,d,d,d|
LOG_D(PHY, "PUSCH estimation DMRS type 2, Freq-domain interpolation\n");
c16_t *pil = pilot;
c16_t *rx = &rxdataF[soffset + nushift];
c16_t *rx = &rxdataF2[soffset + nushift];
for (int n = 0; n < nb_rb_pusch * NR_NB_SC_PER_RB; n += 6) {
c16_t ch0 = c16mulShift(*pil, rx[(k0 + n) % symbolSize], 15);
pil++;
@@ -334,9 +350,9 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
}
else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1) { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB
else if (ue || pusch_pdu->dmrs_config_type == pusch_dmrs_type1) { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB
LOG_D(PHY,"PUSCH estimation DMRS type 1, no Freq-domain interpolation\n");
c16_t *rxF = &rxdataF[soffset + nushift];
c16_t *rxF = &rxdataF2[soffset + nushift];
int pil_offset = 0;
int re_offset = k0;
c16_t ch;
@@ -398,23 +414,23 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
c32_t ch0={0};
//First PRB
ch0=c32x16mulShift(*pil,
rxdataF[soffset + nushift + re_offset],
rxdataF2[soffset + nushift + re_offset],
15);
pil++;
re_offset = (re_offset+1) % symbolSize;
ch0=c32x16maddShift(*pil,
rxdataF[nushift+re_offset],
rxdataF2[nushift+re_offset],
ch0,
15);
pil++;
re_offset = (re_offset+5) % symbolSize;
ch0=c32x16maddShift(*pil,
rxdataF[nushift+re_offset],
rxdataF2[nushift+re_offset],
ch0,
15);
re_offset = (re_offset+1) % symbolSize;
ch0=c32x16maddShift(*pil,
rxdataF[nushift+re_offset],
rxdataF2[nushift+re_offset],
ch0,
15);
pil++;
@@ -435,19 +451,19 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
for (int pilot_cnt=4; pilot_cnt<4*(nb_rb_pusch-1); pilot_cnt += 4) {
c32_t ch0;
ch0=c32x16mulShift(*pil, rxdataF[nushift+re_offset], 15);
ch0=c32x16mulShift(*pil, rxdataF2[nushift+re_offset], 15);
pil++;
re_offset = (re_offset+1) % symbolSize;
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
ch0=c32x16maddShift(*pil, rxdataF2[nushift+re_offset], ch0, 15);
pil++;
re_offset = (re_offset+5) % symbolSize;
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
ch0=c32x16maddShift(*pil, rxdataF2[nushift+re_offset], ch0, 15);
pil++;
re_offset = (re_offset+1) % symbolSize;
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
ch0=c32x16maddShift(*pil, rxdataF2[nushift+re_offset], ch0, 15);
pil++;
re_offset = (re_offset+5) % symbolSize;
@@ -470,19 +486,19 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
}
// Last PRB
ch0=c32x16mulShift(*pil, rxdataF[nushift+re_offset], 15);
ch0=c32x16mulShift(*pil, rxdataF2[nushift+re_offset], 15);
pil++;
re_offset = (re_offset+1) % symbolSize;
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
ch0=c32x16maddShift(*pil, rxdataF2[nushift+re_offset], ch0, 15);
pil++;
re_offset = (re_offset+5) % symbolSize;
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
ch0=c32x16maddShift(*pil, rxdataF2[nushift+re_offset], ch0, 15);
pil++;
re_offset = (re_offset+1) % symbolSize;
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
ch0=c32x16maddShift(*pil, rxdataF2[nushift+re_offset], ch0, 15);
pil++;
re_offset = (re_offset+5) % symbolSize;
@@ -500,12 +516,12 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
}
#ifdef DEBUG_PUSCH
ul_ch = &ul_ch_estimates[p * gNB->frame_parms.nb_antennas_rx + aarx][ch_offset];
ul_ch = &ul_ch_estimates[p * (gNB?gNB->frame_parms.nb_antennas_rx:ue->SL_UE_PHY_PARAMS.sl_frame_params.nb_antennas_rx) + aarx][ch_offset];
for (int idxP = 0; idxP < ceil((float)nb_rb_pusch * 12 / 8); idxP++) {
for (int idxI = 0; idxI < 8; idxI++) {
printf("%d\t%d\t", ul_ch[idxP * 8 + idxI].r, ul_ch[idxP * 8 + idxI].i);
LOG_I(NR_PHY,"%d\t%d\t", ul_ch[idxP * 8 + idxI].r, ul_ch[idxP * 8 + idxI].i);
}
printf("%d\n", idxP);
LOG_I(NR_PHY,"%d\n", idxP);
}
#endif
@@ -545,28 +561,33 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
* 3) Compensated DMRS based estimated signal with PTRS estimation for slot
*********************************************************************/
void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
struct PHY_VARS_NR_UE_s *ue,
NR_DL_FRAME_PARMS *frame_parms,
nfapi_nr_pusch_pdu_t *rel15_ul,
sl_nr_rx_config_pssch_sci_pdu_t *pssch_pdu,
uint8_t ulsch_id,
uint8_t nr_tti_rx,
unsigned char symbol,
uint32_t nb_re_pusch)
{
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id];
NR_gNB_PUSCH *pusch_vars = gNB ? &gNB->pusch_vars[ulsch_id] : &ue->pssch_vars[ulsch_id];
//#define DEBUG_UL_PTRS 1
int32_t *ptrs_re_symbol = NULL;
int8_t ret = 0;
uint8_t symbInSlot = rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols;
uint8_t *startSymbIndex = &rel15_ul->start_symbol_index;
uint8_t *nbSymb = &rel15_ul->nr_of_symbols;
uint8_t *L_ptrs = &rel15_ul->pusch_ptrs.ptrs_time_density;
uint8_t *K_ptrs = &rel15_ul->pusch_ptrs.ptrs_freq_density;
uint16_t *dmrsSymbPos = &rel15_ul->ul_dmrs_symb_pos;
uint8_t symbInSlot = gNB ? (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols) : (1 + pssch_pdu->pssch_numsym);
uint8_t sl_startSymbIndex = 1;
uint8_t *startSymbIndex = gNB ? &rel15_ul->start_symbol_index : &sl_startSymbIndex;
uint8_t *nbSymb = gNB ? &rel15_ul->nr_of_symbols : &pssch_pdu->pssch_numsym;
uint8_t *L_ptrs = gNB ? &rel15_ul->pusch_ptrs.ptrs_time_density : NULL;
uint8_t *K_ptrs = gNB ? &rel15_ul->pusch_ptrs.ptrs_freq_density:NULL;
uint16_t *dmrsSymbPos = gNB ? &rel15_ul->ul_dmrs_symb_pos : &pssch_pdu->dmrs_symbol_position;
uint16_t *ptrsSymbPos = &pusch_vars->ptrs_symbols;
uint8_t *ptrsSymbIdx = &pusch_vars->ptrs_symbol_index;
uint8_t *dmrsConfigType = &rel15_ul->dmrs_config_type;
uint16_t *nb_rb = &rel15_ul->rb_size;
uint8_t *ptrsReOffset = &rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset;
uint8_t sl_dmrsConfigType = 0;
uint8_t *dmrsConfigType = gNB ? &rel15_ul->dmrs_config_type : &sl_dmrsConfigType;
uint16_t sl_nb_rb = pssch_pdu->num_subch * pssch_pdu->subchannel_size;
uint16_t *nb_rb = gNB ? &rel15_ul->rb_size : &sl_nb_rb;
uint8_t *ptrsReOffset = gNB ? &rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset : NULL;
/* loop over antennas */
for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {

View File

@@ -24,6 +24,7 @@
#include "PHY/defs_gNB.h"
#include "PHY/defs_nr_UE.h"
/** @addtogroup _PHY_PARAMETER_ESTIMATION_BLOCKS_
* @{
*/
@@ -41,12 +42,16 @@
*/
int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
PHY_VARS_NR_UE *ue,
int rxFSz,
c16_t rxdataF[][rxFSz],
unsigned char Ns,
unsigned short p,
unsigned char symbol,
int ul_id,
unsigned short bwp_start_subcarrier,
nfapi_nr_pusch_pdu_t *pusch_pdu,
sl_nr_rx_config_pssch_sci_pdu_t *pssch_pdu,
int *max_ch,
uint32_t *nvar);
@@ -54,7 +59,8 @@ void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB);
void gNB_I0_measurements(PHY_VARS_gNB *gNB,int slot,int first_symb,int num_symb);
void nr_gnb_measurements(PHY_VARS_gNB *gNB,
void nr_gnb_measurements(PHY_MEASUREMENTS_gNB *meas,
NR_DL_FRAME_PARMS *fp,
NR_gNB_ULSCH_t *ulsch,
NR_gNB_PUSCH *pusch_vars,
unsigned char symbol,
@@ -68,8 +74,10 @@ int nr_est_timing_advance_srs(const NR_DL_FRAME_PARMS *frame_parms,
const int32_t srs_estimated_channel_time[][frame_parms->ofdm_symbol_size]);
void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
struct PHY_VARS_NR_UE_s *ue,
NR_DL_FRAME_PARMS *frame_parms,
nfapi_nr_pusch_pdu_t *rel15_ul,
sl_nr_rx_config_pssch_sci_pdu_t *pssch_pdu,
uint8_t ulsch_id,
uint8_t nr_tti_rx,
unsigned char symbol,

View File

@@ -63,7 +63,7 @@ int nr_pusch_dmrs_delta(uint8_t dmrs_config_type, unsigned short p) {
}
}
int nr_pusch_dmrs_rx(PHY_VARS_gNB *gNB,
int nr_pusch_dmrs_rx(int Ncp,
unsigned int Ns,
unsigned int *nr_gold_pusch,
int32_t *output,
@@ -86,7 +86,7 @@ int nr_pusch_dmrs_rx(PHY_VARS_gNB *gNB,
LOG_E(PHY,"PUSCH DMRS config type %d not valid\n", dmrs_type+1);
if ((p>=1000) && (p<((dmrs_type==pusch_dmrs_type1) ? 1008 : 1012))) {
if (gNB->frame_parms.Ncp == NORMAL) {
if (Ncp == NORMAL) {
nb_dmrs = ((dmrs_type==pusch_dmrs_type1) ? 6:4);
for (int i=dmrs_offset; i<dmrs_offset+(nb_pusch_rb*nb_dmrs); i++) {
k = i-dmrs_offset;
@@ -197,22 +197,30 @@ int nr_pdcch_dmrs_rx(PHY_VARS_NR_UE *ue,
int nr_pbch_dmrs_rx(int symbol,
unsigned int *nr_gold_pbch,
int32_t *output)
int32_t *output,
bool sidelink)
{
int m,m0,m1;
uint8_t idx=0;
AssertFatal(symbol>=0 && symbol <3,"illegal symbol %d\n",symbol);
if (symbol == 0) {
m0=0;
m1=60;
}
else if (symbol == 1) {
m0=60;
m1=84;
}
else {
m0=84;
m1=144;
if (sidelink) {
AssertFatal(symbol== 0 || (symbol>=5 && symbol <=12),"illegal symbol %d\n",symbol);
m0 = (symbol) ? (symbol - 4) * 33 : 0;
m1 = (symbol) ? (symbol - 3) * 33 : 33;
} else {
AssertFatal(symbol>=0 && symbol <3,"illegal symbol %d\n",symbol);
if (symbol == 0) {
m0=0;
m1=60;
}
else if (symbol == 1) {
m0=60;
m1=84;
}
else {
m0=84;
m1=144;
}
}
// printf("Generating pilots symbol %d, m0 %d, m1 %d\n",symbol,m0,m1);
/// QPSK modulation

View File

@@ -53,12 +53,10 @@ void nr_init_pbch_dmrs(PHY_VARS_gNB* gNB)
}
void nr_init_pdcch_dmrs(PHY_VARS_gNB* gNB, uint32_t Nid)
void nr_init_pdcch_dmrs(NR_DL_FRAME_PARMS *fp, uint32_t ***pdcch_dmrs, uint32_t Nid)
{
uint32_t x1 = 0, x2 = 0;
uint8_t reset;
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
uint32_t ***pdcch_dmrs = gNB->nr_gold_pdcch_dmrs;
int pdcch_dmrs_init_length = (((fp->N_RB_DL<<1)*3)>>5)+1;
for (uint8_t slot=0; slot<fp->slots_per_frame; slot++) {

View File

@@ -51,21 +51,20 @@ void nr_gold_pbch(PHY_VARS_NR_UE* ue)
}
void nr_gold_pdcch(PHY_VARS_NR_UE* ue,
unsigned short nid)
void nr_gold_pdcch(NR_DL_FRAME_PARMS *fp, uint32_t ***nr_gold,uint16_t nid)
{
unsigned int n = 0, x1 = 0, x2 = 0, x2tmp0 = 0;
uint8_t reset;
int pdcch_dmrs_init_length = (((ue->frame_parms.N_RB_DL << 1) * 3) >> 5) + 1;
int pdcch_dmrs_init_length = (((fp->N_RB_DL << 1) * 3) >> 5) + 1;
for (int ns = 0; ns < ue->frame_parms.slots_per_frame; ns++) {
for (int l = 0; l < ue->frame_parms.symbols_per_slot; l++) {
for (int ns = 0; ns < fp->slots_per_frame; ns++) {
for (int l = 0; l < fp->symbols_per_slot; l++) {
reset = 1;
x2tmp0 = ((ue->frame_parms.symbols_per_slot * ns + l + 1) * ((nid << 1) + 1));
x2tmp0 = ((fp->symbols_per_slot * ns + l + 1) * ((nid << 1) + 1));
x2tmp0 <<= 17;
x2 = (x2tmp0 + (nid << 1)) % (1U << 31); //cinit
for (n=0; n<pdcch_dmrs_init_length; n++) {
ue->nr_gold_pdcch[0][ns][l][n] = lte_gold_generic(&x1, &x2, reset);
nr_gold[ns][l][n] = lte_gold_generic(&x1, &x2, reset);
reset = 0;
}
}
@@ -118,6 +117,24 @@ void nr_init_pusch_dmrs(PHY_VARS_NR_UE* ue,
}
}
void nr_init_pssch_dmrs_oneshot(NR_DL_FRAME_PARMS *fp,
uint16_t N_id,
uint32_t *pssch_dmrs,
int slot,
int symb)
{
uint32_t x1 = 0, x2 = 0, n = 0;
int pusch_dmrs_init_length = ((fp->N_RB_UL * 12) >> 5) + 1;
int reset = 1;
x2 = ((1U << 17) * (fp->symbols_per_slot*slot + symb + 1) * ((N_id << 1) + 1) + (N_id << 1) );
LOG_D(PHY,"DMRS slot %d, symb %d x2 %x\n", slot, symb, x2);
for (n=0; n<pusch_dmrs_init_length; n++) {
pssch_dmrs[n] = lte_gold_generic(&x1, &x2, reset);
reset = 0;
}
}
void init_nr_gold_prs(PHY_VARS_NR_UE* ue)
{
unsigned int x1 = 0, x2 = 0;

View File

@@ -43,7 +43,7 @@ void nr_init_prs(PHY_VARS_gNB* gNB);
@param PHY_VARS_gNB* gNB structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables
@param Nid is used for the initialization of x2, Physical cell Id by default or upper layer configured pdcch_scrambling_ID
*/
void nr_init_pdcch_dmrs(PHY_VARS_gNB* gNB, uint32_t Nid);
void nr_init_pdcch_dmrs(NR_DL_FRAME_PARMS *fp,uint32_t ***pdcch_dmrs, uint32_t Nid);
void nr_init_pdsch_dmrs(PHY_VARS_gNB* gNB, uint8_t nscid, uint32_t Nid);
void nr_init_csi_rs(const NR_DL_FRAME_PARMS *fp, uint32_t ***csi_rs, uint32_t Nid);
@@ -51,7 +51,7 @@ void nr_gold_pusch(PHY_VARS_gNB* gNB, int nscid, uint32_t nid);
int nr_pusch_dmrs_delta(uint8_t dmrs_config_type, unsigned short p);
int nr_pusch_dmrs_rx(PHY_VARS_gNB *gNB,
int nr_pusch_dmrs_rx(int Ncp,
unsigned int Ns,
unsigned int *nr_gold_pusch,
int32_t *output,

View File

@@ -27,13 +27,32 @@
#include "PHY/defs_nr_UE.h"
#include "PHY/LTE_REFSIG/lte_refsig.h"
typedef struct port_freq_indices {
uint8_t p;
uint16_t k;
} port_freq_indices_t;
typedef struct csi_rs_params {
uint8_t size;
uint8_t j[16];
uint8_t k_n[6];
uint8_t kprime;
uint8_t lprime;
uint8_t ports;
uint8_t koverline[16];
uint8_t loverline[16];
double rho;
double alpha;
uint8_t gs;
} csi_rs_params_t;
/*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PBCH DMRS.
@param PHY_VARS_NR_UE* ue structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables
*/
int nr_pbch_dmrs_rx(int dmrss,
unsigned int *nr_gold_pbch,
int32_t *output);
int32_t *output,
bool sidelink);
/*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PDCCH DMRS.
@param PHY_VARS_NR_UE* ue structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables
@@ -56,8 +75,8 @@ int nr_pdsch_dmrs_rx(PHY_VARS_NR_UE *ue,
void nr_gold_pbch(PHY_VARS_NR_UE* ue);
void nr_gold_pdcch(PHY_VARS_NR_UE* ue,
unsigned short n_idDMRS);
void nr_gold_pdcch(NR_DL_FRAME_PARMS *fp,
uint32_t ***nr_gold, uint16_t nid);
void nr_gold_pdsch(PHY_VARS_NR_UE* ue,
int nscid,
@@ -67,7 +86,21 @@ void nr_init_pusch_dmrs(PHY_VARS_NR_UE* ue,
uint16_t N_n_scid,
uint8_t n_scid);
void nr_init_pssch_dmrs_oneshot(NR_DL_FRAME_PARMS *fp,
uint16_t N_id,
uint32_t *pssch_dmrs,
int slot,
int symb);
void nr_init_csi_rs(const NR_DL_FRAME_PARMS *fp, uint32_t ***csi_rs, uint32_t Nid);
void init_nr_gold_prs(PHY_VARS_NR_UE* ue);
void get_csi_rs_freq_ind_sl(const NR_DL_FRAME_PARMS* frame_parms,
uint16_t n,
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t* csi_params,
csi_rs_params_t* table_params,
port_freq_indices_t* port_freq_indices);
void get_csi_rs_params_from_table(const nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params,
csi_rs_params_t* table_params);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -30,7 +30,7 @@
* \warning
*/
#include "PHY/defs_nr_UE.h"
#include "nr_dci.h"
#include "nr_dlsch.h"
#include "nr_sch_dmrs.h"
@@ -45,12 +45,13 @@ void nr_pdcch_scrambling(uint32_t *in,
uint32_t size,
uint32_t Nid,
uint32_t scrambling_RNTI,
uint32_t *out) {
uint32_t *out,
int sci_flag) {
uint8_t reset;
uint32_t x1 = 0, x2 = 0, s = 0;
reset = 1;
x2 = (scrambling_RNTI<<16) + Nid;
LOG_D(PHY,"PDCCH Scrambling x2 %x : scrambling_RNTI %x \n", x2, scrambling_RNTI);
if (sci_flag==0) x2 = (scrambling_RNTI<<16) + Nid;
else x2 = (Nid<<15) + 1010;
for (int i=0; i<size; i++) {
if ((i&0x1f)==0) {
s = lte_gold_generic(&x1, &x2, reset);
@@ -66,28 +67,36 @@ void nr_pdcch_scrambling(uint32_t *in,
}
}
void nr_generate_dci(PHY_VARS_gNB *gNB,
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
int32_t *txdataF,
int16_t amp,
NR_DL_FRAME_PARMS *frame_parms,
int slot) {
uint32_t nr_generate_dci(PHY_VARS_gNB *gNB, PHY_VARS_NR_UE *ue,
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
int32_t *txdataF,
int16_t amp,
NR_DL_FRAME_PARMS *frame_parms,
int slot) {
uint16_t cset_start_sc;
uint8_t cset_start_symb, cset_nsymb;
int k,l,k_prime,dci_idx, dmrs_idx;
AssertFatal((gNB&&(!ue)) || (ue&&(!gNB)),"This should be either for gNB (%p) or UE (%p)\n",gNB,ue);
// fill reg list per symbol
int reg_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL * NR_NB_REG_PER_CCE];
nr_fill_reg_list(reg_list, pdcch_pdu_rel15);
if (gNB) nr_fill_reg_list(reg_list, pdcch_pdu_rel15);
// compute rb_offset and n_prb based on frequency allocation
int rb_offset;
int n_rb;
get_coreset_rballoc(pdcch_pdu_rel15->FreqDomainResource,&n_rb,&rb_offset);
if (gNB) get_coreset_rballoc(pdcch_pdu_rel15->FreqDomainResource,&n_rb,&rb_offset);
else {
rb_offset=pdcch_pdu_rel15->FreqDomainResource[0];
n_rb = pdcch_pdu_rel15->FreqDomainResource[1];
}
cset_start_sc = frame_parms->first_carrier_offset + (pdcch_pdu_rel15->BWPStart + rb_offset) * NR_NB_SC_PER_RB;
int16_t mod_dmrs[pdcch_pdu_rel15->StartSymbolIndex+pdcch_pdu_rel15->DurationSymbols][(((n_rb+rb_offset+pdcch_pdu_rel15->BWPStart)*6+15)>>4)<<4] __attribute__((aligned(16))); // 3 for the max coreset duration
uint32_t tcrc[pdcch_pdu_rel15->numDlDci];
for (int d=0;d<pdcch_pdu_rel15->numDlDci;d++) {
/*The coreset is initialised
* in frequency: the first subcarrier is obtained by adding the first CRB overlapping the SSB and the rb_offset for coreset 0
@@ -95,21 +104,22 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
* in time: by its first slot and its first symbol*/
const nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[d];
if(dci_pdu->ScramblingId != gNB->pdcch_gold_init) {
if(gNB && dci_pdu->ScramblingId != gNB->pdcch_gold_init) {
gNB->pdcch_gold_init = dci_pdu->ScramblingId;
nr_init_pdcch_dmrs(gNB, dci_pdu->ScramblingId);
nr_init_pdcch_dmrs(&gNB->frame_parms,gNB->nr_gold_pdcch_dmrs, dci_pdu->ScramblingId);
}
uint32_t **gold_pdcch_dmrs = gNB->nr_gold_pdcch_dmrs[slot];
uint32_t **gold_pdcch_dmrs=NULL;
if (gNB) gold_pdcch_dmrs= gNB->nr_gold_pdcch_dmrs[slot];
else if (ue) gold_pdcch_dmrs = ue->nr_gold_pscch_dmrs[slot];
cset_start_symb = pdcch_pdu_rel15->StartSymbolIndex;
cset_nsymb = pdcch_pdu_rel15->DurationSymbols;
dci_idx = 0;
LOG_D(PHY, "pdcch: Coreset rb_offset %d, nb_rb %d BWP Start %d\n",rb_offset,n_rb,pdcch_pdu_rel15->BWPStart);
LOG_D(PHY, "pdcch: Coreset starting subcarrier %d on symbol %d (%d symbols)\n", cset_start_sc, cset_start_symb, cset_nsymb);
LOG_D(NR_PHY, "pdcch: Coreset rb_offset %d, nb_rb %d BWP Start %d\n",rb_offset,n_rb,pdcch_pdu_rel15->BWPStart);
LOG_D(NR_PHY, "pdcch: Coreset starting subcarrier %d on symbol %d (%d symbols)\n", cset_start_sc, cset_start_symb, cset_nsymb);
// DMRS length is per OFDM symbol
uint32_t dmrs_length = (n_rb+pdcch_pdu_rel15->BWPStart)*6; //2(QPSK)*3(per RB)*6(REG per CCE)
uint32_t encoded_length = dci_pdu->AggregationLevel*108; //2(QPSK)*9(per RB)*6(REG per CCE)
uint32_t encoded_length = gNB ? dci_pdu->AggregationLevel*108:dci_pdu->AggregationLevel*18; //2(QPSK)*9(per RB)*6(REG per CCE)
if (dci_pdu->RNTI != 0xFFFF)
LOG_D(PHY, "DL_DCI : rb_offset %d, nb_rb %d, DMRS length per symbol %d\t DCI encoded length %d (precoder_granularity %d, reg_mapping %d), Scrambling_Id %d, ScramblingRNTI %x, PayloadSizeBits %d\n",
rb_offset, n_rb,dmrs_length, encoded_length,pdcch_pdu_rel15->precoderGranularity,pdcch_pdu_rel15->CceRegMappingType,
@@ -137,9 +147,9 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
uint16_t n_RNTI = dci_pdu->RNTI;
uint16_t Nid = dci_pdu->ScramblingId;
uint16_t scrambling_RNTI = dci_pdu->ScramblingRNTI;
polar_encoder_fast((uint64_t*)dci_pdu->Payload, (void*)encoder_output, n_RNTI, 1,
NR_POLAR_DCI_MESSAGE_TYPE, dci_pdu->PayloadSizeBits, dci_pdu->AggregationLevel);
polar_encoder_fast((uint64_t*)dci_pdu->Payload, (void*)encoder_output, &tcrc[d],n_RNTI, 1,
gNB ? NR_POLAR_DCI_MESSAGE_TYPE : NR_POLAR_SCI_MESSAGE_TYPE,
dci_pdu->PayloadSizeBits, dci_pdu->AggregationLevel);
#ifdef DEBUG_CHANNEL_CODING
//debug dump dci
printf("polar rnti %x,length %d, L %d\n",n_RNTI, dci_pdu->PayloadSizeBits,pdcch_pdu_rel15->dci_pdu->AggregationLevel);
@@ -154,15 +164,15 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
#endif
/// Scrambling
uint32_t scrambled_output[NR_MAX_DCI_SIZE_DWORD]= {0};
nr_pdcch_scrambling(encoder_output, encoded_length, Nid, scrambling_RNTI, scrambled_output);
nr_pdcch_scrambling(encoder_output, encoded_length, Nid, scrambling_RNTI, scrambled_output,0);
#ifdef DEBUG_CHANNEL_CODING
printf("scrambled output: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\t [4]->0x%08x\t [5]->0x%08x\t \
printf("scrambled output: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\t [4]->0x%08x\t [5]->0x%08x\n \
[6]->0x%08x \t [7]->0x%08x \t [8]->0x%08x \t [9]->0x%08x\t [10]->0x%08x\t [11]->0x%08x\n",
scrambled_output[0], scrambled_output[1], scrambled_output[2], scrambled_output[3], scrambled_output[4],scrambled_output[5],
scrambled_output[6], scrambled_output[7], scrambled_output[8], scrambled_output[9], scrambled_output[10],scrambled_output[11] );
#endif
/// QPSK modulation
int16_t mod_dci[NR_MAX_DCI_SIZE>>1] __attribute__((aligned(16)));
int16_t mod_dci[encoded_length] __attribute__((aligned(16)));
nr_modulation(scrambled_output, encoded_length, DMRS_MOD_ORDER, mod_dci); //Qm = 2 as DMRS is QPSK modulated
#ifdef DEBUG_DCI
@@ -176,23 +186,26 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
if (cset_start_sc >= frame_parms->ofdm_symbol_size)
cset_start_sc -= frame_parms->ofdm_symbol_size;
int num_regs = dci_pdu->AggregationLevel * NR_NB_REG_PER_CCE / pdcch_pdu_rel15->DurationSymbols;
int num_regs = gNB ? dci_pdu->AggregationLevel * NR_NB_REG_PER_CCE / pdcch_pdu_rel15->DurationSymbols : dci_pdu->AggregationLevel/pdcch_pdu_rel15->DurationSymbols;
/*Mapping the encoded DCI along with the DMRS */
for(int symbol_idx = 0; symbol_idx < pdcch_pdu_rel15->DurationSymbols; symbol_idx++) {
// allocating rbs per symbol
for (int reg_count = 0; reg_count < num_regs; reg_count++) {
k = cset_start_sc + reg_list[d][reg_count] * NR_NB_SC_PER_RB;
LOG_D(PHY, "REG %d k %d\n", reg_list[d][reg_count], k);
if (gNB) {
k = cset_start_sc + reg_list[d][reg_count] * NR_NB_SC_PER_RB;
LOG_D(PHY, "REG %d k %d\n", reg_list[d][reg_count], k);
}
else if (reg_count ==0) k=cset_start_sc+pdcch_pdu_rel15->dci_pdu[d].CceIndex * NR_NB_SC_PER_RB;
if (k >= frame_parms->ofdm_symbol_size)
k -= frame_parms->ofdm_symbol_size;
l = cset_start_symb + symbol_idx;
// dmrs index depends on reference point for k according to 38.211 7.4.1.3.2
if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG)
dmrs_idx = (reg_list[d][reg_count] + pdcch_pdu_rel15->BWPStart) * 3;
dmrs_idx = (gNB ? reg_list[d][reg_count] + pdcch_pdu_rel15->BWPStart : reg_count) * 3;
else
dmrs_idx = (reg_list[d][reg_count] + rb_offset) * 3;
dmrs_idx = gNB ? ((reg_list[d][reg_count] + rb_offset) * 3) : (pdcch_pdu_rel15->dci_pdu[d].CceIndex + rb_offset + reg_count) * 3;
k_prime = 0;
@@ -237,11 +250,12 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
} // reg_count
} // symbol_idx
LOG_D(PHY,
LOG_D(NR_PHY,
"DCI: payloadSize = %d | payload = %llx\n",
dci_pdu->PayloadSizeBits,
*(unsigned long long *)dci_pdu->Payload);
} // for (int d=0;d<pdcch_pdu_rel15->numDlDci;d++)
return(tcrc[0]); // this is for SCI, it should be passed in another way after so we can get more than 1
}
void nr_generate_dci_top(processingData_L1tx_t *msgTx,
@@ -251,9 +265,9 @@ void nr_generate_dci_top(processingData_L1tx_t *msgTx,
NR_DL_FRAME_PARMS *frame_parms) {
for (int i=0; i<msgTx->num_ul_pdcch; i++)
nr_generate_dci(msgTx->gNB,&msgTx->ul_pdcch_pdu[i].pdcch_pdu.pdcch_pdu_rel15,txdataF,amp,frame_parms,slot);
nr_generate_dci(msgTx->gNB,NULL,&msgTx->ul_pdcch_pdu[i].pdcch_pdu.pdcch_pdu_rel15,txdataF,amp,frame_parms,slot);
for (int i=0; i<msgTx->num_dl_pdcch; i++)
nr_generate_dci(msgTx->gNB,&msgTx->pdcch_pdu[i].pdcch_pdu_rel15,txdataF,amp,frame_parms,slot);
nr_generate_dci(msgTx->gNB,NULL,&msgTx->pdcch_pdu[i].pdcch_pdu_rel15,txdataF,amp,frame_parms,slot);
}

View File

@@ -39,7 +39,8 @@ void nr_pdcch_scrambling(uint32_t *in,
uint32_t size,
uint32_t Nid,
uint32_t n_RNTI,
uint32_t *out);
uint32_t *out,
int sci_flag);
int16_t find_nr_pdcch(int frame,int slot, PHY_VARS_gNB *gNB,find_type_t type);

View File

@@ -302,7 +302,7 @@ int nr_generate_pbch(nfapi_nr_dl_tti_ssb_pdu *ssb_pdu,
a_reversed |= (((uint64_t)pbch->pbch_a_prime>>i)&1)<<(31-i);
/// CRC, coding and rate matching
polar_encoder_fast (&a_reversed, (void*)pbch->pbch_e, 0, 0,
polar_encoder_fast (&a_reversed, (void*)pbch->pbch_e, NULL,0, 0,
NR_POLAR_PBCH_MESSAGE_TYPE, NR_POLAR_PBCH_PAYLOAD_BITS, NR_POLAR_PBCH_AGGREGATION_LEVEL);
#ifdef DEBUG_PBCH_ENCODING

View File

@@ -40,6 +40,18 @@ uint32_t nr_get_G(uint16_t nb_rb, uint16_t nb_symb_sch,uint8_t nb_re_dmrs,uint16
return(G);
}
uint32_t nr_get_G_SL(uint16_t nb_rb, uint16_t nb_symb_sch, uint8_t nb_re_dmrs, uint16_t length_dmrs, uint8_t sci1_dmrs_overlap, uint16_t sci1_re, uint16_t sci1_rb, uint16_t sci2_re, uint16_t csi_rs_re, uint8_t Qm, uint8_t Nl) {
uint32_t G_SL, slsch_re;
slsch_re = ((NR_NB_SC_PER_RB*nb_symb_sch) - (nb_re_dmrs*length_dmrs)) * nb_rb;
if (sci1_dmrs_overlap > 0) slsch_re += (nb_re_dmrs * sci1_rb); // return the dmrs that are not transmitted due to SCI1
slsch_re -= sci1_re; // REs taken by SCI1
slsch_re -= sci2_re; // REs taken by SCI2
slsch_re -= csi_rs_re; // REs taken by CSI_RS
G_SL = slsch_re * Qm * Nl;
return(G_SL);
}
uint32_t nr_get_E(uint32_t G, uint8_t C, uint8_t Qm, uint8_t Nl, uint8_t r) {
uint32_t E;
uint8_t Cprime = C; //assume CBGTI not present

View File

@@ -59,6 +59,19 @@ uint32_t nr_get_G(uint16_t nb_rb, uint16_t nb_symb_sch, uint8_t nb_re_dmrs, uint
uint32_t nr_get_E(uint32_t G, uint8_t C, uint8_t Qm, uint8_t Nl, uint8_t r);
int get_NREsci2_2(const int sci2_alpha,
const int sci2_payload_len,
const int sci2_beta_offset,
const int pssch_numsym,
const int pscch_numsym,
const int pscch_numrbs,
const int l_subch,
const int subchannel_size,
const int target_coderate,
const int mcs_table_index);
uint32_t nr_get_G_SL(uint16_t nb_rb, uint16_t nb_symb_sch, uint8_t nb_re_dmrs, uint16_t length_dmrs, uint8_t sci1_dmrs_overlap, uint16_t sci1_re, uint16_t sci1_rb, uint16_t sci2_re, uint16_t csi_rs_re, uint8_t Qm, uint8_t Nl);
void compute_nr_prach_seq(uint8_t short_sequence, uint8_t num_sequences, uint8_t rootSequenceIndex, c16_t X_u[64][839]);
void nr_fill_du(uint16_t N_ZC, const uint16_t *prach_root_sequence_map);

View File

@@ -35,6 +35,7 @@
#include "PHY/defs_nr_common.h"
#include "PHY/defs_gNB.h"
#include "PHY/defs_nr_UE.h"
#define NR_PBCH_PDU_BITS 24
@@ -126,10 +127,17 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch, uint16_t N_RB, const NR_DL_FRAME_PARM
@param harq_pid HARQ process ID
*/
void nr_rx_pusch(PHY_VARS_gNB *gNB,
PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
nr_phy_data_t *phy_data,
int rxFSz,
c16_t rxdataF[][rxFSz],
uint8_t UE_id,
uint32_t frame,
uint8_t slot,
unsigned char harq_pid);
unsigned char harq_pid,
bool *is_csi_rs_slot
);
/** \brief This function performs RB extraction (signal and channel estimates) (currently signal only until channel estimation and compensation are implemented)
@param rxdataF pointer to the received frequency domain signal
@@ -140,13 +148,21 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
@param nb_rb_pusch The number of RBs allocated (used for Resource Allocation Type 1 in NR)
@param frame_parms, Pointer to frame descriptor structure
*/
void nr_ulsch_extract_rbs(c16_t **rxdataF,
void nr_ulsch_extract_rbs(int rxFSz,
c16_t rxdataF[][rxFSz],
NR_gNB_PUSCH *pusch_vars,
int slot,
unsigned char symbol,
uint8_t is_dmrs_symbol,
nfapi_nr_pusch_pdu_t *pusch_pdu,
NR_DL_FRAME_PARMS *frame_parms);
uint8_t is_csirs_symbol,
uint32_t bwp_start,
uint32_t rb_start,
uint32_t rb_size,
uint32_t nrOfLayers,
uint32_t num_dmrs_cdm_grps_no_data,
uint32_t dmrs_config_type,
NR_DL_FRAME_PARMS *frame_parms,
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params);
void nr_ulsch_scale_channel(int32_t **ul_ch_estimates_ext,
NR_DL_FRAME_PARMS *frame_parms,

View File

@@ -31,6 +31,7 @@
*/
#include "nr_dci.h"
# include "executables/softmodem-common.h"
void nr_group_sequence_hopping (pucch_GroupHopping_t PUCCH_GroupHopping,
uint32_t n_id,
@@ -63,7 +64,11 @@ void nr_group_sequence_hopping (pucch_GroupHopping_t PUCCH_GroupHopping,
uint8_t f_ss=0,f_gh=0;
*u=0;
*v=0;
uint32_t c_init = 0;
uint32_t c_init = 0;
if (get_softmodem_params()->sl_mode) {
*u = n_id % 30;
return;
}
uint32_t x1,s; // TS 38.211 Subclause 5.2.1
int l = 32, minShift = ((2*nr_slot_tx+n_hop)<<3);
int tmpShift =0;
@@ -139,29 +144,31 @@ double nr_cyclic_shift_hopping(uint32_t n_id,
uint32_t c_init = n_id; // we initialize c_init again to calculate n_cs
uint32_t x1,s = lte_gold_generic(&x1, &c_init, 1); // TS 38.211 Subclause 5.2.1
uint8_t n_cs=0;
int l = 32, minShift = (14*8*nr_slot_tx )+ 8*(lnormal+lprime);
int tmpShift =0;
uint8_t n_cs = 0;
int l = 32;
lnormal = get_softmodem_params()->sl_mode ? 0 : lnormal;
int minShift = (14 * 8 * nr_slot_tx) + 8 * (lnormal + lprime);
int tmpShift = 0;
#ifdef DEBUG_NR_PUCCH_TX
printf("\t\t [nr_cyclic_shift_hopping] calculating alpha (cyclic shift) using c_init=%u -> \n",c_init);
#endif
for (int m=0; m<8; m++) {
for (int m = 0; m < 8; m++) {
while(minShift >= l) {
s = lte_gold_generic(&x1, &c_init, 0);
l = l+32;
l = l + 32;
}
tmpShift = (minShift&((1<<5)-1)); //minShift%32;
tmpShift = (minShift & ((1 << 5) - 1)); //minShift%32;
minShift ++;
n_cs = n_cs+((1<<m)*((uint8_t)((s>>tmpShift)&1)));
n_cs = n_cs + ((1 << m) * ((uint8_t)((s >> (tmpShift + m)) & 1)));
// calculating n_cs (Not sure we have to use nr_slot_tx FIXME!!!)
// n_cs = n_cs+((1<<m)*((uint8_t)((s>>((14*8*nr_slot_tx) + 8*(lnormal+lprime) + m))&1)));
}
alpha = (alpha * (double)((m0+mcs+n_cs)%12));
alpha = (alpha * (double)((m0 + mcs + n_cs) % 12));
#ifdef DEBUG_NR_PUCCH_TX
printf("n_cs=%d -> %lf\n",n_cs,alpha);
printf("n_cs = %d -> %lf\n", n_cs, alpha);
#endif
return(alpha);
}

View File

@@ -31,6 +31,7 @@
*/
#include "PHY/defs_gNB.h"
#include "PHY/defs_nr_UE.h"
#include "common/utils/threadPool/thread-pool.h"
void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch, uint16_t N_RB_UL);
@@ -50,6 +51,7 @@ NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL);
*/
int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
struct PHY_VARS_NR_UE_s *UE,
uint8_t UE_id,
short *ulsch_llr,
NR_DL_FRAME_PARMS *frame_parms,
@@ -57,7 +59,11 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
uint32_t frame,
uint8_t nr_tti_rx,
uint8_t harq_pid,
uint32_t G);
uint32_t G,
UE_nr_rxtx_proc_t *proc,
nr_phy_data_t *phy_data,
int8_t *ack_nack_rcvd,
uint8_t num_acks);
/*! \brief Perform PUSCH unscrambling. TS 38.211 V15.4.0 subclause 6.3.1.1
@param llr, Pointer to llr bits

View File

@@ -31,6 +31,7 @@
*/
#include "PHY/defs_nr_UE.h"
// [from gNB coding]
#include "PHY/defs_gNB.h"
#include "PHY/CODING/coding_extern.h"
@@ -43,10 +44,12 @@
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
#include "SCHED_NR/sched_nr.h"
#include "SCHED_NR/fapi_nr_l1.h"
#include "defs.h"
#include "openair1/SCHED_NR_UE/defs.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "common/utils/LOG/log.h"
#include <syscall.h>
#include "executables/nr-uesoftmodem.h"
//#define DEBUG_ULSCH_DECODING
//#define gNB_DEBUG_TRACE
@@ -155,9 +158,9 @@ static void nr_processULSegment(void *arg)
t_nrLDPC_time_stats procTime = {0};
t_nrLDPC_time_stats *p_procTime = &procTime;
// start_meas(&phy_vars_gNB->ulsch_deinterleaving_stats);
#ifdef DEBUG_ULSCH_DECODING
start_meas(&phy_vars_gNB->ulsch_deinterleaving_stats);
#endif
////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// nr_deinterleaving_ldpc ///////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
@@ -169,21 +172,20 @@ static void nr_processULSegment(void *arg)
nr_deinterleaving_ldpc(E, Qm, harq_e, ulsch_llr + r_offset);
// for (int i =0; i<16; i++)
// printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,ulsch_harq->w[r][i], r_offset);
#ifdef DEBUG_ULSCH_DECODING
for (int i =0; i<16; i++)
printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,ulsch_harq->w[r][i], r_offset);
stop_meas(&phy_vars_gNB->ulsch_deinterleaving_stats);
//////////////////////////////////////////////////////////////////////////////////////////
#endif
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////// nr_rate_matching_ldpc_rx ////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
///////////////////////// ulsch_harq->e =====> ulsch_harq->d /////////////////////////
// start_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
#ifdef DEBUG_ULSCH_DECODING
start_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
#endif
if (nr_rate_matching_ldpc_rx(rdata->tbslbrm,
p_decoderParms->BG,
p_decoderParms->Z,
@@ -196,17 +198,19 @@ static void nr_processULSegment(void *arg)
ulsch_harq->F,
Kr - ulsch_harq->F - 2 * (p_decoderParms->Z))
== -1) {
#ifdef DEBUG_ULSCH_DECODING
stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
#endif
LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n");
rdata->decodeIterations = max_ldpc_iterations + 1;
return;
} else {
#ifdef DEBUG_ULSCH_DECODING
stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
#endif
}
ulsch_harq->d_to_be_cleared[r] = false;
memset(ulsch_harq->c[r], 0, Kr_bytes);
if (ulsch_harq->C == 1) {
@@ -220,9 +224,9 @@ static void nr_processULSegment(void *arg)
crc_type = CRC24_B;
length_dec = (ulsch_harq->B + 24 * ulsch_harq->C) / ulsch_harq->C;
}
// start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats);
#ifdef DEBUG_ULSCH_DECODING
start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats);
#endif
// set first 2*Z_c bits to zeros
memset(&z[0], 0, 2 * ulsch_harq->Z * sizeof(int16_t));
// set Filler bits
@@ -235,7 +239,6 @@ static void nr_processULSegment(void *arg)
for (i = 0, j = 0; j < ((kc * ulsch_harq->Z) >> 4) + 1; i += 2, j++) {
pl[j] = _mm_packs_epi16(pv[i], pv[i + 1]);
}
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////// nrLDPC_decoder /////////////////////////////////////
@@ -248,19 +251,30 @@ static void nr_processULSegment(void *arg)
if (rdata->decodeIterations <= p_decoderParms->numMaxIter)
memcpy(ulsch_harq->c[r],llrProcBuf, Kr>>3);
//stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats);
#ifdef DEBUG_ULSCH_DECODING
stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats);
#endif
}
int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
uint8_t ULSCH_id,
short *ulsch_llr,
NR_DL_FRAME_PARMS *frame_parms,
nfapi_nr_pusch_pdu_t *pusch_pdu,
uint32_t frame,
uint8_t nr_tti_rx,
uint8_t harq_pid,
uint32_t G)
struct PHY_VARS_NR_UE_s *UE,
uint8_t ULSCH_id,
short *ulsch_llr,
NR_DL_FRAME_PARMS *frame_parms,
nfapi_nr_pusch_pdu_t *pusch_pdu,
uint32_t frame,
uint8_t nr_tti_rx,
uint8_t harq_pid,
uint32_t G,
UE_nr_rxtx_proc_t *proc,
nr_phy_data_t *phy_data,
int8_t *ack_nack_rcvd,
uint8_t num_acks)
{
AssertFatal((phy_vars_gNB && !UE) || (!phy_vars_gNB && UE),"Only one of gNB or UE must be non-null`");
if (!ulsch_llr) {
LOG_E(PHY, "ulsch_decoding.c: NULL ulsch_llr pointer\n");
return -1;
@@ -268,8 +282,8 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 1);
NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id];
NR_gNB_PUSCH *pusch = &phy_vars_gNB->pusch_vars[ULSCH_id];
NR_gNB_ULSCH_t *ulsch = phy_vars_gNB ? &phy_vars_gNB->ulsch[ULSCH_id] : &UE->slsch[ULSCH_id];
NR_gNB_PUSCH *pusch = phy_vars_gNB ? &phy_vars_gNB->pusch_vars[ULSCH_id] : &UE->pssch_vars[ULSCH_id];
NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process;
if (!harq_process) {
@@ -382,7 +396,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
Kr_bytes = Kr >> 3;
uint32_t offset = 0;
if (phy_vars_gNB->ldpc_offload_flag && mcs > 9) {
if (phy_vars_gNB && phy_vars_gNB->ldpc_offload_flag && mcs > 9) {
int8_t llrProcBuf[22 * 384];
// if (dtx_det==0) {
int16_t z_ol[68 * 384];
@@ -464,17 +478,17 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 0);
if (harq_process->processedSegments == harq_process->C) {
LOG_D(PHY, "[gNB %d] ULSCH: Setting ACK for slot %d TBS %d\n", phy_vars_gNB->Mod_id, ulsch->slot, harq_process->TBS);
LOG_D(NR_PHY, "[%s %d] ULSCH: Setting ACK for slot %d TBS %d\n", phy_vars_gNB ? "gNB" : "UE", phy_vars_gNB ? phy_vars_gNB->Mod_id : 0, ulsch->slot, harq_process->TBS);
ulsch->active = false;
harq_process->round = 0;
LOG_D(PHY, "ULSCH received ok \n");
nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 0, 0);
} else {
LOG_D(PHY,
"[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d)\n",
phy_vars_gNB->Mod_id,
LOG_E(PHY,
"[%s %d] ULSCH %d in error: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d)\n",
phy_vars_gNB ? "gNB" : "UE", phy_vars_gNB ? phy_vars_gNB->Mod_id : 0,
ULSCH_id,
ulsch->frame,
ulsch->slot,
harq_pid,
@@ -483,7 +497,6 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
harq_process->TBS);
ulsch->handled = 1;
decodeIterations = ulsch->max_ldpc_iterations + 1;
LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id);
nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 1, 0);
}
ulsch->last_iteration_cnt = decodeIterations;
@@ -492,13 +505,16 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
else {
dtx_det = 0;
set_abort(&harq_process->abort_decode, false);
notifiedFIFO_t nf;
if (UE) initNotifiedFIFO(&nf);
for (int r = 0; r < harq_process->C; r++) {
int E = nr_get_E(G, harq_process->C, Qm, n_layers, r);
union ldpcReqUnion id = {.s = {ulsch->rnti, frame, nr_tti_rx, 0, 0}};
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(ldpcDecode_t), id.p, &phy_vars_gNB->respDecode, &nr_processULSegment);
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(ldpcDecode_t), id.p, phy_vars_gNB ? &phy_vars_gNB->respDecode : &nf, &nr_processULSegment);
ldpcDecode_t *rdata = (ldpcDecode_t *)NotifiedFifoData(req);
decParams.R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index, E, decParams.BG, decParams.Z, &harq_process->llrLen, harq_process->round);
rdata->gNB = phy_vars_gNB;
rdata->UE = UE;
rdata->ulsch_harq = harq_process;
rdata->decoderParms = decParams;
rdata->ulsch_llr = ulsch_llr;
@@ -516,12 +532,24 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
rdata->ulsch = ulsch;
rdata->ulsch_id = ULSCH_id;
rdata->tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes;
pushTpool(&phy_vars_gNB->threadPool, req);
pushTpool(phy_vars_gNB ? &phy_vars_gNB->threadPool : &get_nrUE_params()->Tpool, req);
LOG_D(PHY, "Added a block to decode, in pipe: %d\n", r);
r_offset += E;
offset += (Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
//////////////////////////////////////////////////////////////////////////////////////////
}
if (UE) {
int nbDecode = harq_process->C;
while (nbDecode) {
notifiedFIFO_elt_t *req=pullTpool(&nf, &get_nrUE_params()->Tpool);
if (req == NULL)
break; // Tpool has been stopped
nr_postDecode_slsch(UE, req, proc, phy_data, ack_nack_rcvd, num_acks);
delNotifiedFIFO_elt(req);
nbDecode--;
}
}
}
return harq_process->C;
}

View File

@@ -3,11 +3,16 @@
#include "nr_transport_proto.h"
#include "PHY/impl_defs_top.h"
#include "PHY/NR_TRANSPORT/nr_sch_dmrs.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "PHY/NR_REFSIG/dmrs_nr.h"
#include "PHY/NR_REFSIG/ptrs_nr.h"
#include "PHY/NR_ESTIMATION/nr_ul_estimation.h"
#include "PHY/defs_nr_common.h"
#include "common/utils/nr/nr_common.h"
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
#include "executables/nr-uesoftmodem.h"
#include "SCHED_NR_UE/defs.h"
#include "openair1/PHY/MODULATION/modulation_UE.h"
//#define DEBUG_CH_COMP
//#define DEBUG_RB_EXT
@@ -16,8 +21,8 @@
#define INVALID_VALUE 255
void nr_idft(int32_t *z, uint32_t Msc_PUSCH)
{
void nr_idft(int32_t *z, uint32_t Msc_PUSCH) {
#if defined(__x86_64__) || defined(__i386__)
__m128i idft_in128[1][3240], idft_out128[1][3240];
@@ -303,14 +308,22 @@ void nr_idft(int32_t *z, uint32_t Msc_PUSCH)
}
void nr_ulsch_extract_rbs(c16_t **rxdataF,
void nr_ulsch_extract_rbs(int rxFSz,
c16_t rxdataF[][rxFSz],
NR_gNB_PUSCH *pusch_vars,
int slot,
unsigned char symbol,
uint8_t is_dmrs_symbol,
nfapi_nr_pusch_pdu_t *pusch_pdu,
NR_DL_FRAME_PARMS *frame_parms) {
uint8_t is_csirs_symbol,
uint32_t bwp_start,
uint32_t rb_start,
uint32_t rb_size,
uint32_t nrOfLayers,
uint32_t num_dmrs_cdm_grps_no_data,
uint32_t dmrs_config_type,
NR_DL_FRAME_PARMS *frame_parms,
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params) {
unsigned short start_re, re, nb_re_pusch;
unsigned char aarx, aatx;
uint32_t rxF_ext_index = 0;
@@ -318,16 +331,16 @@ void nr_ulsch_extract_rbs(c16_t **rxdataF,
uint32_t ul_ch0_index = 0;
int16_t *rxF,*rxF_ext;
int *ul_ch0,*ul_ch0_ext;
int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size;
int soffset = 0; /*(slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size;*/
#ifdef DEBUG_RB_EXT
printf("--------------------symbol = %d-----------------------\n", symbol);
printf("--------------------ch_ext_index = %d-----------------------\n", symbol*NR_NB_SC_PER_RB * pusch_pdu->rb_size);
printf("--------------------ch_ext_index = %d-----------------------\n", symbol*NR_NB_SC_PER_RB * rb_size);
#endif
uint8_t is_data_re;
start_re = (frame_parms->first_carrier_offset + (pusch_pdu->rb_start + pusch_pdu->bwp_start) * NR_NB_SC_PER_RB)%frame_parms->ofdm_symbol_size;
nb_re_pusch = NR_NB_SC_PER_RB * pusch_pdu->rb_size;
start_re = (frame_parms->first_carrier_offset + (rb_start + bwp_start) * NR_NB_SC_PER_RB)%frame_parms->ofdm_symbol_size;
nb_re_pusch = NR_NB_SC_PER_RB * rb_size;
int nb_re_pusch2 = nb_re_pusch + (nb_re_pusch&7);
@@ -335,26 +348,73 @@ void nr_ulsch_extract_rbs(c16_t **rxdataF,
rxF = (int16_t *)&rxdataF[aarx][soffset+(symbol * frame_parms->ofdm_symbol_size)];
rxF_ext = (int16_t *)&pusch_vars->rxdataF_ext[aarx][symbol * nb_re_pusch2]; // [hna] rxdataF_ext isn't contiguous in order to solve an alignment problem ib llr computation in case of mod_order = 4, 6
AssertFatal(soffset + (symbol * frame_parms->ofdm_symbol_size) + start_re < rxFSz, "rxF offset is greater than the buffer size\n");
AssertFatal(symbol * nb_re_pusch2 + nb_re_pusch < nb_re_pusch2 * frame_parms->symbols_per_slot, "Copied PUSCH data is more than rxF_ext size\n");
LOG_D(NR_PHY,"symbol %d : rxF energy %d\n",symbol,dB_fixed(signal_energy_nodc((int32_t*)rxF,frame_parms->ofdm_symbol_size)));
if (is_dmrs_symbol == 0) {
if (start_re + nb_re_pusch <= frame_parms->ofdm_symbol_size) {
memcpy1((void*)rxF_ext, (void*)&rxF[start_re*2], nb_re_pusch*sizeof(int32_t));
if (is_csirs_symbol == 0) {
if (start_re + nb_re_pusch <= frame_parms->ofdm_symbol_size) {
memcpy1((void*)rxF_ext, (void*)&rxF[start_re*2], nb_re_pusch*sizeof(int32_t));
} else {
int neg_length = frame_parms->ofdm_symbol_size-start_re;
int pos_length = nb_re_pusch-neg_length;
memcpy1((void*)rxF_ext, (void*)&rxF[start_re*2], neg_length*sizeof(int32_t));
memcpy1((void*)&rxF_ext[2*neg_length], (void*)rxF, pos_length*sizeof(int32_t));
}
for (aatx = 0; aatx < nrOfLayers; aatx++) {
ul_ch0 = &pusch_vars->ul_ch_estimates[aatx*frame_parms->nb_antennas_rx+aarx][pusch_vars->dmrs_symbol*frame_parms->ofdm_symbol_size]; // update channel estimates if new dmrs symbol are available
ul_ch0_ext = &pusch_vars->ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*nb_re_pusch2];
memcpy1((void*)ul_ch0_ext, (void*)ul_ch0,nb_re_pusch*sizeof(int32_t));
}
} else {
int neg_length = frame_parms->ofdm_symbol_size-start_re;
int pos_length = nb_re_pusch-neg_length;
memcpy1((void*)rxF_ext,(void*)&rxF[start_re*2],neg_length*sizeof(int32_t));
memcpy1((void*)&rxF_ext[2*neg_length],(void*)rxF,pos_length*sizeof(int32_t));
}
int16_t csi_rs_rb = csi_params->start_rb;
for (aatx = 0; aatx < nrOfLayers; aatx++) {
ul_ch0 = &pusch_vars->ul_ch_estimates[aatx*frame_parms->nb_antennas_rx+aarx][pusch_vars->dmrs_symbol*frame_parms->ofdm_symbol_size]; // update channel estimates if new dmrs symbol are available
ul_ch0_ext = &pusch_vars->ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*nb_re_pusch2];
for (aatx = 0; aatx < pusch_pdu->nrOfLayers; aatx++) {
ul_ch0 = &pusch_vars->ul_ch_estimates[aatx*frame_parms->nb_antennas_rx+aarx][pusch_vars->dmrs_symbol*frame_parms->ofdm_symbol_size]; // update channel estimates if new dmrs symbol are available
ul_ch0_ext = &pusch_vars->ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*nb_re_pusch2];
memcpy1((void*)ul_ch0_ext,(void*)ul_ch0,nb_re_pusch*sizeof(int32_t));
}
rxF_ext_index = 0;
ul_ch0_ext_index = 0;
ul_ch0_index = 0;
for (re = 0; re < nb_re_pusch; re++) {
uint8_t is_csi_rs = 0;
uint16_t k = start_re + re;
if ((k >= csi_params->start_rb * NR_NB_SC_PER_RB) && (re % NR_NB_SC_PER_RB == 0) && (csi_rs_rb < csi_params->nr_of_rbs)) {
csi_rs_params_t table_params;
get_csi_rs_params_from_table(csi_params, &table_params);
port_freq_indices_t *port_freq_indices = (port_freq_indices_t *)malloc(table_params.ports*sizeof(port_freq_indices));
get_csi_rs_freq_ind_sl(frame_parms, csi_rs_rb, csi_params, &table_params, port_freq_indices);
if (k == port_freq_indices[aatx].k) {
is_csi_rs = 1;
csi_rs_rb++;
}
free(port_freq_indices);
port_freq_indices = NULL;
}
if (++k >= frame_parms->ofdm_symbol_size) {
k -= frame_parms->ofdm_symbol_size;
}
// save only data and respective channel estimates
if (is_csi_rs == 0) {
if (aatx == 0) {
rxF_ext[rxF_ext_index] = (rxF[ ((start_re + re)*2) % (frame_parms->ofdm_symbol_size*2)]);
rxF_ext[rxF_ext_index + 1] = (rxF[(((start_re + re)*2) + 1) % (frame_parms->ofdm_symbol_size*2)]);
rxF_ext_index +=2;
}
ul_ch0_ext[ul_ch0_ext_index] = ul_ch0[ul_ch0_index];
ul_ch0_ext_index++;
}
ul_ch0_index++;
}
}
}
} else {
for (aatx = 0; aatx < pusch_pdu->nrOfLayers; aatx++) {
for (aatx = 0; aatx < nrOfLayers; aatx++) {
ul_ch0 = &pusch_vars->ul_ch_estimates[aatx*frame_parms->nb_antennas_rx+aarx][pusch_vars->dmrs_symbol*frame_parms->ofdm_symbol_size]; // update channel estimates if new dmrs symbol are available
ul_ch0_ext = &pusch_vars->ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*nb_re_pusch2];
@@ -363,7 +423,7 @@ void nr_ulsch_extract_rbs(c16_t **rxdataF,
ul_ch0_index = 0;
for (re = 0; re < nb_re_pusch; re++) {
uint16_t k = start_re + re;
is_data_re = allowed_xlsch_re_in_dmrs_symbol(k, start_re, frame_parms->ofdm_symbol_size, pusch_pdu->num_dmrs_cdm_grps_no_data, pusch_pdu->dmrs_config_type);
is_data_re = allowed_xlsch_re_in_dmrs_symbol(k, start_re, frame_parms->ofdm_symbol_size, num_dmrs_cdm_grps_no_data, dmrs_config_type);
if (++k >= frame_parms->ofdm_symbol_size) {
k -= frame_parms->ofdm_symbol_size;
}
@@ -388,7 +448,7 @@ void nr_ulsch_extract_rbs(c16_t **rxdataF,
is_dmrs_symbol,rxF_ext_index>>1, rxF_ext[rxF_ext_index],rxF_ext[rxF_ext_index+1],
ul_ch0_ext_index, ((int16_t*)&ul_ch0_ext[ul_ch0_ext_index])[0], ((int16_t*)&ul_ch0_ext[ul_ch0_ext_index])[1]);
#endif
}
}
ul_ch0_index++;
}
}
@@ -591,13 +651,13 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext,
rxF = (int16_t *) &rxdataF_ext[aarx][symbol * (off + (nb_rb * 12))];
ul_ch = (int16_t *) &ul_ch_estimates_ext[nl * frame_parms->nb_antennas_rx + aarx][symbol * (off + (nb_rb * 12))];
printf("--------symbol = %d, mod_order = %d, output_shift = %d, layer %i, antenna rx = %d -----------\n",
LOG_I(NR_PHY,"--------symbol = %d, mod_order = %d, output_shift = %d, layer %i, antenna rx = %d -----------\n",
symbol, mod_order, output_shift, nl, aarx);
printf("----------------Before compensation------------------\n");
LOG_I(NR_PHY,"----------------Before compensation------------------\n");
for (prnt_idx = 0; prnt_idx < 12 * 5 * 2; prnt_idx += 2) {
printf("rxF[%d] = (%d,%d)\n", prnt_idx >> 1, rxF[prnt_idx], rxF[prnt_idx + 1]);
printf("ul_ch[%d] = (%d,%d)\n", prnt_idx >> 1, ul_ch[prnt_idx], ul_ch[prnt_idx + 1]);
LOG_I(NR_PHY,"rxF[%d] = (%d,%d)\n", prnt_idx >> 1, rxF[prnt_idx], rxF[prnt_idx + 1]);
LOG_I(NR_PHY,"ul_ch[%d] = (%d,%d)\n", prnt_idx >> 1, ul_ch[prnt_idx], ul_ch[prnt_idx + 1]);
}
}
}
@@ -1049,10 +1109,10 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext,
for (int aarx2=0; aarx2<frame_parms->nb_antennas_rx; aarx2++) {
rxF = (int16_t *)&rxdataF_comp[nl2*frame_parms->nb_antennas_rx+aarx2][(symbol*(off+(nb_rb*12)))];
printf("--------After compansation, layer %i, antenna rx %i----------\n", nl2, aarx2);
LOG_I(NR_PHY,"--------After compansation, layer %i, antenna rx %i----------\n", nl2, aarx2);
for (prnt_idx=0;prnt_idx<12*5*2;prnt_idx+=2){
printf("rxF[%d] = (%d,%d)\n", prnt_idx>>1, rxF[prnt_idx],rxF[prnt_idx+1]);
LOG_I(NR_PHY,"rxF[%d] = (%d,%d)\n", prnt_idx>>1, rxF[prnt_idx],rxF[prnt_idx+1]);
}
}
}
@@ -1893,160 +1953,249 @@ uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms,
/* Main Function */
void nr_rx_pusch(PHY_VARS_gNB *gNB,
PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
nr_phy_data_t *phy_data,
int rxFSz,
c16_t rxdataF[][rxFSz],
uint8_t ulsch_id,
uint32_t frame,
uint8_t slot,
unsigned char harq_pid)
unsigned char harq_pid,
bool *is_csi_rs_slot)
{
uint8_t aarx, aatx;
uint32_t nb_re_pusch, bwp_start_subcarrier;
int avgs = 0;
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ulsch_id];
nfapi_nr_pusch_pdu_t *rel15_ul = &ulsch->harq_process->ulsch_pdu;
int avg[frame_parms->nb_antennas_rx*rel15_ul->nrOfLayers];
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params = NULL;
AssertFatal((gNB && !ue) || (!gNB && ue),"Both gNB and UE cannot be non-null\n");
NR_DL_FRAME_PARMS *frame_parms = gNB ? &gNB->frame_parms : &ue->SL_UE_PHY_PARAMS.sl_frame_params;
NR_gNB_ULSCH_t *ulsch = gNB ? &gNB->ulsch[ulsch_id] : &ue->slsch[ulsch_id];
nfapi_nr_pusch_pdu_t *rel15_ul = gNB ? &ulsch->harq_process->ulsch_pdu : NULL;
sl_nr_rx_config_pssch_sci_pdu_t *pssch_pdu = ue ? ulsch->harq_process->pssch_pdu : NULL;
uint32_t nrOfLayers = pssch_pdu ? pssch_pdu->num_layers : rel15_ul->nrOfLayers;
uint32_t rb_start = pssch_pdu ? pssch_pdu->startrb : rel15_ul->rb_start;
uint32_t bwp_start = pssch_pdu ? 0 : rel15_ul->bwp_start;
uint32_t rnti = pssch_pdu ? 0 : rel15_ul->rnti;
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id];
uint32_t rb_size = pssch_pdu ? pssch_pdu->num_subch*pssch_pdu->subchannel_size : rel15_ul->rb_size;
uint32_t qam_mod_order = pssch_pdu ? pssch_pdu->mod_order : rel15_ul->qam_mod_order;
uint32_t start_symbol_index = pssch_pdu ? 1 : rel15_ul->start_symbol_index;
uint32_t nr_of_symbols = pssch_pdu ? pssch_pdu->pssch_numsym : rel15_ul->nr_of_symbols;
uint32_t dmrs_config_type = pssch_pdu ? 0 : rel15_ul->dmrs_config_type;
uint32_t num_dmrs_cdm_grps_no_data = pssch_pdu ? 1 : rel15_ul->num_dmrs_cdm_grps_no_data;
uint32_t ul_dmrs_symb_pos = pssch_pdu ? pssch_pdu->dmrs_symbol_position : rel15_ul->ul_dmrs_symb_pos;
uint32_t dmrs_ports = pssch_pdu ? pssch_pdu->num_layers : rel15_ul->dmrs_ports;
int sci1_re_per_symb = pssch_pdu ? (pssch_pdu->pscch_numrbs*NR_NB_SC_PER_RB) : 0;
int sci2_re = pssch_pdu ? get_NREsci2_2(pssch_pdu->sci2_alpha_times_100,
pssch_pdu->sci2_len,
pssch_pdu->sci2_beta_offset,
pssch_pdu->pssch_numsym,
pssch_pdu->pscch_numsym,
pssch_pdu->pscch_numrbs,
pssch_pdu->l_subch,
pssch_pdu->subchannel_size,
pssch_pdu->targetCodeRate,
0) : 0;
int16_t sci2_llrs[(sci2_re*2)] __attribute__((aligned(16)));
int16_t unscrambled_sci2_llrs[(sci2_re*2)] __attribute__((aligned(16)));
int sci2_cnt=0;
int sci2_left = sci2_re;
int avg[frame_parms->nb_antennas_rx*nrOfLayers];
int16_t *temp_llr = (int16_t *)malloc16_clear((8 * ((3 * 8 * 6144) + 12)) * sizeof(int16_t));
int32_t *temp_symbol = (int32_t *) malloc16_clear(rb_size * NR_NB_SC_PER_RB * sizeof(int32_t));
NR_gNB_PUSCH *pusch_vars = gNB ? &gNB->pusch_vars[ulsch_id] : &ue->pssch_vars[ulsch_id];
pusch_vars->dmrs_symbol = INVALID_VALUE;
pusch_vars->cl_done = 0;
bwp_start_subcarrier = ((rel15_ul->rb_start + rel15_ul->bwp_start)*NR_NB_SC_PER_RB + frame_parms->first_carrier_offset) % frame_parms->ofdm_symbol_size;
LOG_D(PHY,"pusch %d.%d : bwp_start_subcarrier %d, rb_start %d, first_carrier_offset %d\n", frame,slot,bwp_start_subcarrier, rel15_ul->rb_start, frame_parms->first_carrier_offset);
LOG_D(PHY,"pusch %d.%d : ul_dmrs_symb_pos %x\n",frame,slot,rel15_ul->ul_dmrs_symb_pos);
LOG_D(PHY,"ulsch RX %x : start_rb %d nb_rb %d mcs %d Nl %d Tpmi %d bwp_start %d start_sc %d start_symbol %d num_symbols %d cdmgrpsnodata %d num_dmrs %d dmrs_ports %d\n",
rel15_ul->rnti,rel15_ul->rb_start,rel15_ul->rb_size,rel15_ul->mcs_index,
rel15_ul->nrOfLayers,0,rel15_ul->bwp_start,0,rel15_ul->start_symbol_index,rel15_ul->nr_of_symbols,
rel15_ul->num_dmrs_cdm_grps_no_data,rel15_ul->ul_dmrs_symb_pos,rel15_ul->dmrs_ports);
bwp_start_subcarrier = ((rb_start + bwp_start)*NR_NB_SC_PER_RB + frame_parms->first_carrier_offset) % frame_parms->ofdm_symbol_size;
LOG_D(PHY,"pusch %d.%d : bwp_start_subcarrier %d, rb_start %d, first_carrier_offset %d\n", frame,slot,bwp_start_subcarrier, rb_start, frame_parms->first_carrier_offset);
LOG_D(PHY,"pusch %d.%d : ul_dmrs_symb_pos %x\n",frame,slot,ul_dmrs_symb_pos);
LOG_D(PHY,"ulsch RX %x : start_rb %d nb_rb %d Nl %d Tpmi %d bwp_start %d start_sc %d start_symbol %d num_symbols %d cdmgrpsnodata %d num_dmrs %d dmrs_ports %d\n",
rnti,rb_start,rb_size,
nrOfLayers,0,bwp_start,0,start_symbol_index,nr_of_symbols,
num_dmrs_cdm_grps_no_data,ul_dmrs_symb_pos,dmrs_ports);
//----------------------------------------------------------
//--------------------- Channel estimation ---------------------
//----------------------------------------------------------
start_meas(&gNB->ulsch_channel_estimation_stats);
if (gNB) start_meas(&gNB->ulsch_channel_estimation_stats);
int max_ch = 0;
uint32_t nvar = 0;
for(uint8_t symbol = rel15_ul->start_symbol_index; symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); symbol++) {
uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01;
for(uint8_t symbol = start_symbol_index; symbol < (start_symbol_index + nr_of_symbols); symbol++) {
uint8_t dmrs_symbol_flag = (ul_dmrs_symb_pos >> symbol) & 0x01;
LOG_D(PHY, "symbol %d, dmrs_symbol_flag :%d\n", symbol, dmrs_symbol_flag);
if (dmrs_symbol_flag == 1) {
if (pusch_vars->dmrs_symbol == INVALID_VALUE)
pusch_vars->dmrs_symbol = symbol;
for (int nl=0; nl<rel15_ul->nrOfLayers; nl++) {
for (int nl=0; nl<nrOfLayers; nl++) {
uint32_t nvar_tmp = 0;
nr_pusch_channel_estimation(gNB,
int dmrs_port = get_dmrs_port(nl,dmrs_ports);
if (dmrs_port<0) return;
nr_pusch_channel_estimation(gNB,ue,rxFSz,rxdataF,
slot,
get_dmrs_port(nl,rel15_ul->dmrs_ports),
dmrs_port,
symbol,
ulsch_id,
bwp_start_subcarrier,
rel15_ul,
pssch_pdu,
&max_ch,
&nvar_tmp);
nvar += nvar_tmp;
}
nr_gnb_measurements(gNB, ulsch, pusch_vars, symbol, rel15_ul->nrOfLayers);
PHY_MEASUREMENTS_gNB *meas = gNB ? &gNB->measurements : ue->sl_measurements;
nr_gnb_measurements(meas, frame_parms,ulsch, pusch_vars, symbol, nrOfLayers);
allocCast2D(n0_subband_power,
unsigned int,
gNB->measurements.n0_subband_power,
meas->n0_subband_power,
frame_parms->nb_antennas_rx,
frame_parms->N_RB_UL,
false);
for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
if (symbol == rel15_ul->start_symbol_index) {
if (symbol == start_symbol_index) {
pusch_vars->ulsch_power[aarx] = 0;
pusch_vars->ulsch_noise_power[aarx] = 0;
}
for (aatx = 0; aatx < rel15_ul->nrOfLayers; aatx++) {
for (aatx = 0; aatx < nrOfLayers; aatx++) {
pusch_vars->ulsch_power[aarx] += signal_energy_nodc(
&pusch_vars->ul_ch_estimates[aatx * gNB->frame_parms.nb_antennas_rx + aarx][symbol * frame_parms->ofdm_symbol_size],
rel15_ul->rb_size * 12);
&pusch_vars->ul_ch_estimates[aatx * frame_parms->nb_antennas_rx + aarx][symbol * frame_parms->ofdm_symbol_size],
rb_size * 12);
}
for (int rb = 0; rb < rel15_ul->rb_size; rb++) {
for (int rb = 0; rb < rb_size; rb++) {
pusch_vars->ulsch_noise_power[aarx] +=
n0_subband_power[aarx][rel15_ul->bwp_start + rel15_ul->rb_start + rb] / rel15_ul->rb_size;
n0_subband_power[aarx][bwp_start + rb_start + rb] / rb_size;
}
LOG_D(PHY,
"aa %d, bwp_start%d, rb_start %d, rb_size %d: ulsch_power %d, ulsch_noise_power %d\n",
aarx,
rel15_ul->bwp_start,
rel15_ul->rb_start,
rel15_ul->rb_size,
LOG_D(NR_PHY,
"aa %d, symbol %d, bwp_start%d, rb_start %d, rb_size %d: ulsch_power %d, ulsch_noise_power %d\n",
aarx,symbol,
bwp_start,
rb_start,
rb_size,
pusch_vars->ulsch_power[aarx],
pusch_vars->ulsch_noise_power[aarx]);
}
}
}
nvar /= (rel15_ul->nr_of_symbols * rel15_ul->nrOfLayers * frame_parms->nb_antennas_rx);
nvar /= (nr_of_symbols * nrOfLayers * frame_parms->nb_antennas_rx);
if (gNB->chest_time == 1) { // averaging time domain channel estimates
if (gNB && gNB->chest_time == 1) { // averaging time domain channel estimates
nr_chest_time_domain_avg(frame_parms,
pusch_vars->ul_ch_estimates,
rel15_ul->nr_of_symbols,
rel15_ul->start_symbol_index,
rel15_ul->ul_dmrs_symb_pos,
rel15_ul->rb_size);
nr_of_symbols,
start_symbol_index,
ul_dmrs_symb_pos,
rb_size);
pusch_vars->dmrs_symbol =
get_next_dmrs_symbol_in_slot(rel15_ul->ul_dmrs_symb_pos, rel15_ul->start_symbol_index, rel15_ul->nr_of_symbols);
get_next_dmrs_symbol_in_slot(ul_dmrs_symb_pos, start_symbol_index, nr_of_symbols);
}
stop_meas(&gNB->ulsch_channel_estimation_stats);
if (gNB) stop_meas(&gNB->ulsch_channel_estimation_stats);
int off = ((rel15_ul->rb_size&1) == 1)? 4:0;
int off = ((rb_size&1) == 1)? 4:0;
uint32_t rxdataF_ext_offset = 0;
uint8_t shift_ch_ext = rel15_ul->nrOfLayers > 1 ? log2_approx(max_ch >> 11) : 0;
uint8_t shift_ch_ext = nrOfLayers > 1 ? log2_approx(max_ch >> 11) : 0;
// Flag to select the receiver: (true) Nonlinear ML receiver, (false) Linear MMSE receiver
// By default, we are using the Nonlinear ML receiver, except
// - for 256QAM as Nonlinear ML receiver is not implemented for 256QAM
// - for 64QAM as Nonlinear ML receiver requires more processing time than MMSE, and many machines are not powerful enough
bool ml_rx = true;
if (rel15_ul->nrOfLayers != 2 || rel15_ul->qam_mod_order >= 6) {
if (nrOfLayers != 2 || qam_mod_order >= 6) {
ml_rx = false;
}
int ad_shift = 0;
if (rel15_ul->nrOfLayers == 1) {
if (nrOfLayers == 1) {
ad_shift = 1 + log2_approx(frame_parms->nb_antennas_rx >> 2);
} else if (ml_rx == false) {
ad_shift = -3; // For 2-layers, we are already doing a bit shift in the nr_ulsch_mmse_2layers() function, so we can use more bits
}
for(uint8_t symbol = rel15_ul->start_symbol_index; symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); symbol++) {
uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01;
if (dmrs_symbol_flag == 1) {
if ((rel15_ul->ul_dmrs_symb_pos >> ((symbol + 1) % frame_parms->symbols_per_slot)) & 0x01)
for(uint8_t symbol = start_symbol_index; symbol < (start_symbol_index + nr_of_symbols); symbol++) {
uint8_t csi_rs_symbol_flag = 0;
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_CSI_RS) {
*is_csi_rs_slot = true;
csi_params = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)&ue->csirs_vars[0]->csirs_config_pdu;
} else {
*is_csi_rs_slot = false;
}
if (*is_csi_rs_slot && (csi_params->symb_l0 == symbol)) {
csi_rs_symbol_flag = 1;
AssertFatal(csi_params->freq_density > 0, "freq_density MUST be greater than zero");
AssertFatal(csi_params->nr_of_rbs > 0, "nr_of_rbs MUST be greater than zero");
LOG_D(NR_PHY, "%d.%d symbol %i, freq_density %i symb_l0 %i csi_type %i power_control_offset %i power_control_offset_ss %i measurement_bitmap %i cdm_type %i row %i freq_domain %i start_rb %i nr_of_rbs %i\n",
frame,
slot,
symbol,
csi_params->freq_density,
csi_params->symb_l0,
csi_params->csi_type,
csi_params->power_control_offset,
csi_params->power_control_offset_ss,
csi_params->measurement_bitmap,
csi_params->cdm_type,
csi_params->row,
csi_params->freq_domain,
csi_params->start_rb,
csi_params->nr_of_rbs);
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_CSI_RS) {
// FIXIT: Reconsider index of csirs_vars[0] for multiple connected UEs case
if (ue->csirs_vars[0]->active == 1) {
LOG_D(NR_PHY, "%d.%d Received CSI-RS\n", proc->frame_rx, proc->nr_slot_rx);
nr_slot_fep(ue, frame_parms, proc, symbol, rxdataF, link_type_sl);
nr_ue_csi_rs_procedures(ue, proc, rxdataF);
ue->csirs_vars[0]->active = 0;
}
}
}
uint8_t dmrs_symbol_flag = (ul_dmrs_symb_pos >> symbol) & 0x01;
int sci2_cnt_thissymb=0;
if (csi_rs_symbol_flag) {
uint8_t freq_subcarriers_per_rb = 12;
uint8_t nr_rbs_w_csi_rs = csi_params->nr_of_rbs / csi_params->freq_density;
uint8_t nr_rbs_wo_csi_rs = (rb_size - nr_rbs_w_csi_rs);
// Actually, kprime + 1 sub-carriers are used by csi-rs. kprime can be 0 or 1 but nb_antennas_tx can be greater than 2.
uint8_t subcarriers_used = get_nrUE_params()->nb_antennas_tx > 2 ? 2 : get_nrUE_params()->nb_antennas_tx;
nb_re_pusch = nr_rbs_wo_csi_rs * freq_subcarriers_per_rb + nr_rbs_w_csi_rs * (freq_subcarriers_per_rb - subcarriers_used);
} else if (dmrs_symbol_flag == 1) {
if ((ul_dmrs_symb_pos >> ((symbol + 1) % frame_parms->symbols_per_slot)) & 0x01)
AssertFatal(1==0,"Double DMRS configuration is not yet supported\n");
if (gNB->chest_time == 0) // Non averaging time domain channel estimates
if (ue || gNB->chest_time == 0) // Non averaging time domain channel estimates
pusch_vars->dmrs_symbol = symbol;
if (rel15_ul->dmrs_config_type == 0) {
if (dmrs_config_type == 0) {
// if no data in dmrs cdm group is 1 only even REs have no data
// if no data in dmrs cdm group is 2 both odd and even REs have no data
nb_re_pusch = rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*6));
nb_re_pusch = rb_size *(12 - (num_dmrs_cdm_grps_no_data*6));
}
else {
nb_re_pusch = rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*4));
nb_re_pusch = rb_size *(12 - (num_dmrs_cdm_grps_no_data*4));
}
}
else {
nb_re_pusch = rel15_ul->rb_size * NR_NB_SC_PER_RB;
nb_re_pusch = rb_size * NR_NB_SC_PER_RB;
}
pusch_vars->ul_valid_re_per_slot[symbol] = nb_re_pusch;
LOG_D(PHY, "symbol %d: nb_re_pusch %d, DMRS symbl used for Chest :%d \n", symbol, nb_re_pusch, pusch_vars->dmrs_symbol);
//----------------------------------------------------------
//--------------------- RBs extraction ---------------------
//----------------------------------------------------------
if (nb_re_pusch > 0) {
start_meas(&gNB->ulsch_rbs_extraction_stats);
nr_ulsch_extract_rbs(gNB->common_vars.rxdataF, pusch_vars, slot, symbol, dmrs_symbol_flag, rel15_ul, frame_parms);
stop_meas(&gNB->ulsch_rbs_extraction_stats);
LOG_D(NR_PHY,"extract RBs : frame %d, slot %d symbol %d nb_re_pusch %d\n", frame,slot,symbol, nb_re_pusch);
if (gNB) start_meas(&gNB->ulsch_rbs_extraction_stats);
nr_ulsch_extract_rbs(rxFSz, rxdataF, pusch_vars, slot, symbol, dmrs_symbol_flag, csi_rs_symbol_flag, bwp_start, rb_start, rb_size, nrOfLayers, num_dmrs_cdm_grps_no_data, dmrs_config_type, frame_parms, csi_params);
if (gNB) stop_meas(&gNB->ulsch_rbs_extraction_stats);
//----------------------------------------------------------
//--------------------- Channel Scaling --------------------
@@ -2057,8 +2206,8 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
symbol,
dmrs_symbol_flag,
nb_re_pusch,
rel15_ul->nrOfLayers,
rel15_ul->rb_size,
nrOfLayers,
rb_size,
shift_ch_ext);
if (pusch_vars->cl_done == 0) {
@@ -2067,12 +2216,12 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
avg,
symbol,
nb_re_pusch,
rel15_ul->nrOfLayers,
rel15_ul->rb_size);
nrOfLayers,
rb_size);
avgs = 0;
for (aatx=0;aatx<rel15_ul->nrOfLayers;aatx++)
for (aatx=0;aatx<nrOfLayers;aatx++)
for (aarx=0;aarx<frame_parms->nb_antennas_rx;aarx++)
avgs = cmax(avgs,avg[aatx*frame_parms->nb_antennas_rx+aarx]);
@@ -2086,57 +2235,57 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
//----------------------------------------------------------
//--------------------- Channel Compensation ---------------
//----------------------------------------------------------
start_meas(&gNB->ulsch_channel_compensation_stats);
LOG_D(PHY, "Doing channel compensations log2_maxh %d, avgs %d (%d,%d)\n" ,pusch_vars->log2_maxh, avgs,avg[0], avg[1]);
if (gNB) start_meas(&gNB->ulsch_channel_compensation_stats);
//LOG_I(PHY, "Doing channel compensations log2_maxh %d, avgs %d (%d,%d)\n" ,pusch_vars->log2_maxh, avgs,avg[0], avg[1]);
nr_ulsch_channel_compensation(pusch_vars->rxdataF_ext,
pusch_vars->ul_ch_estimates_ext,
pusch_vars->ul_ch_mag0,
pusch_vars->ul_ch_magb0,
pusch_vars->ul_ch_magc0,
pusch_vars->rxdataF_comp,
(rel15_ul->nrOfLayers > 1) ? pusch_vars->rho : NULL,
(nrOfLayers > 1) ? pusch_vars->rho : NULL,
frame_parms,
symbol,
nb_re_pusch,
dmrs_symbol_flag,
rel15_ul->qam_mod_order,
rel15_ul->nrOfLayers,
rel15_ul->rb_size,
qam_mod_order,
nrOfLayers,
rb_size,
pusch_vars->log2_maxh);
stop_meas(&gNB->ulsch_channel_compensation_stats);
if (gNB) stop_meas(&gNB->ulsch_channel_compensation_stats);
start_meas(&gNB->ulsch_mrc_stats);
if (gNB) start_meas(&gNB->ulsch_mrc_stats);
nr_ulsch_detection_mrc(frame_parms,
pusch_vars->rxdataF_comp,
pusch_vars->ul_ch_mag0,
pusch_vars->ul_ch_magb0,
pusch_vars->ul_ch_magc0,
(rel15_ul->nrOfLayers > 1) ? pusch_vars->rho : NULL,
rel15_ul->nrOfLayers,
(nrOfLayers > 1) ? pusch_vars->rho : NULL,
nrOfLayers,
symbol,
rel15_ul->rb_size,
rb_size,
nb_re_pusch);
// Apply MMSE for 2 Tx layers
if (ml_rx == false && rel15_ul->nrOfLayers == 2) {
if (ml_rx == false && nrOfLayers == 2) {
nr_ulsch_mmse_2layers(frame_parms,
pusch_vars->rxdataF_comp,
pusch_vars->ul_ch_mag0,
pusch_vars->ul_ch_magb0,
pusch_vars->ul_ch_magc0,
pusch_vars->ul_ch_estimates_ext,
rel15_ul->rb_size,
rb_size,
frame_parms->nb_antennas_rx,
rel15_ul->qam_mod_order,
qam_mod_order,
pusch_vars->log2_maxh,
symbol,
nb_re_pusch,
nvar);
}
stop_meas(&gNB->ulsch_mrc_stats);
if (gNB) stop_meas(&gNB->ulsch_mrc_stats);
if (rel15_ul->transform_precoding == transformPrecoder_enabled) {
if (gNB && rel15_ul->transform_precoding == transformPrecoder_enabled) {
// For odd number of resource blocks need byte alignment to multiple of 8
int nb_re_pusch2 = nb_re_pusch + (nb_re_pusch&7);
@@ -2150,16 +2299,17 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
//----------------------------------------------------------
/* In case PTRS is enabled then LLR will be calculated after PTRS symbols are processed *
* otherwise LLR are calculated for each symbol based upon DMRS channel estimates only. */
if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
start_meas(&gNB->ulsch_ptrs_processing_stats);
nr_pusch_ptrs_processing(gNB,
if (gNB && rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
if (gNB) start_meas(&gNB->ulsch_ptrs_processing_stats);
nr_pusch_ptrs_processing(gNB,ue,
frame_parms,
rel15_ul,
pssch_pdu,
ulsch_id,
slot,
symbol,
nb_re_pusch);
stop_meas(&gNB->ulsch_ptrs_processing_stats);
if (gNB) stop_meas(&gNB->ulsch_ptrs_processing_stats);
/* Subtract total PTRS RE's in the symbol from PUSCH RE's */
pusch_vars->ul_valid_re_per_slot[symbol] -= pusch_vars->ptrs_re_per_slot;
@@ -2168,38 +2318,125 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
/*---------------------------------------------------------------------------------------------------- */
/*-------------------- LLRs computation -------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------------------------*/
start_meas(&gNB->ulsch_llr_stats);
if (ml_rx == false || rel15_ul->nrOfLayers == 1) {
for (aatx=0; aatx < rel15_ul->nrOfLayers; aatx++) {
nr_ulsch_compute_llr(&pusch_vars->rxdataF_comp[aatx * frame_parms->nb_antennas_rx][symbol * (off + rel15_ul->rb_size * NR_NB_SC_PER_RB)],
pusch_vars->ul_ch_mag0[aatx * frame_parms->nb_antennas_rx],
pusch_vars->ul_ch_magb0[aatx * frame_parms->nb_antennas_rx],
pusch_vars->ul_ch_magc0[aatx * frame_parms->nb_antennas_rx],
&pusch_vars->llr_layers[aatx][rxdataF_ext_offset * rel15_ul->qam_mod_order],
rel15_ul->rb_size,
pusch_vars->ul_valid_re_per_slot[symbol],
symbol,
rel15_ul->qam_mod_order);
if (gNB) start_meas(&gNB->ulsch_llr_stats);
int sci1_offset=0;
if (symbol <= pssch_pdu->pscch_numsym) {
pusch_vars->ul_valid_re_per_slot[symbol] -= sci1_re_per_symb;
sci1_offset=sci1_re_per_symb;
}
if (ml_rx == false || nrOfLayers == 1) {
if (pssch_pdu && sci2_left>0){
LOG_D(NR_PHY, "valid_re_per_slot[%d] %d\n", symbol, pusch_vars->ul_valid_re_per_slot[symbol]);
int available_sci2_res_in_symb = pusch_vars->ul_valid_re_per_slot[symbol];
int slsch_res_in_symbol;
LOG_D(NR_PHY,"available_sci2_res_in_symb[%d] %d (sci1_re %d)\n",symbol,available_sci2_res_in_symb,sci1_re_per_symb);
int sci2_cnt_prev = sci2_cnt;
if (available_sci2_res_in_symb < sci2_left) {
sci2_cnt += available_sci2_res_in_symb; // take all of the PSSCH REs for SCI2
memcpy(&sci2_llrs[2*sci2_cnt_prev],&pusch_vars->rxdataF_comp[0][(symbol * (off + rb_size * NR_NB_SC_PER_RB))+sci1_offset],
available_sci2_res_in_symb*sizeof(int32_t));
sci2_left-= available_sci2_res_in_symb;
LOG_D(NR_PHY,"SCI2 taking all available REs. sci2_left %d\n",sci2_left);
pusch_vars->ul_valid_re_per_slot[symbol] = 0;
sci2_cnt_thissymb=available_sci2_res_in_symb;
}
else { // we finish SCI2 off here
memcpy(&sci2_llrs[2*sci2_cnt_prev],&pusch_vars->rxdataF_comp[0][(symbol * (off + rb_size * NR_NB_SC_PER_RB))+sci1_re_per_symb],
sci2_left*sizeof(int32_t));
slsch_res_in_symbol=available_sci2_res_in_symb-sci2_left;
LOG_D(NR_PHY, "SCI2 taking %d REs, SLSCH taking %d\n", sci2_left, slsch_res_in_symbol);
pusch_vars->ul_valid_re_per_slot[symbol]=slsch_res_in_symbol;
sci2_cnt_thissymb=sci2_left;
sci2_left=0;
//for (int i=0;i<sci2_re;i++) LOG_I(NR_PHY,"sci2_llrs [%d] %d,%d\n",i,sci2_llrs[i<<1],sci2_llrs[1+(i<<1)]);
//unscramble the SCI2 payload
nr_pdcch_unscrambling(sci2_llrs, 1010,sci2_re*2,pssch_pdu->Nid,unscrambled_sci2_llrs,1);
// for (int i=0;i<sci2_re;i++) LOG_I(NR_PHY,"sci2_llrs [%d] %d,%d\n",i,unscrambled_sci2_llrs[i<<1],unscrambled_sci2_llrs[1+(i<<1)]);
uint64_t sci_estimation[2]={0};
uint16_t dummy;
uint16_t crc = polar_decoder_int16(unscrambled_sci2_llrs,
sci_estimation,
&dummy,
1,
NR_POLAR_SCI2_MESSAGE_TYPE,
pssch_pdu->sci2_len,
sci2_re);
// send SCI indication with SCI2 payload and get SLSCH information if CRC is OK
LOG_D(NR_PHY,"SCI indication (crc %x)\n",crc);
if (crc==0) ue->SL_UE_PHY_PARAMS.pssch.rx_sci2_ok++;
else ue->SL_UE_PHY_PARAMS.pssch.rx_sci2_errors++;
sl_nr_sci_indication_t sci_ind={0};
sci_ind.sfn = frame;
sci_ind.slot = slot;
sci_ind.sensing_result = 0;
sci_ind.pssch_rsrp = 0; // setting this flag to zero; measuring from sci1
sci_ind.sci_pdu[sci_ind.number_of_SCIs].sci_format_type = SL_SCI_FORMAT_2_ON_PSSCH;
sci_ind.sci_pdu[sci_ind.number_of_SCIs].subch_index = 0;
sci_ind.sci_pdu[sci_ind.number_of_SCIs].pscch_rsrp = 0; // setting this flag to zero; measuring from sci1
sci_ind.sci_pdu[sci_ind.number_of_SCIs].sci_payloadlen = pssch_pdu->sci2_len;
sci_ind.sci_pdu[sci_ind.number_of_SCIs].Nid = dummy&65535;
memcpy(sci_ind.sci_pdu[sci_ind.number_of_SCIs].sci_payloadBits,&sci_estimation,8);
sci_ind.number_of_SCIs++;
nr_sidelink_indication_t sl_indication;
nr_fill_sl_indication(&sl_indication, NULL, &sci_ind, proc, ue, phy_data);
ue->if_inst->sl_indication(&sl_indication);
LOG_D(NR_PHY,"Returning from SCI2 SL indication\n");
//
}
} // (not ML || nrOfLayers==1 ) AND pssch and sci2 REs to handle
if (pssch_pdu) LOG_D(NR_PHY, "symbol %d: PSSCH REs %d (sci1 %d,sci2 %d)\n", symbol, pusch_vars->ul_valid_re_per_slot[symbol], sci1_offset, sci2_cnt_thissymb);
for (aatx=0; aatx < nrOfLayers; aatx++) {
if ((sci1_offset > 0 || sci2_cnt_thissymb > 0) && (qam_mod_order > 2)) {
memset(temp_symbol, 0, (sci1_offset + sci2_cnt_thissymb) * sizeof(int32_t));
memcpy(temp_symbol + sci1_offset + sci2_cnt_thissymb,
&pusch_vars->rxdataF_comp[aatx * frame_parms->nb_antennas_rx][symbol * (off + rb_size * NR_NB_SC_PER_RB) + sci1_offset+sci2_cnt_thissymb],
(rb_size * NR_NB_SC_PER_RB - (sci1_offset + sci2_cnt_thissymb)) * sizeof(int32_t));
nr_ulsch_compute_llr(temp_symbol,
pusch_vars->ul_ch_mag0[aatx * frame_parms->nb_antennas_rx],
pusch_vars->ul_ch_magb0[aatx * frame_parms->nb_antennas_rx],
pusch_vars->ul_ch_magc0[aatx * frame_parms->nb_antennas_rx],
temp_llr,
rb_size,
rb_size * NR_NB_SC_PER_RB,
symbol,
qam_mod_order);
memcpy(&pusch_vars->llr_layers[aatx][rxdataF_ext_offset * qam_mod_order],
temp_llr + (sci1_offset + sci2_cnt_thissymb) * qam_mod_order,
(rb_size * NR_NB_SC_PER_RB - (sci1_offset + sci2_cnt_thissymb)) * 2 * qam_mod_order);
} else {
nr_ulsch_compute_llr(&pusch_vars->rxdataF_comp[aatx * frame_parms->nb_antennas_rx][symbol * (off + rb_size * NR_NB_SC_PER_RB) + sci1_offset + sci2_cnt_thissymb],
pusch_vars->ul_ch_mag0[aatx * frame_parms->nb_antennas_rx],
pusch_vars->ul_ch_magb0[aatx * frame_parms->nb_antennas_rx],
pusch_vars->ul_ch_magc0[aatx * frame_parms->nb_antennas_rx],
&pusch_vars->llr_layers[aatx][rxdataF_ext_offset * qam_mod_order],
rb_size,
pusch_vars->ul_valid_re_per_slot[symbol],
symbol,
qam_mod_order);
}
}
} else {
} else { // this is MIMO case with ML
if (pssch_pdu) AssertFatal(1==0,"We need to handle the MIMO case for SCI2\n");
nr_ulsch_compute_ML_llr(pusch_vars->rxdataF_comp,
pusch_vars->ul_ch_mag0,
pusch_vars->rho,
pusch_vars->llr_layers,
frame_parms->nb_antennas_rx,
rel15_ul->rb_size,
rb_size,
nb_re_pusch,
symbol,
rxdataF_ext_offset,
rel15_ul->qam_mod_order);
qam_mod_order);
if (rel15_ul->qam_mod_order == 2) {
nr_ulsch_shift_llr(pusch_vars->llr_layers, nb_re_pusch, rxdataF_ext_offset, rel15_ul->qam_mod_order, 4);
if (qam_mod_order == 2) {
nr_ulsch_shift_llr(pusch_vars->llr_layers, nb_re_pusch, rxdataF_ext_offset, qam_mod_order, 4);
}
#ifdef ML_DEBUG
c16_t *llr_layers0 = (c16_t *)&pusch_vars->llr_layers[0][rxdataF_ext_offset * rel15_ul->qam_mod_order];
c16_t *llr_layers1 = (c16_t *)&pusch_vars->llr_layers[1][rxdataF_ext_offset * rel15_ul->qam_mod_order];
c16_t *llr_layers0 = (c16_t *)&pusch_vars->llr_layers[0][rxdataF_ext_offset * qam_mod_order];
c16_t *llr_layers1 = (c16_t *)&pusch_vars->llr_layers[1][rxdataF_ext_offset * qam_mod_order];
printf("===============================\n");
printf("AFTER nr_ulsch_compute_ML_llr()\n");
printf("===============================\n");
@@ -2214,4 +2451,6 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
rxdataF_ext_offset += pusch_vars->ul_valid_re_per_slot[symbol];
}
} // symbol loop
free(temp_llr);
free(temp_symbol);
}

View File

@@ -116,36 +116,6 @@ int get_pucch0_cs_lut_index(PHY_VARS_gNB *gNB,nfapi_nr_pucch_pdu_t* pucch_pdu) {
gNB->pucch0_lut.nb_id++;
return(gNB->pucch0_lut.nb_id-1);
}
static const int16_t idft12_re[12][12] = {
{23170,23170,23170,23170,23170,23170,23170,23170,23170,23170,23170,23170},
{23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585,0,11585,20066},
{23170,11585,-11585,-23170,-11585,11585,23170,11585,-11585,-23170,-11585,11585},
{23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170,0},
{23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585},
{23170,-20066,11585,0,-11585,20066,-23170,20066,-11585,0,11585,-20066},
{23170,-23170,23170,-23170,23170,-23170,23170,-23170,23170,-23170,23170,-23170},
{23170,-20066,11585,0,-11585,20066,-23170,20066,-11585,0,11585,-20066},
{23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585},
{23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170,0},
{23170,11585,-11585,-23170,-11585,11585,23170,11585,-11585,-23170,-11585,11585},
{23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585,0,11585,20066}
};
static const int16_t idft12_im[12][12] = {
{0,0,0,0,0,0,0,0,0,0,0,0},
{0,11585,20066,23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585},
{0,20066,20066,0,-20066,-20066,0,20066,20066,0,-20066,-20066},
{0,23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170},
{0,20066,-20066,0,20066,-20066,0,20066,-20066,0,20066,-20066},
{0,11585,-20066,23170,-20066,11585,0,-11585,20066,-23170,20066,-11585},
{0,0,0,0,0,0,0,0,0,0,0,0},
{0,-11585,20066,-23170,20066,-11585,0,11585,-20066,23170,-20066,11585},
{0,-20066,20066,0,-20066,20066,0,-20066,20066,0,-20066,20066},
{0,-23170,0,23170,0,-23170,0,23170,0,-23170,0,23170},
{0,-20066,-20066,0,20066,20066,0,-20066,-20066,0,20066,20066},
{0,-11585,-20066,-23170,-20066,-11585,0,11585,20066,23170,20066,11585}
};
void nr_decode_pucch0(PHY_VARS_gNB *gNB,
int frame,
@@ -1691,7 +1661,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
} // symb
// run polar decoder on llrs
decoderState = polar_decoder_int16((int16_t *)llrs, decodedPayload, 0, NR_POLAR_UCI_PUCCH_MESSAGE_TYPE, nb_bit, pucch_pdu->prb_size);
decoderState = polar_decoder_int16((int16_t *)llrs, decodedPayload, NULL, 0, NR_POLAR_UCI_PUCCH_MESSAGE_TYPE, nb_bit, pucch_pdu->prb_size);
LOG_D(PHY,"UCI decoderState %d, payload[0] %llu\n",decoderState,(unsigned long long)decodedPayload[0]);
if (decoderState>0) decoderState=1;

View File

@@ -44,6 +44,9 @@
#define CH_INTERP 0
#define NO_INTERP 1
// 10*log10(pow(2,30))
#define pow_2_30_dB 90
extern openair0_config_t openair0_cfg[];
/* Generic function to find the peak of channel estimation buffer */
void peak_estimator(int32_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t *peak_val)
{
@@ -608,7 +611,7 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
#endif
// generate pilot
nr_pbch_dmrs_rx(dmrss,ue->nr_gold_pbch[n_hf][ssb_index], &pilot[0]);
nr_pbch_dmrs_rx(dmrss,ue->nr_gold_pbch[n_hf][ssb_index], &pilot[0],0);
for (int aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
@@ -729,15 +732,18 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
}
int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
NR_DL_FRAME_PARMS *fp,
int estimateSz,
struct complex16 dl_ch_estimates[][estimateSz],
struct complex16 dl_ch_estimates_time[][ue->frame_parms.ofdm_symbol_size],
struct complex16 dl_ch_estimates_time[][fp->ofdm_symbol_size],
UE_nr_rxtx_proc_t *proc,
unsigned char symbol,
int dmrss,
uint8_t ssb_index,
uint8_t n_hf,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
c16_t rxdataF[][fp->samples_per_slot_wCP],
bool sidelink,
uint16_t Nid)
{
int Ns = proc->nr_slot_rx;
int pilot[200] __attribute__((aligned(16)));
@@ -748,25 +754,48 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
int ch_offset,symbol_offset;
//int slot_pbch;
uint8_t nushift;
nushift = ue->frame_parms.Nid_cell%4;
ue->frame_parms.nushift = nushift;
unsigned int ssb_offset = ue->frame_parms.first_carrier_offset + ue->frame_parms.ssb_start_subcarrier;
if (ssb_offset>= ue->frame_parms.ofdm_symbol_size) ssb_offset-=ue->frame_parms.ofdm_symbol_size;
uint8_t nushift = 0, lastsymbol = 0;
ch_offset = ue->frame_parms.ofdm_symbol_size*symbol;
uint32_t *gold_seq = NULL;
AssertFatal(dmrss >= 0 && dmrss < 3,
if (sidelink) {
AssertFatal(dmrss == 0 || (dmrss >= 5 && dmrss <= 12),
"symbol %d is illegal for PSBCH DM-RS \n",
dmrss);
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
LOG_D(PHY,"PSBCH Channel Estimation SLSSID:%d\n", Nid);
gold_seq = sl_phy_params->init_params.psbch_dmrs_gold_sequences[Nid];
lastsymbol = 12;
} else {
nushift = fp->Nid_cell%4;
fp->nushift = nushift;
AssertFatal(dmrss >= 0 && dmrss < 3,
"symbol %d is illegal for PBCH DM-RS \n",
dmrss);
symbol_offset = ue->frame_parms.ofdm_symbol_size*symbol;
gold_seq = ue->nr_gold_pbch[n_hf][ssb_index];
lastsymbol = 2;
}
unsigned int ssb_offset = fp->first_carrier_offset + fp->ssb_start_subcarrier;
if (ssb_offset>= fp->ofdm_symbol_size) ssb_offset-= fp->ofdm_symbol_size;
ch_offset = fp->ofdm_symbol_size*symbol;
symbol_offset = fp->ofdm_symbol_size*symbol;
k = nushift;
#ifdef DEBUG_PBCH
printf("PBCH Channel Estimation : gNB_id %d ch_offset %d, OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n", proc->gNB_id, ch_offset, ue->frame_parms.ofdm_symbol_size, ue->frame_parms.Ncp, Ns, k, symbol);
printf("PBCH Channel Estimation : gNB_id %d ch_offset %d, OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n", proc->gNB_id, ch_offset, fp->ofdm_symbol_size, fp->Ncp, Ns, k, symbol);
#endif
switch (k) {
@@ -802,7 +831,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
idft_size_idx_t idftsizeidx;
switch (ue->frame_parms.ofdm_symbol_size) {
switch (fp->ofdm_symbol_size) {
case 128:
idftsizeidx = IDFT_128;
break;
@@ -849,20 +878,20 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
}
// generate pilot
nr_pbch_dmrs_rx(dmrss,ue->nr_gold_pbch[n_hf][ssb_index], &pilot[0]);
nr_pbch_dmrs_rx(dmrss,gold_seq, &pilot[0], sidelink);
for (int aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
for (int aarx=0; aarx<fp->nb_antennas_rx; aarx++) {
int re_offset = ssb_offset;
pil = (int16_t *)&pilot[0];
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
dl_ch = (int16_t *)&dl_ch_estimates[aarx][ch_offset];
memset(dl_ch,0,sizeof(struct complex16)*(ue->frame_parms.ofdm_symbol_size));
memset(dl_ch,0,sizeof(struct complex16)*(fp->ofdm_symbol_size));
#ifdef DEBUG_PBCH
printf("pbch ch est pilot addr %p RB_DL %d\n",&pilot[0], ue->frame_parms.N_RB_DL);
printf("k %d, first_carrier %d\n",k,ue->frame_parms.first_carrier_offset);
printf("pbch ch est pilot addr %p RB_DL %d\n",&pilot[0], fp->N_RB_DL);
printf("k %d, first_carrier %d\n",k,fp->first_carrier_offset);
printf("rxF addr %p\n", rxF);
printf("dl_ch addr %p\n",dl_ch);
#endif
@@ -881,7 +910,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
dl_ch,
16);
pil += 2;
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
re_offset = (re_offset+4) % fp->ofdm_symbol_size;
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
//for (int i= 0; i<8; i++)
@@ -899,7 +928,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
dl_ch,
16);
pil += 2;
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
re_offset = (re_offset+4) % fp->ofdm_symbol_size;
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
@@ -914,7 +943,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
dl_ch,
16);
pil += 2;
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
re_offset = (re_offset+4) % fp->ofdm_symbol_size;
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
dl_ch += 24;
@@ -926,7 +955,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
// in 2nd symbol, skip middle REs (48 with DMRS, 144 for SSS, and another 48 with DMRS)
if (dmrss == 1 && pilot_cnt == 12) {
pilot_cnt=48;
re_offset = (re_offset+144) % ue->frame_parms.ofdm_symbol_size;
re_offset = (re_offset+144) % fp->ofdm_symbol_size;
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
dl_ch += 288;
}
@@ -945,7 +974,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
// printf("pilot_cnt %d dl_ch %d %d\n", pilot_cnt, dl_ch+i, *(dl_ch+i));
pil += 2;
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
re_offset = (re_offset+4) % fp->ofdm_symbol_size;
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
@@ -960,7 +989,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
dl_ch,
16);
pil += 2;
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
re_offset = (re_offset+4) % fp->ofdm_symbol_size;
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
@@ -975,13 +1004,13 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
dl_ch,
16);
pil += 2;
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
re_offset = (re_offset+4) % fp->ofdm_symbol_size;
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
dl_ch += 24;
}
if( dmrss == 2) // update time statistics for last PBCH symbol
if( dmrss == lastsymbol) // update time statistics for last PBCH symbol
{
// do ifft of channel estimate
LOG_D(PHY,"Channel Impulse Computation Slot %d Symbol %d ch_offset %d\n", Ns, symbol, ch_offset);
@@ -992,27 +1021,34 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
}
}
if (dmrss == 2)
if (dmrss == lastsymbol) {
enum scopeDataType typ = (sidelink) ? psbchDlChEstimateTime
: pbchDlChEstimateTime;
UEscopeCopy(ue,
pbchDlChEstimateTime,
typ,
(void *)dl_ch_estimates_time,
sizeof(c16_t),
ue->frame_parms.nb_antennas_rx,
ue->frame_parms.ofdm_symbol_size,
fp->nb_antennas_rx,
fp->ofdm_symbol_size,
0);
}
return(0);
}
void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
int pscch_flag,
unsigned char symbol,
fapi_nr_coreset_t *coreset,
uint16_t first_carrier_offset,
uint16_t BWPStart,
int32_t pdcch_est_size,
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
int16_t *rsrp_dBm)
{
int Ns = proc->nr_slot_rx;
@@ -1022,6 +1058,9 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
unsigned int pilot_cnt;
int16_t ch[2],*pil,*rxF,*dl_ch;
int ch_offset,symbol_offset;
uint16_t meas_count = 0;
int32_t rsrp_sum = 0;
int rsrp = 0;
ch_offset = ue->frame_parms.ofdm_symbol_size*symbol;
@@ -1029,12 +1068,16 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
int nb_rb_coreset=0;
int coreset_start_rb=0;
get_coreset_rballoc(coreset->frequency_domain_resource,&nb_rb_coreset,&coreset_start_rb);
if (pscch_flag == 0) get_coreset_rballoc(coreset->frequency_domain_resource,&nb_rb_coreset,&coreset_start_rb);
else {
coreset_start_rb = coreset->frequency_domain_resource[0];
nb_rb_coreset = coreset->frequency_domain_resource[1];
}
if(nb_rb_coreset==0) return;
#ifdef DEBUG_PDCCH
printf("pdcch_channel_estimation: first_carrier_offset %d, BWPStart %d, coreset_start_rb %d, coreset_nb_rb %d\n",
first_carrier_offset, BWPStart, coreset_start_rb, nb_rb_coreset);
printf("pdcch_channel_estimation: first_carrier_offset %d, BWPStart %d, coreset_start_rb %d, coreset_nb_rb %d, symbold %d\n",
first_carrier_offset, BWPStart, coreset_start_rb, nb_rb_coreset,symbol);
#endif
unsigned short coreset_start_subcarrier = first_carrier_offset+(BWPStart + coreset_start_rb)*12;
@@ -1052,17 +1095,20 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
unsigned short scrambling_id = coreset->pdcch_dmrs_scrambling_id;
// checking if re-initialization of scrambling IDs is needed (should be done here but scrambling ID for PDCCH is not taken from RRC)
if (scrambling_id != ue->scramblingID_pdcch){
if (pscch_flag == 0 && scrambling_id != ue->scramblingID_pdcch){
ue->scramblingID_pdcch = scrambling_id;
nr_gold_pdcch(ue,ue->scramblingID_pdcch);
nr_gold_pdcch(&ue->frame_parms,ue->nr_gold_pdcch[gNB_id],ue->scramblingID_pdcch);
}
int dmrs_ref = 0;
if (coreset->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG)
dmrs_ref = BWPStart;
// generate pilot
int pilot[(nb_rb_coreset + dmrs_ref) * 3] __attribute__((aligned(16)));
nr_pdcch_dmrs_rx(ue,Ns,ue->nr_gold_pdcch[gNB_id][Ns][symbol], &pilot[0],2000,(nb_rb_coreset+dmrs_ref));
if (pscch_flag ==0)
nr_pdcch_dmrs_rx(ue,Ns,ue->nr_gold_pdcch[gNB_id][Ns][symbol], &pilot[0],2000,(nb_rb_coreset+dmrs_ref));
else
nr_pdcch_dmrs_rx(ue,Ns,ue->nr_gold_pscch[Ns][symbol], &pilot[0],2000,(nb_rb_coreset+dmrs_ref));
for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
@@ -1212,6 +1258,8 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
#else //ELSE CH_INTERP
int ch_sum[2] = {0, 0};
c16_t rx_signal = rxdataF[aarx][(symbol_offset + k + 1)];
for (pilot_cnt = 0; pilot_cnt < 3*nb_rb_coreset; pilot_cnt++) {
if (k >= ue->frame_parms.ofdm_symbol_size) {
k -= ue->frame_parms.ofdm_symbol_size;
@@ -1220,11 +1268,15 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
#ifdef DEBUG_PDCCH
printf("pilot[%u] = (%d, %d)\trxF[%d] = (%d, %d)\n", pilot_cnt, pil[0], pil[1], k+1, rxF[0], rxF[1]);
#endif
rsrp_sum += (((int32_t)(rx_signal.r) * rx_signal.r) + ((int32_t)(rx_signal.i) * rx_signal.i));
LOG_D(NR_PHY, "r: %d, i: %d, k %d, offset %d\n", rx_signal.r, rx_signal.i, k, (symbol_offset + k + 1));
meas_count++;
ch_sum[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
ch_sum[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
pil += 2;
rxF += 8;
k += 4;
rx_signal = rxdataF[aarx][(symbol_offset + k + 1)];
if (pilot_cnt % 3 == 2) {
ch[0] = ch_sum[0] / 3;
@@ -1245,6 +1297,11 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
//}
}
rsrp = rsrp_sum / meas_count;
*rsrp_dBm = dB_fixed(rsrp) + 30 - pow_2_30_dB
- ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size);
LOG_D(NR_PHY, "%4d.%2d rsrp %d, rsrp_dBm %d, rsrp_sum %d, meas_count %d\n", proc->frame_rx, proc->nr_slot_rx, rsrp, *rsrp_dBm, rsrp_sum, meas_count);
}
void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms,

View File

@@ -52,13 +52,15 @@ void peak_estimator(int32_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t
*/
void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
int pscch_flag,
unsigned char symbol,
fapi_nr_coreset_t *coreset,
uint16_t first_carrier_offset,
uint16_t BWPStart,
int32_t pdcch_est_size,
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
int16_t* rsrp_dBm);
int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
@@ -68,15 +70,18 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
NR_DL_FRAME_PARMS *fp,
int estimateSz,
struct complex16 dl_ch_estimates[][estimateSz],
struct complex16 dl_ch_estimates_time[][ue->frame_parms.ofdm_symbol_size],
struct complex16 dl_ch_estimates_time[][fp->ofdm_symbol_size],
UE_nr_rxtx_proc_t *proc,
unsigned char symbol,
int dmrss,
uint8_t ssb_index,
uint8_t n_hf,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
c16_t rxdataF[][fp->samples_per_slot_wCP],
bool sidelink,
uint16_t Nid);
int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
@@ -141,4 +146,9 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
float_t get_nr_RSRP(module_id_t Mod_id,uint8_t CC_id,uint8_t gNB_index);
void nr_sl_psbch_rsrp_measurements(sl_nr_ue_phy_params_t *sl_phy_params,
NR_DL_FRAME_PARMS *fp,
c16_t rxdataF[][fp->samples_per_slot_wCP],
bool use_SSS);
#endif

View File

@@ -313,3 +313,56 @@ void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue,
ue->measurements.n0_power_tot_dB + 30 - 10*log10(pow(2, 30)) - dB_fixed(ue->frame_parms.ofdm_symbol_size) - ((int)rx_gain - (int)rx_gain_offset));
}
//PSBCH RSRP calculations according to 38.215 section 5.1.22
void nr_sl_psbch_rsrp_measurements(sl_nr_ue_phy_params_t *sl_phy_params,
NR_DL_FRAME_PARMS *fp,
c16_t rxdataF[][fp->samples_per_slot_wCP],
bool use_SSS)
{
SL_NR_UE_PSBCH_t *psbch_rx = &sl_phy_params->psbch;
uint8_t numsym = (fp->Ncp) ? SL_NR_NUM_SYMBOLS_SSB_EXT_CP
: SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP;
uint32_t re_offset = fp->first_carrier_offset + fp->ssb_start_subcarrier;
uint32_t rsrp = 0, num_re = 0;
LOG_D(PHY, "PSBCH RSRP MEAS: numsym:%d, re_offset:%d\n",numsym, re_offset);
for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++) {
//Calculate PSBCH RSRP based from DMRS REs
for (uint8_t symbol=0; symbol<numsym;) {
struct complex16 *rxF = &rxdataF[aarx][symbol*fp->ofdm_symbol_size];
for (int re=0;re<SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL;re++) {
if (re%4 == 0) { //DMRS RE
uint16_t offset = (re_offset + re) % fp->ofdm_symbol_size;
rsrp += rxF[offset].r*rxF[offset].r + rxF[offset].i*rxF[offset].i;
num_re++;
}
}
symbol = (symbol == 0) ? 5 : symbol+1;
}
}
if (use_SSS) {
//TBD...
//UE can decide between using only PSBCH DMRS or PSBCH DMRS and SSS for PSBCH RSRP computation.
//If needed this can be implemented. Reference Spec 38.215
}
psbch_rx->rsrp_dB_per_RE = 10*log10(rsrp / num_re);
psbch_rx->rsrp_dBm_per_RE = psbch_rx->rsrp_dB_per_RE +
30 - 10*log10(pow(2,30)) -
((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) -
dB_fixed(fp->ofdm_symbol_size);
LOG_D(PHY, "PSBCH RSRP (DMRS REs): numREs:%d RSRP :%d dB/RE ,RSRP:%d dBm/RE\n",
num_re, psbch_rx->rsrp_dB_per_RE, psbch_rx->rsrp_dBm_per_RE);
}

View File

@@ -39,14 +39,15 @@
#include "common/utils/nr/nr_common.h"
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
#include "PHY/NR_UE_ESTIMATION/filt16a_32.h"
#include "executables/nr-uesoftmodem.h"
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
// 10*log10(pow(2,30))
#define pow_2_30_dB 90
// Additional memory allocation, because of applying the filter and the memory offset to ensure memory alignment
#define FILTER_MARGIN 32
//#define NR_CSIRS_DEBUG
// #define DEBUG_CSI_PRINTS // To enable CSI SNR debug logs
extern short nr_qpsk_mod_table[8];
// #define NR_CSIRS_DEBUG
#define METRICS
//#define NR_CSIIM_DEBUG
void nr_det_A_MF_2x2(int32_t *a_mf_00,
@@ -205,7 +206,7 @@ int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue,
for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) {
// for freq density 0.5 checks if even or odd RB
if(csirs_config_pdu->freq_density <= 1 && csirs_config_pdu->freq_density != (rb % 2)) {
if(csirs_config_pdu->freq_density <= 1 && get_softmodem_params()->sl_mode ? 0 : csirs_config_pdu->freq_density != (rb % 2)) {
continue;
}
@@ -230,12 +231,12 @@ int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue,
((int32_t)(rx_csi_rs_signal[k].i)*rx_csi_rs_signal[k].i));
meas_count++;
LOG_D(NR_PHY, "RX CSI-RS symbol_offset %li k %i symbol_offset+k=%li\n", symbol_offset, k, symbol_offset+k);
#ifdef NR_CSIRS_DEBUG
int dataF_offset = proc->nr_slot_rx*ue->frame_parms.samples_per_slot_wCP;
int dataF_offset = get_softmodem_params()->sl_mode == 2 ? 0 : proc->nr_slot_rx * ue->frame_parms.samples_per_slot_wCP;
uint16_t port_tx = s+j_cdm[cdm_id]*CDM_group_size;
c16_t *tx_csi_rs_signal = (c16_t*)&nr_csi_info->csi_rs_generated_signal[port_tx][symbol_offset+dataF_offset];
LOG_I(NR_PHY, "l,k (%2d,%4d) |\tport_tx %d (%4d,%4d)\tant_rx %d (%4d,%4d)\n",
LOG_D(NR_PHY, "l,k (%2d,%4d) |\tport_tx %d (%4d,%4d)\tant_rx %d (%4d,%4d)\n",
symb,
k,
port_tx+3000,
@@ -257,7 +258,7 @@ int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue,
*rsrp_dBm = dB_fixed(*rsrp) + 30 - pow_2_30_dB
- ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size);
#ifdef NR_CSIRS_DEBUG
#ifdef METRICS
LOG_I(NR_PHY, "RSRP = %i (%i dBm)\n", *rsrp, *rsrp_dBm);
#endif
@@ -270,7 +271,7 @@ uint32_t calc_power_csirs(const uint16_t *x, const fapi_nr_dl_config_csirs_pdu_r
uint64_t sum_x2 = 0;
uint16_t size = 0;
for (int rb = 0; rb < csirs_config_pdu->nr_of_rbs; rb++) {
if (csirs_config_pdu->freq_density <= 1 && csirs_config_pdu->freq_density != ((rb + csirs_config_pdu->start_rb) % 2)) {
if (csirs_config_pdu->freq_density <= 1 && get_softmodem_params()->sl_mode ? 0 : csirs_config_pdu->freq_density != ((rb + csirs_config_pdu->start_rb) % 2)) {
continue;
}
sum_x = sum_x + x[rb];
@@ -300,9 +301,8 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
int16_t *log2_re,
int16_t *log2_maxh,
uint32_t *noise_power) {
const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
const int dataF_offset = proc->nr_slot_rx*ue->frame_parms.samples_per_slot_wCP;
const int dataF_offset = get_softmodem_params()->sl_mode == 2 ? 0 : proc->nr_slot_rx * ue->frame_parms.samples_per_slot_wCP;
*noise_power = 0;
int maxh = 0;
int count = 0;
@@ -318,7 +318,7 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) {
// for freq density 0.5 checks if even or odd RB
if(csirs_config_pdu->freq_density <= 1 && csirs_config_pdu->freq_density != (rb % 2)) {
if(csirs_config_pdu->freq_density <= 1 && get_softmodem_params()->sl_mode ? 0 : csirs_config_pdu->freq_density != (rb % 2)) {
continue;
}
@@ -360,19 +360,19 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
continue;
}
for(int k = 0; k<frame_parms->ofdm_symbol_size; k++) {
LOG_I(NR_PHY, "l,k (%2d,%4d) | ", symb, k);
LOG_D(NR_PHY, "l,k (%2d,%4d) | ", symb, k);
for(uint16_t port_tx = 0; port_tx<N_ports; port_tx++) {
uint64_t symbol_offset = symb*frame_parms->ofdm_symbol_size;
c16_t *tx_csi_rs_signal = (c16_t*)&csi_rs_generated_signal[port_tx][symbol_offset+dataF_offset];
c16_t *rx_csi_rs_signal = (c16_t*)&csi_rs_received_signal[ant_rx][symbol_offset];
c16_t *csi_rs_ls_estimated_channel16 = (c16_t*)&csi_rs_ls_estimated_channel[ant_rx][port_tx][0];
printf("port_tx %d --> ant_rx %d, tx (%4d,%4d), rx (%4d,%4d), ls (%4d,%4d) | ",
port_tx+3000, ant_rx,
tx_csi_rs_signal[k].r, tx_csi_rs_signal[k].i,
rx_csi_rs_signal[k].r, rx_csi_rs_signal[k].i,
csi_rs_ls_estimated_channel16[k].r, csi_rs_ls_estimated_channel16[k].i);
// printf("port_tx %d --> ant_rx %d, tx (%4d,%4d), rx (%4d,%4d), ls (%4d,%4d) | ",
// port_tx+3000, ant_rx,
// tx_csi_rs_signal[k].r, tx_csi_rs_signal[k].i,
// rx_csi_rs_signal[k].r, rx_csi_rs_signal[k].i,
// csi_rs_ls_estimated_channel16[k].r, csi_rs_ls_estimated_channel16[k].i);
}
printf("\n");
// printf("\n");
}
}
#endif
@@ -386,7 +386,7 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) {
// for freq density 0.5 checks if even or odd RB
if(csirs_config_pdu->freq_density <= 1 && csirs_config_pdu->freq_density != (rb % 2)) {
if(csirs_config_pdu->freq_density <= 1 && get_softmodem_params()->sl_mode ? 0 : csirs_config_pdu->freq_density != (rb % 2)) {
continue;
}
@@ -412,7 +412,7 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
uint16_t noise_real[frame_parms->nb_antennas_rx][N_ports][csirs_config_pdu->nr_of_rbs];
uint16_t noise_imag[frame_parms->nb_antennas_rx][N_ports][csirs_config_pdu->nr_of_rbs];
for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) {
if (csirs_config_pdu->freq_density <= 1 && csirs_config_pdu->freq_density != (rb % 2)) {
if (csirs_config_pdu->freq_density <= 1 && get_softmodem_params()->sl_mode ? 0 : csirs_config_pdu->freq_density != (rb % 2)) {
continue;
}
uint16_t k = (frame_parms->first_carrier_offset + rb*NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size;
@@ -425,8 +425,9 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
maxh = cmax3(maxh, abs(csi_rs_estimated_channel16->r), abs(csi_rs_estimated_channel16->i));
}
}
for(uint16_t port_tx = 0; port_tx<N_ports; port_tx++) {
*noise_power += (calc_power_csirs(noise_real[ant_rx][port_tx], csirs_config_pdu) + calc_power_csirs(noise_imag[ant_rx][port_tx],csirs_config_pdu));
*noise_power += (calc_power_csirs(noise_real[ant_rx][port_tx], csirs_config_pdu) + calc_power_csirs(noise_imag[ant_rx][port_tx], csirs_config_pdu));
}
#ifdef NR_CSIRS_DEBUG
@@ -434,18 +435,18 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
int rb = k >= frame_parms->first_carrier_offset ?
(k - frame_parms->first_carrier_offset)/NR_NB_SC_PER_RB :
(k + frame_parms->ofdm_symbol_size - frame_parms->first_carrier_offset)/NR_NB_SC_PER_RB;
LOG_I(NR_PHY, "(k = %4d) |\t", k);
LOG_D(NR_PHY, "(k = %4d) |\t", k);
for(uint16_t port_tx = 0; port_tx<N_ports; port_tx++) {
c16_t *csi_rs_ls_estimated_channel16 = (c16_t*)&csi_rs_ls_estimated_channel[ant_rx][port_tx][0];
c16_t *csi_rs_estimated_channel16 = (c16_t *)&csi_rs_estimated_channel_freq[ant_rx][port_tx][mem_offset];
printf("Channel port_tx %d --> ant_rx %d : ls (%4d,%4d), int (%4d,%4d), noise (%4d,%4d) | ",
port_tx+3000, ant_rx,
csi_rs_ls_estimated_channel16[k].r, csi_rs_ls_estimated_channel16[k].i,
csi_rs_estimated_channel16[k].r, csi_rs_estimated_channel16[k].i,
rb >= csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs ? 0 : noise_real[ant_rx][port_tx][rb-csirs_config_pdu->start_rb],
rb >= csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs ? 0 : noise_imag[ant_rx][port_tx][rb-csirs_config_pdu->start_rb]);
// printf("Channel port_tx %d --> ant_rx %d : ls (%4d,%4d), int (%4d,%4d), noise (%4d,%4d) | ",
// port_tx+3000, ant_rx,
// csi_rs_ls_estimated_channel16[k].r, csi_rs_ls_estimated_channel16[k].i,
// csi_rs_estimated_channel16[k].r, csi_rs_estimated_channel16[k].i,
// rb >= csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs ? 0 : noise_real[ant_rx][port_tx][rb-csirs_config_pdu->start_rb],
// rb >= csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs ? 0 : noise_imag[ant_rx][port_tx][rb-csirs_config_pdu->start_rb]);
}
printf("\n");
// printf("\n");
}
#endif
@@ -634,7 +635,7 @@ int nr_csi_rs_pmi_estimation(const PHY_VARS_NR_UE *ue,
for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) {
if (csirs_config_pdu->freq_density <= 1 && csirs_config_pdu->freq_density != (rb % 2)) {
if (csirs_config_pdu->freq_density <= 1 && get_softmodem_params()->sl_mode ? 0 : csirs_config_pdu->freq_density != (rb % 2)) {
continue;
}
uint16_t k = (frame_parms->first_carrier_offset + rb * NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size;
@@ -697,6 +698,53 @@ int nr_csi_rs_pmi_estimation(const PHY_VARS_NR_UE *ue,
return 0;
}
int nr_csi_rs_sinr_estimation(const PHY_VARS_NR_UE *ue,
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
const uint8_t N_ports,
uint8_t mem_offset,
const int32_t csi_rs_estimated_channel_freq[][N_ports][ue->frame_parms.ofdm_symbol_size + FILTER_MARGIN],
const uint32_t interference_plus_noise_power,
const int16_t log2_re,
int32_t *precoded_sinr_dB) {
const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
if (interference_plus_noise_power == 0) {
*precoded_sinr_dB = 0;
return 0;
}
int32_t sum_re = 0;
int32_t sum_im = 0;
int32_t sum2_re = 0;
int32_t sum2_im = 0;
int32_t tested_precoded_sinr = 0;
for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) {
if (csirs_config_pdu->freq_density <= 1 && get_softmodem_params()->sl_mode ? 0 : csirs_config_pdu->freq_density != (rb % 2)) {
continue;
}
uint16_t k = (frame_parms->first_carrier_offset + rb * NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size;
uint16_t k_offset = k + mem_offset;
for (int ant_rx = 0; ant_rx < frame_parms->nb_antennas_rx; ant_rx++) {
c16_t *csi_rs_estimated_channel_p = (c16_t *) &csi_rs_estimated_channel_freq[ant_rx][0][k_offset];
sum_re += csi_rs_estimated_channel_p->r;
sum_im += csi_rs_estimated_channel_p->i;
sum2_re += (csi_rs_estimated_channel_p->r * csi_rs_estimated_channel_p->r) >> log2_re;
sum2_im += (csi_rs_estimated_channel_p->i * csi_rs_estimated_channel_p->i) >> log2_re;
}
}
int32_t power_re = sum2_re - (sum_re >> log2_re) * (sum_re >> log2_re);
int32_t power_im = sum2_im - (sum_im >> log2_re) * (sum_im >> log2_re);
tested_precoded_sinr = (power_re + power_im) / (int32_t)interference_plus_noise_power;
*precoded_sinr_dB = dB_fixed(tested_precoded_sinr);
return 0;
}
int nr_csi_rs_cqi_estimation(const uint32_t precoded_sinr,
uint8_t *cqi) {
@@ -809,6 +857,46 @@ int nr_csi_im_power_estimation(const PHY_VARS_NR_UE *ue,
return 0;
}
int nr_csi_rs_cqi_estimation_sl(const int32_t precoded_sinr,
uint8_t *cqi) {
*cqi = 0;
if (precoded_sinr >= -20 && precoded_sinr < -6) {
*cqi = 1;
} else if(precoded_sinr >= -6 && precoded_sinr < -3) {
*cqi = 2;
} else if(precoded_sinr >= -3 && precoded_sinr <= 0) {
*cqi = 3;
// Default SINR table for an AWGN channel for SISO scenario, considering 0.1 BLER condition and TS 38.214 Table 5.2.2.1-2
} else if(precoded_sinr > 0 && precoded_sinr <= 2) {
*cqi = 4;
} else if(precoded_sinr == 3) {
*cqi = 5;
} else if(precoded_sinr > 3 && precoded_sinr <= 5) {
*cqi = 6;
} else if(precoded_sinr > 5 && precoded_sinr <= 7) {
*cqi = 7;
} else if(precoded_sinr > 7 && precoded_sinr <= 9) {
*cqi = 8;
} else if(precoded_sinr == 10) {
*cqi = 9;
} else if(precoded_sinr > 10 && precoded_sinr <= 12) {
*cqi = 10;
} else if(precoded_sinr > 12 && precoded_sinr <= 15) {
*cqi = 11;
} else if(precoded_sinr == 16) {
*cqi = 12;
} else if(precoded_sinr > 16 && precoded_sinr <= 18) {
*cqi = 13;
} else if(precoded_sinr == 19) {
*cqi = 14;
} else if(precoded_sinr > 19) {
*cqi = 15;
}
return 0;
}
int nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
int gNB_id = proc->gNB_id;
@@ -836,13 +924,13 @@ int nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t r
void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
{
int gNB_id = proc->gNB_id;
if(!ue->csirs_vars[gNB_id]->active) {
// TODO: check the id whether it is working for multiple UEs
int id = get_softmodem_params()->sl_mode == 2 ? 0 : proc->gNB_id;
if (!ue->csirs_vars[id]->active) {
return;
}
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu = (fapi_nr_dl_config_csirs_pdu_rel15_t*)&ue->csirs_vars[gNB_id]->csirs_config_pdu;
fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu = (fapi_nr_dl_config_csirs_pdu_rel15_t*)&ue->csirs_vars[id]->csirs_config_pdu;
#ifdef NR_CSIRS_DEBUG
LOG_I(NR_PHY, "csirs_config_pdu->subcarrier_spacing = %i\n", csirs_config_pdu->subcarrier_spacing);
@@ -883,13 +971,20 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t
uint32_t noise_power = 0;
uint8_t rank_indicator = 0;
uint32_t precoded_sinr_dB = 0;
int32_t sl_sinr_dB = 0;
uint8_t cqi = 0;
uint8_t i1[3];
uint8_t i2[1];
uint8_t num_of_layers = min(get_nrUE_params()->nb_antennas_tx, get_nrUE_params()->nb_antennas_rx);
AssertFatal(num_of_layers > 0, "Number of layers MUST be greater than zero!!!");
uint16_t beta_csirs = get_softmodem_params()->sl_mode ? (uint16_t)(AMP * (ceil(sqrt(num_of_layers / frame_parms->nb_antennas_tx)))) & 0xFFFF : AMP;
csirs_config_pdu->scramb_id = ue->slsch[0].harq_process->pssch_pdu->Nid % (1 << 10);
LOG_D(NR_PHY, "Rx beta_csirs: %d, scramb_id %i, frame.slot (%d.%d)\n", beta_csirs, csirs_config_pdu->scramb_id, proc->frame_rx, proc->nr_slot_rx);
nr_generate_csi_rs(frame_parms,
ue->nr_csi_info->csi_rs_generated_signal,
AMP,
beta_csirs,
ue->nr_csi_info,
(nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *) csirs_config_pdu,
proc->nr_slot_rx,
@@ -964,22 +1059,43 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t
// bit 3 in bitmap to indicate RI measurment
if (csirs_config_pdu->measurement_bitmap & 8) {
nr_csi_rs_pmi_estimation(ue,
csirs_config_pdu,
ue->nr_csi_info,
N_ports,
mem_offset,
csi_rs_estimated_channel_freq,
ue->nr_csi_info->csi_im_meas_computed ? ue->nr_csi_info->interference_plus_noise_power : noise_power,
rank_indicator,
log2_re,
i1,
i2,
&precoded_sinr_dB);
// Sidelink mode 2 considers only one port (for now), in case of N_ports = 2, we need to revisit
if (N_ports >= 2)
nr_csi_rs_pmi_estimation(ue,
csirs_config_pdu,
ue->nr_csi_info,
N_ports,
mem_offset,
csi_rs_estimated_channel_freq,
ue->nr_csi_info->csi_im_meas_computed ? ue->nr_csi_info->interference_plus_noise_power : noise_power,
rank_indicator,
log2_re,
i1,
i2,
&precoded_sinr_dB);
else
nr_csi_rs_sinr_estimation(ue,
csirs_config_pdu,
N_ports,
mem_offset,
csi_rs_estimated_channel_freq,
noise_power,
log2_re,
&sl_sinr_dB);
// bit 4 in bitmap to indicate RI measurment
if(csirs_config_pdu->measurement_bitmap & 16)
nr_csi_rs_cqi_estimation(precoded_sinr_dB, &cqi);
if (csirs_config_pdu->measurement_bitmap & 16) {
if (get_softmodem_params()->sl_mode == 2) {
nr_csi_rs_cqi_estimation_sl(sl_sinr_dB, &cqi);
get_nrUE_params()->snr = sl_sinr_dB;
LOG_I(NR_PHY, "Rx CSI-RS %4d.%2d sl_sinr %i rsrp %d dBm cqi %d\n",
proc->frame_rx, proc->nr_slot_rx, sl_sinr_dB, rsrp_dBm, cqi);
} else {
nr_csi_rs_cqi_estimation(precoded_sinr_dB, &cqi);
LOG_I(NR_PHY, "Rx %4d.%2d snr %u rsrp %d dBm cqi %d\n",
proc->frame_rx, proc->nr_slot_rx, precoded_sinr_dB, rsrp_dBm, cqi);
}
}
}
switch (csirs_config_pdu->measurement_bitmap) {
@@ -991,7 +1107,7 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t
rank_indicator + 1, i1[0], i1[1], i1[2], i2[0], precoded_sinr_dB, cqi);
break;
case 27 :
LOG_I(NR_PHY, "RSRP = %i dBm, RI = %i i1 = %i.%i.%i, i2 = %i, SINR = %i dB, CQI = %i\n",
LOG_D(NR_PHY, "RSRP = %i dBm, RI = %i i1 = %i.%i.%i, i2 = %i, SINR = %i dB, CQI = %i\n",
rsrp_dBm, rank_indicator + 1, i1[0], i1[1], i1[2], i2[0], precoded_sinr_dB, cqi);
break;
default :

View File

@@ -79,7 +79,8 @@ char nr_dci_format_string[8][30] = {
//static const int16_t conjugate[8]__attribute__((aligned(32))) = {-1,1,-1,1,-1,1,-1,1};
static void nr_pdcch_demapping_deinterleaving(uint32_t *llr,
static void nr_pdcch_demapping_deinterleaving(int pscch_flag,
uint32_t *llr,
uint32_t *e_rx,
uint8_t coreset_time_dur,
uint8_t start_symbol,
@@ -146,7 +147,7 @@ static void nr_pdcch_demapping_deinterleaving(uint32_t *llr,
int max_bundles = n_cce * num_bundles_per_cce;
int f_bundle_j_list[max_bundles];
// for each bundle
for (int nb = 0; nb < max_bundles; nb++) {
for (int nb = 0; nb < max_bundles && pscch_flag==0; nb++) {
if (coreset_interleaved == 0)
f_bundle_j = nb;
else {
@@ -162,7 +163,7 @@ static void nr_pdcch_demapping_deinterleaving(uint32_t *llr,
// Get cce_list indices by bundle index in ascending order
int f_bundle_j_list_ord[number_of_candidates][max_bundles];
for (int c_id = 0; c_id < number_of_candidates; c_id++ ) {
for (int c_id = 0; c_id < number_of_candidates && pscch_flag==0; c_id++ ) {
int start_bund_cand = CCE[c_id] * num_bundles_per_cce;
int max_bund_per_cand = L[c_id] * num_bundles_per_cce;
int f_bundle_j_list_id = 0;
@@ -181,23 +182,28 @@ static void nr_pdcch_demapping_deinterleaving(uint32_t *llr,
int data_sc = 9; // 9 sub-carriers with data per PRB
for (int c_id = 0; c_id < number_of_candidates; c_id++ ) {
for (int symbol_idx = start_symbol; symbol_idx < start_symbol+coreset_time_dur; symbol_idx++) {
for (int cce_count = 0; cce_count < L[c_id]; cce_count ++) {
for (int k=0; k<NR_NB_REG_PER_CCE/reg_bundle_size_L; k++) { // loop over REG bundles
int f = f_bundle_j_list_ord[c_id][k+NR_NB_REG_PER_CCE*cce_count/reg_bundle_size_L];
for(int rb=0; rb<B_rb; rb++) { // loop over the RBs of the bundle
index_z = data_sc * rb_count;
index_llr = (uint16_t) (f*B_rb + rb + symbol_idx * coreset_nbr_rb) * data_sc;
for (int i = 0; i < data_sc; i++) {
e_rx[index_z + i] = llr[index_llr + i];
if (pscch_flag == 0) {
for (int cce_count = 0; cce_count < L[c_id]; cce_count ++) {
for (int k=0; k<NR_NB_REG_PER_CCE/reg_bundle_size_L; k++) { // loop over REG bundles
int f = f_bundle_j_list_ord[c_id][k+NR_NB_REG_PER_CCE*cce_count/reg_bundle_size_L];
for(int rb=0; rb<B_rb; rb++) { // loop over the RBs of the bundle
index_z = data_sc * rb_count;
index_llr = (uint16_t) (f*B_rb + rb + symbol_idx * coreset_nbr_rb) * data_sc;
for (int i = 0; i < data_sc; i++) {
e_rx[index_z + i] = llr[index_llr + i];
#ifdef NR_PDCCH_DCI_DEBUG
LOG_I(PHY,"[candidate=%d,symbol_idx=%d,cce=%d,REG bundle=%d,PRB=%d] z[%d]=(%d,%d) <-> \t llr[%d]=(%d,%d) \n",
c_id,symbol_idx,cce_count,k,f*B_rb + rb,(index_z + i),*(int16_t *) &e_rx[index_z + i],*(1 + (int16_t *) &e_rx[index_z + i]),
(index_llr + i),*(int16_t *) &llr[index_llr + i], *(1 + (int16_t *) &llr[index_llr + i]));
LOG_I(PHY,"[candidate=%d,symbol_idx=%d,cce=%d,REG bundle=%d,PRB=%d] z[%d]=(%d,%d) <-> \t llr[%d]=(%d,%d) \n",
c_id,symbol_idx,cce_count,k,f*B_rb + rb,(index_z + i),*(int16_t *) &e_rx[index_z + i],*(1 + (int16_t *) &e_rx[index_z + i]),
(index_llr + i),*(int16_t *) &llr[index_llr + i], *(1 + (int16_t *) &llr[index_llr + i]));
#endif
}
rb_count++;
}
rb_count++;
}
}
} // pscch_flag == 0
else { //this will need to be changed a bit when we scan for multiple SCI
memcpy(e_rx,llr+(data_sc*coreset_nbr_rb),coreset_nbr_rb*coreset_time_dur*data_sc*sizeof(uint32_t));
}
}
}
@@ -404,10 +410,11 @@ void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz,
c_rb_by6 = c_rb/6;
// skip zeros in frequency domain bitmap
while ((coreset_freq_dom[c_rb_by6>>3] & (1<<(7-(c_rb_by6&7)))) == 0) {
c_rb+=6;
c_rb_by6 = c_rb/6;
}
if (coreset_freq_dom)
while ((coreset_freq_dom[c_rb_by6>>3] & (1<<(7-(c_rb_by6&7)))) == 0) {
c_rb+=6;
c_rb_by6 = c_rb/6;
}
rxF=NULL;
@@ -665,6 +672,7 @@ void nr_pdcch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms,
int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
int pscch_flag,
int32_t pdcch_est_size,
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
int16_t *pdcch_e_rx,
@@ -677,8 +685,11 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
int32_t avgs;
int32_t avgP[4];
int n_rb,rb_offset;
get_coreset_rballoc(rel15->coreset.frequency_domain_resource,&n_rb,&rb_offset);
if (pscch_flag == 0) get_coreset_rballoc(rel15->coreset.frequency_domain_resource,&n_rb,&rb_offset);
else {
rb_offset = rel15->coreset.frequency_domain_resource[0];
n_rb = rel15->coreset.frequency_domain_resource[1];
}
// Pointers to extracted PDCCH symbols in frequency-domain.
int32_t rx_size = ((4 * frame_parms->N_RB_DL * 12 + 31) >> 5) << 5;
__attribute__ ((aligned(32))) int32_t rxdataF_ext[frame_parms->nb_antennas_rx][rx_size];
@@ -693,10 +704,10 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
memset(llr, 0, sizeof(llr));
LOG_D(PHY,"pdcch coreset: freq %x, n_rb %d, rb_offset %d\n",
LOG_D(NR_PHY,"pdcch coreset: freq %x, n_rb %d, rb_offset %d\n",
rel15->coreset.frequency_domain_resource[0],n_rb,rb_offset);
for (int s=rel15->coreset.StartSymbolIndex; s<(rel15->coreset.StartSymbolIndex+rel15->coreset.duration); s++) {
LOG_D(PHY,"in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n");
LOG_D(NR_PHY,"in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n");
nr_pdcch_extract_rbs_single(ue->frame_parms.samples_per_slot_wCP,
rxdataF,
@@ -707,10 +718,17 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
pdcch_dl_ch_estimates_ext,
s,
frame_parms,
rel15->coreset.frequency_domain_resource,
pscch_flag ==0 ? rel15->coreset.frequency_domain_resource : NULL,
n_rb,
rel15->BWPStart);
/* if (pscch_flag == 1 && dB_fixed(signal_energy_nodc(&pdcch_dl_ch_estimates_ext[0][s*n_rb*NBR_RE_PER_RB_WITH_DMRS],n_rb*NBR_RE_PER_RB_WITH_DMRS)) > 40) {
LOG_I(NR_PHY,"PSCCH: %d.%d rx level0_%d %d ch_level0_%d %d\n",proc->frame_rx,proc->nr_slot_rx, s, dB_fixed(signal_energy_nodc(&rxdataF_ext[0][s*n_rb*NBR_RE_PER_RB_WITH_DMRS],n_rb*NBR_RE_PER_RB_WITH_DMRS)),s,dB_fixed(signal_energy_nodc(&pdcch_dl_ch_estimates_ext[0][s*n_rb*NBR_RE_PER_RB_WITH_DMRS],n_rb*NBR_RE_PER_RB_WITH_DMRS)));
LOG_M("sciF.m","scisF0",&rxdataF_ext[0][s*n_rb*NBR_RE_PER_RB_WITH_DMRS],n_rb*NBR_RE_PER_RB_WITH_DMRS,1,1);
LOG_M("scicF.m","scicF0",&pdcch_dl_ch_estimates_ext[0][s*n_rb*NBR_RE_PER_RB_WITH_DMRS],n_rb*NBR_RE_PER_RB_WITH_DMRS,1,1);
exit(-1);
}
*/
LOG_D(PHY,"we enter nr_pdcch_channel_level(avgP=%d) => compute channel level based on ofdm symbol 0, pdcch_vars[eNB_id]->dl_ch_estimates_ext\n",*avgP);
LOG_D(PHY,"in nr_pdcch_channel_level(dl_ch_estimates_ext -> dl_ch_estimates_ext)\n");
// compute channel level based on ofdm symbol 0
@@ -769,14 +787,12 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
// T_INT(n_pdcch_symbols),
// T_BUFFER(pdcch_vars[eNB_id]->rxdataF_comp, frame_parms->N_RB_DL*12*n_pdcch_symbols* 4));
#endif
#ifdef DEBUG_DCI_DECODING
printf("demapping: slot %u, mi %d\n",slot,get_mi(frame_parms,slot));
#endif
}
LOG_D(PHY,"we enter nr_pdcch_demapping_deinterleaving(), number of candidates %d\n",rel15->number_of_candidates);
nr_pdcch_demapping_deinterleaving((uint32_t *) llr,
nr_pdcch_demapping_deinterleaving(pscch_flag,
(uint32_t *) llr,
(uint32_t *) pdcch_e_rx,
rel15->coreset.duration,
rel15->coreset.StartSymbolIndex,
@@ -800,7 +816,8 @@ void nr_pdcch_unscrambling(int16_t *e_rx,
uint16_t scrambling_RNTI,
uint32_t length,
uint16_t pdcch_DMRS_scrambling_id,
int16_t *z2) {
int16_t *z2,
int sci_flag) {
int i;
uint8_t reset;
uint32_t x1 = 0, x2 = 0, s = 0;
@@ -809,7 +826,7 @@ void nr_pdcch_unscrambling(int16_t *e_rx,
reset = 1;
// x1 is set in first call to lte_gold_generic
n_id = pdcch_DMRS_scrambling_id;
x2 = ((rnti<<16) + n_id); //mod 2^31 is implicit //this is c_init in 38.211 v15.1.0 Section 7.3.2.3
x2 = sci_flag == 0 ? ((rnti<<16) + n_id) : ((n_id<<15) + 1010); //mod 2^31 is implicit //this is c_init in 38.211 v15.1.0 Section 7.3.2.3
LOG_D(PHY,"PDCCH Unscrambling x2 %x : scrambling_RNTI %x\n", x2, rnti);
@@ -840,7 +857,7 @@ static uint16_t nr_dci_false_detection(uint64_t *dci,
) {
uint32_t encoder_output[NR_MAX_DCI_SIZE_DWORD];
polar_encoder_fast(dci, (void*)encoder_output, rnti, 1,
polar_encoder_fast(dci, (void*)encoder_output, NULL,rnti, 1,
messageType, messageLength, aggregation_level);
uint8_t *enout_p = (uint8_t*)encoder_output;
uint16_t x = 0;
@@ -860,15 +877,22 @@ static uint16_t nr_dci_false_detection(uint64_t *dci,
uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
int pscch_flag,
int16_t *pdcch_e_rx,
fapi_nr_dci_indication_t *dci_ind,
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15) {
void *ind,
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15,
int16_t *rsrp_dBm) {
//int gNB_id = 0;
int16_t tmp_e[16*108];
rnti_t n_rnti;
int e_rx_cand_idx = 0;
fapi_nr_dci_indication_t *dci_ind=NULL;
sl_nr_sci_indication_t *sci_ind=NULL;
if (pscch_flag == 0) dci_ind = (fapi_nr_dci_indication_t*)ind;
else sci_ind = (sl_nr_sci_indication_t *)ind;
for (int j=0;j<rel15->number_of_candidates;j++) {
int CCEind = rel15->CCE[j];
int L = rel15->L[j];
@@ -879,11 +903,13 @@ uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
// skip this candidate if we've already found one with the
// same rnti and format at a different aggregation level
int dci_found=0;
for (int ind=0;ind < dci_ind->number_of_dcis ; ind++) {
if (rel15->rnti== dci_ind->dci_list[ind].rnti &&
rel15->dci_format_options[k]==dci_ind->dci_list[ind].dci_format) {
dci_found=1;
break;
if (dci_ind) {
for (int ind=0;ind < dci_ind->number_of_dcis ; ind++) {
if (rel15->rnti== dci_ind->dci_list[ind].rnti &&
rel15->dci_format_options[k]==dci_ind->dci_list[ind].dci_format) {
dci_found=1;
break;
}
}
}
if (dci_found == 1)
@@ -895,47 +921,72 @@ uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
proc->frame_rx, proc->nr_slot_rx, j, rel15->number_of_candidates, CCEind, e_rx_cand_idx, L, dci_length, nr_dci_format_string[rel15->dci_format_options[k]]);
nr_pdcch_unscrambling(&pdcch_e_rx[e_rx_cand_idx], rel15->coreset.scrambling_rnti, L*108, rel15->coreset.pdcch_dmrs_scrambling_id, tmp_e);
nr_pdcch_unscrambling(&pdcch_e_rx[e_rx_cand_idx], rel15->coreset.scrambling_rnti, pscch_flag==0 ? L*108 : L*18, rel15->coreset.pdcch_dmrs_scrambling_id, tmp_e,0);
#ifdef DEBUG_DCI_DECODING
uint32_t *z = (uint32_t *) &e_rx[e_rx_cand_idx];
for (int index_z = 0; index_z < L*6; index_z++){
uint32_t *z = (uint32_t *) &pdcch_e_rx[e_rx_cand_idx];
for (int index_z = 0; index_z < (pscch_flag == 0 ? L*6 : L); index_z++){
for (int i=0; i<9; i++) {
LOG_I(PHY,"z[%d]=(%d,%d) \n", (9*index_z + i), *(int16_t *) &z[9*index_z + i],*(1 + (int16_t *) &z[9*index_z + i]));
}
}
#endif
uint16_t Nid;
uint16_t crc = polar_decoder_int16(tmp_e,
dci_estimation,
&Nid,
1,
NR_POLAR_DCI_MESSAGE_TYPE, dci_length, L);
pscch_flag == 0 ? NR_POLAR_DCI_MESSAGE_TYPE : NR_POLAR_SCI_MESSAGE_TYPE, dci_length, L);
n_rnti = rel15->rnti;
LOG_D(PHY, "(%i.%i) dci indication (rnti %x,dci format %s,n_CCE %d,payloadSize %d,payload %llx )\n",
proc->frame_rx, proc->nr_slot_rx,n_rnti,nr_dci_format_string[rel15->dci_format_options[k]],CCEind,dci_length, *(unsigned long long*)dci_estimation);
if (crc == 0) LOG_D(PHY, "(%i.%i) %s indication (rnti %x,format %s,n_CCE %d,payloadSize %d,payload %llx )\n",
proc->frame_rx, proc->nr_slot_rx,pscch_flag==0?"dci":"sci",n_rnti,pscch_flag==0?nr_dci_format_string[rel15->dci_format_options[k]]:"1A",CCEind,dci_length, *(unsigned long long*)dci_estimation);
if (crc == n_rnti) {
LOG_D(PHY, "(%i.%i) Received dci indication (rnti %x,dci format %s,n_CCE %d,payloadSize %d,payload %llx)\n",
proc->frame_rx, proc->nr_slot_rx,n_rnti,nr_dci_format_string[rel15->dci_format_options[k]],CCEind,dci_length,*(unsigned long long*)dci_estimation);
uint16_t mb = nr_dci_false_detection(dci_estimation,tmp_e,L*108,n_rnti, NR_POLAR_DCI_MESSAGE_TYPE, dci_length, L);
LOG_D(PHY, "(%i.%i) Received %s indication (rnti %x,dci format %s,n_CCE %d,payloadSize %d,payload %llx)\n",
proc->frame_rx, proc->nr_slot_rx,pscch_flag==0?"dci":"sci",n_rnti,pscch_flag==0?nr_dci_format_string[rel15->dci_format_options[k]]:"1A",CCEind,dci_length,*(unsigned long long*)dci_estimation);
uint16_t mb = nr_dci_false_detection(dci_estimation,
tmp_e,
pscch_flag == 0 ? L*108 : L*18,
n_rnti,
pscch_flag == 0 ? NR_POLAR_DCI_MESSAGE_TYPE : NR_POLAR_SCI_MESSAGE_TYPE,
dci_length,
L);
ue->dci_thres = (ue->dci_thres + mb) / 2;
if (mb > (ue->dci_thres+30)) {
LOG_W(PHY,"DCI false positive. Dropping DCI index %d. Mismatched bits: %d/%d. Current DCI threshold: %d\n",j,mb,L*108,ue->dci_thres);
LOG_W(PHY,"DCI false positive. Dropping DCI index %d. Mismatched bits: %d/%d. Current DCI threshold: %d\n",j,mb,pscch_flag==0?L*108:L*18,ue->dci_thres);
continue;
} else {
dci_ind->SFN = proc->frame_rx;
dci_ind->slot = proc->nr_slot_rx;
dci_ind->dci_list[dci_ind->number_of_dcis].rnti = n_rnti;
dci_ind->dci_list[dci_ind->number_of_dcis].n_CCE = CCEind;
dci_ind->dci_list[dci_ind->number_of_dcis].N_CCE = L;
dci_ind->dci_list[dci_ind->number_of_dcis].dci_format = rel15->dci_format_options[k];
dci_ind->dci_list[dci_ind->number_of_dcis].ss_type = rel15->dci_type_options[k];
dci_ind->dci_list[dci_ind->number_of_dcis].coreset_type = rel15->coreset.CoreSetType;
int n_rb, rb_offset;
get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &rb_offset);
dci_ind->dci_list[dci_ind->number_of_dcis].cset_start = rel15->BWPStart + rb_offset;
dci_ind->dci_list[dci_ind->number_of_dcis].payloadSize = dci_length;
memcpy((void*)dci_ind->dci_list[dci_ind->number_of_dcis].payloadBits,(void*)dci_estimation,8);
dci_ind->number_of_dcis++;
if (pscch_flag == 0) {
dci_ind->SFN = proc->frame_rx;
dci_ind->slot = proc->nr_slot_rx;
dci_ind->dci_list[dci_ind->number_of_dcis].rnti = n_rnti;
dci_ind->dci_list[dci_ind->number_of_dcis].n_CCE = CCEind;
dci_ind->dci_list[dci_ind->number_of_dcis].N_CCE = L;
dci_ind->dci_list[dci_ind->number_of_dcis].dci_format = rel15->dci_format_options[k];
dci_ind->dci_list[dci_ind->number_of_dcis].ss_type = rel15->dci_type_options[k];
dci_ind->dci_list[dci_ind->number_of_dcis].coreset_type = rel15->coreset.CoreSetType;
int n_rb, rb_offset;
get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &rb_offset);
dci_ind->dci_list[dci_ind->number_of_dcis].cset_start = rel15->BWPStart + rb_offset;
dci_ind->dci_list[dci_ind->number_of_dcis].payloadSize = dci_length;
memcpy((void*)dci_ind->dci_list[dci_ind->number_of_dcis].payloadBits,(void*)dci_estimation,8);
dci_ind->number_of_dcis++;
}
else {
sci_ind->sfn = proc->frame_rx;
sci_ind->slot = proc->nr_slot_rx;
sci_ind->sensing_result = 0;
sci_ind->pssch_rsrp = 0; // measuring from pscch below; setting this flag to zero
sci_ind->sci_pdu[sci_ind->number_of_SCIs].sci_format_type = SL_SCI_FORMAT_1A_ON_PSCCH;
sci_ind->sci_pdu[sci_ind->number_of_SCIs].subch_index = 0;
sci_ind->sci_pdu[sci_ind->number_of_SCIs].pscch_rsrp = *rsrp_dBm;
sci_ind->sci_pdu[sci_ind->number_of_SCIs].sci_payloadlen = dci_length;
sci_ind->sci_pdu[sci_ind->number_of_SCIs].Nid = Nid;
memcpy(sci_ind->sci_pdu[sci_ind->number_of_SCIs].sci_payloadBits,&dci_estimation,8);
sci_ind->number_of_SCIs++;
ue->SL_UE_PHY_PARAMS.pscch.rx_ok++;
}
break; // If DCI is found, no need to check for remaining DCI lengths
}
} else {
@@ -944,7 +995,7 @@ uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
}
e_rx_cand_idx += 9*L*6*2; //e_rx index for next candidate (L CCEs, 6 REGs per CCE and 9 REs per REG and 2 uint16_t per RE)
}
return(dci_ind->number_of_dcis);
return(dci_ind ? dci_ind->number_of_dcis : sci_ind->number_of_SCIs);
}

View File

@@ -151,8 +151,8 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_time[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size];
for(int i=pbch_initial_symbol; i<pbch_initial_symbol+3;i++)
nr_pbch_channel_estimation(ue,estimateSz, dl_ch_estimates, dl_ch_estimates_time,
proc,i,i-pbch_initial_symbol,temp_ptr->i_ssb,temp_ptr->n_hf,rxdataF);
nr_pbch_channel_estimation(ue,&ue->frame_parms, estimateSz, dl_ch_estimates, dl_ch_estimates_time,
proc,i,i-pbch_initial_symbol,temp_ptr->i_ssb,temp_ptr->n_hf,rxdataF,false, frame_parms->Nid_cell);
stop_meas(&ue->dlsch_channel_estimation_stats);
fapiPbch_t result = {0};
@@ -330,7 +330,7 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc,
// compute the scramblingID_pdcch and the gold pdcch
ue->scramblingID_pdcch = fp->Nid_cell;
nr_gold_pdcch(ue,fp->Nid_cell);
nr_gold_pdcch(&ue->frame_parms,ue->nr_gold_pdcch[0],fp->Nid_cell);
// compute the scrambling IDs for PDSCH DMRS
for (int i=0; i<NR_NB_NSCID; i++) {

View File

@@ -0,0 +1,601 @@
#include "PHY/defs_nr_UE.h"
#include "PHY/TOOLS/tools_defs.h"
#include "PHY/NR_REFSIG/sss_nr.h"
#include "PHY/NR_UE_ESTIMATION/nr_estimation.h"
#include "PHY/MODULATION/modulation_UE.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "SCHED_NR_UE/defs.h"
#include "common/utils/colors.h"
//#define SL_DEBUG
static const int16_t sl_phase_re_nr[PHASE_HYPOTHESIS_NUMBER]
// -pi/3 ---- pi/3
= {16384, 20173, 23571, 26509, 28932, 30791, 32051, 32687, 32687, 32051, 30791, 28932, 26509, 23571, 20173, 16384};
static const int16_t sl_phase_im_nr[PHASE_HYPOTHESIS_NUMBER] // -pi/3 ---- pi/3
= {-28377, -25821, -22762, -19260, -15383, -11207, -6813, -2286, 2286, 6813, 11207, 15383, 19260, 22762, 25821, 28377};
static int sl_nr_pss_correlation(PHY_VARS_NR_UE *UE, int frame_index)
{
sl_nr_ue_phy_params_t *sl_ue = &UE->SL_UE_PHY_PARAMS;
SL_NR_SYNC_PARAMS_t *sync_params = &sl_ue->sync_params;
NR_DL_FRAME_PARMS *sl_fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
int16_t **pss_for_correlation = (int16_t **)sl_ue->init_params.sl_pss_for_correlation;
int maxval=0;
int32_t **rxdata = NULL;
unsigned int n, ar, peak_position = 0, pss_source = 0;
int64_t peak_value = 0;
double ffo_est=0;
int64_t avg[SL_NR_NUM_IDs_IN_PSS];
uint32_t length = (frame_index == 0) ? sl_fp->samples_per_frame + (2 * sl_fp->ofdm_symbol_size) : sl_fp->samples_per_frame;
int64_t psss_corr_value = 0;
rxdata = (int32_t **)UE->common_vars.rxdata;
#ifdef SL_DEBUG
char fname[50], sname[25];
sprintf(fname,"rxdata_frame_%d.m",frame_index);
sprintf(sname,"rxd_frame%d",frame_index);
LOG_M(fname,sname, &rxdata[0][frame_index * sl_fp->samples_per_frame],sl_fp->samples_per_frame,1,1);
LOG_M("pss_for_correlation0.m","pss_id0", pss_for_correlation[0],2048,1,1);
LOG_M("pss_for_correlation1.m","pss_id1", pss_for_correlation[1],2048,1,1);
int64_t *pss_corr_debug_values[SL_NR_NUM_IDs_IN_PSS];
#endif
for (int i=0;i<2*(sl_fp->ofdm_symbol_size);i++) {
maxval = max(maxval,pss_for_correlation[0][i]);
maxval = max(maxval,-pss_for_correlation[0][i]);
maxval = max(maxval,pss_for_correlation[1][i]);
maxval = max(maxval,-pss_for_correlation[1][i]);
}
int shift = log2_approx(maxval);//*(sl_fp->ofdm_symbol_size + sl_fp->nb_prefix_samples)*2);
#ifdef SL_DEBUG
LOG_I(NR_PHY,"SIDELINK SLSS SEARCH: Function:%s\n", __func__);
LOG_I(NR_PHY,"maxval:%d, shift:%d\n", maxval, shift);
#endif
for (int pss_index = 0; pss_index < SL_NR_NUM_IDs_IN_PSS; pss_index++) {
avg[pss_index]=0;
#ifdef SL_DEBUG
pss_corr_debug_values[pss_index] = malloc16_clear(length*sizeof(int64_t));
#endif
}
for (n=0; n < length - sl_fp->ofdm_symbol_size; n+=4) { //
for (int pss_index = 0; pss_index < SL_NR_NUM_IDs_IN_PSS; pss_index++) {
psss_corr_value = 0;
// calculate dot product of primary_synchro_time_nr and rxdata[ar][n] (ar=0..nb_ant_rx) and store the sum in temp[n];
for (ar=0; ar<sl_fp->nb_antennas_rx; ar++) {
/* perform correlation of rx data and pss sequence ie it is a dot product */
const c32_t result = dot_product((c16_t *)pss_for_correlation[pss_index],
(c16_t *)&(rxdata[ar][n + frame_index * sl_fp->samples_per_frame]),
sl_fp->ofdm_symbol_size,
shift);
const c64_t r64 = {.r = result.r, .i = result.i};
psss_corr_value += squaredMod(r64);
#ifdef SL_DEBUG
pss_corr_debug_values[pss_index][n] = psss_corr_value;
#endif
#ifdef SL_DEBUG
printf("frame:%d n:%d, pss_index:%d, pss_for_correlation[pss_index][0]:%x, rxdata[n]:%x\n",
frame_index, n, pss_index, pss_for_correlation[pss_index][0], rxdata[ar][n + frame_index * sl_fp->samples_per_frame]);
printf("result %lld, pss_corr_values[%d][%d]:%ld\n",result, pss_index, n, pss_corr_debug_values[pss_index][n]);
printf("pss_index %d: n %6u peak_value %15llu\n", pss_index, n, (unsigned long long)pss_corr_debug_values[pss_index][n]);
printf("peak_value:%ld, peak_position:%d, pss_source:%d\n", peak_value, peak_position, pss_source);
#endif
}
// calculate the absolute value of sync_corr[n]
avg[pss_index] += psss_corr_value;
if (psss_corr_value > peak_value) {
peak_value = psss_corr_value;
peak_position = n;
pss_source = pss_index;
#ifdef SL_DEBUG
printf("pss_index %d: n %6u peak_value %15llu\n", pss_index, n, (unsigned long long)psss_corr_value);
#endif
}
}
}
#ifdef SL_DEBUG
LOG_M("pss_corr_debug_values_0.m","pss_corr0", &pss_corr_debug_values[0][0],length,1,6);
LOG_M("pss_corr_debug_values_1.m","pss_corr1", &pss_corr_debug_values[1][0],length,1,6);
for (int pss_index = 0; pss_index < SL_NR_NUM_IDs_IN_PSS; pss_index++) {
free(pss_corr_debug_values[pss_index]);
}
#endif
if (UE->UE_fo_compensation) { // Not tested
// fractional frequency offset computation according to Cross-correlation Synchronization Algorithm Using PSS
// Shoujun Huang, Yongtao Su, Ying He and Shan Tang, "Joint time and frequency offset estimation in LTE downlink," 7th International Conference on Communications and Networking in China, 2012.
// Computing cross-correlation at peak on half the symbol size for first half of data
c32_t r1 = dot_product((c16_t *)pss_for_correlation[pss_source],
(c16_t *)&(rxdata[0][peak_position + frame_index * sl_fp->samples_per_frame]),
sl_fp->ofdm_symbol_size>>1,
shift);
// Computing cross-correlation at peak on half the symbol size for data shifted by half symbol size
// as it is real and complex it is necessary to shift by a value equal to symbol size to obtain such shift
c32_t r2 = dot_product((c16_t *)pss_for_correlation[pss_source] + (sl_fp->ofdm_symbol_size >> 1),
(c16_t *)&(rxdata[0][peak_position + frame_index * sl_fp->samples_per_frame]) + (sl_fp->ofdm_symbol_size >> 1),
sl_fp->ofdm_symbol_size >> 1,
shift);
cd_t r1d = {r1.r, r1.i}, r2d = {r2.r, r2.i};
// estimation of fractional frequency offset: angle[(result1)'*(result2)]/pi
ffo_est = atan2(r1d.r * r2d.i - r2d.r * r1d.i, r1d.r * r2d.r + r1d.i * r2d.i) / M_PI;
#ifdef SL_DEBUG
printf("ffo %lf\n",ffo_est);
#endif
}
// computing absolute value of frequency offset
sync_params->freq_offset = ffo_est*sl_fp->subcarrier_spacing;
UE->common_vars.freq_offset = sync_params->freq_offset;
for (int pss_index = 0; pss_index < SL_NR_NUM_IDs_IN_PSS; pss_index++) avg[pss_index]/=(length/4);
sync_params->N_sl_id2 = pss_source;
LOG_I(NR_PHY,"%sPSS Source = %d, Peak found at pos %d, val = %llu (%d dB) avg %d dB, ffo %lf, freq offset:%d Hz\n",
KRED,pss_source, peak_position, (unsigned long long)peak_value, dB_fixed64(peak_value),dB_fixed64(avg[pss_source]),ffo_est, sync_params->freq_offset);
if (peak_value < 5*avg[pss_source])
return(-1);
return peak_position;
}
#define SL_NR_MAX_RX_ANTENNA 1
#define SL_NR_FIRST_PSS_SYMBOL 1
#define SL_NR_FIRST_SSS_SYMBOL 3
#define SL_NR_NUM_PSS_SSS_SYMBOLS 4
static void sl_nr_extract_sss(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc,
int32_t *tot_metric, uint8_t *phase_max,
c16_t rxdataF[][ue->SL_UE_PHY_PARAMS.sl_frame_params.samples_per_slot_wCP])
{
c16_t pss_ext[SL_NR_MAX_RX_ANTENNA][SL_NR_NUM_PSS_SYMBOLS][SL_NR_PSS_SEQUENCE_LENGTH];
c16_t sss_ext[SL_NR_MAX_RX_ANTENNA][SL_NR_NUM_SSS_SYMBOLS][SL_NR_PSS_SEQUENCE_LENGTH];
uint8_t Nid2 = ue->SL_UE_PHY_PARAMS.sync_params.N_sl_id2;
NR_DL_FRAME_PARMS *sl_fp=&ue->SL_UE_PHY_PARAMS.sl_frame_params;
int32_t metric, metric_re;
int16_t *d;
uint16_t Nid1 = 0;
uint8_t phase;
int16_t *sss;
c16_t *rxF_ext;
for (int aarx=0; aarx < sl_fp->nb_antennas_rx; aarx++) {
unsigned int ofdm_symbol_size = sl_fp->ofdm_symbol_size;
// pss, sss extraction
for (int sym = SL_NR_FIRST_PSS_SYMBOL; sym < SL_NR_FIRST_PSS_SYMBOL + SL_NR_NUM_PSS_SSS_SYMBOLS;sym ++) {
if (sym < SL_NR_FIRST_PSS_SYMBOL + SL_NR_NUM_PSS_SYMBOLS) {
rxF_ext = &pss_ext[aarx][sym-SL_NR_FIRST_PSS_SYMBOL][0];
} else {
rxF_ext = &sss_ext[aarx][sym-SL_NR_FIRST_SSS_SYMBOL][0];
}
unsigned int k = sl_fp->first_carrier_offset + sl_fp->ssb_start_subcarrier + 2;
if (k >= ofdm_symbol_size) k -= ofdm_symbol_size;
LOG_D(PHY, "firstcarrieroffset:%d, ssb_sc:%d, k:%d, symbol:%d\n",sl_fp->first_carrier_offset, sl_fp->ssb_start_subcarrier, k, sym);
for (int i=0; i < SL_NR_PSS_SEQUENCE_LENGTH; i++) {
rxF_ext[i] = rxdataF[aarx][sym*ofdm_symbol_size + k];
k++;
if (k == ofdm_symbol_size) k=0;
}
}
LOG_D(PHY, "SIDELINK SLSS SEARCH: EXTRACTION OF PSS, SSS done\n");
#ifdef SL_DEBUG
LOG_M("pss_ext_sym1.m","pss_ext1",&pss_ext[aarx][0][0],SL_NR_PSS_SEQUENCE_LENGTH,1,1);
LOG_M("pss_ext_sym2.m","pss_ext2",&pss_ext[aarx][1][0],SL_NR_PSS_SEQUENCE_LENGTH,1,1);
LOG_M("sss_ext_sym3.m","sss_ext3",&sss_ext[aarx][0][0],SL_NR_PSS_SEQUENCE_LENGTH,1,1);
LOG_M("sss_ext_sym4.m","sss_ext4",&sss_ext[aarx][1][0],SL_NR_PSS_SEQUENCE_LENGTH,1,1);
#endif
// get conjugated channel estimate from PSS, H* = R* \cdot PSS
// and do channel estimation and compensation based on PSS
int16_t *pss = ue->SL_UE_PHY_PARAMS.init_params.sl_pss_for_sync[Nid2];
int16_t *pss_ext2,*sss_ext2;
int16_t tmp_re,tmp_im,tmp_re2,tmp_im2;
int32_t amp, shift;
for (int j=0; j<2;j++) {
int16_t *sss_ext3 = (int16_t*)&sss_ext[aarx][j][0];
sss_ext2 = (int16_t*)&sss_ext[aarx][j][0];
pss_ext2 = (int16_t*)&pss_ext[aarx][j][0];
for (int i = 0; i < SL_NR_PSS_SEQUENCE_LENGTH; i++) {
// This is H*(PSS) = R* \cdot PSS
tmp_re = pss_ext2[i*2] * pss[i];
tmp_im = -pss_ext2[i*2+1] * pss[i];
amp = (((int32_t)tmp_re)*tmp_re) + ((int32_t)tmp_im)*tmp_im;
shift = log2_approx(amp)/2;
// This is R(SSS) \cdot H*(PSS)
tmp_re2 = (int16_t)(((tmp_re * (int32_t)sss_ext2[i*2])>>shift) - ((tmp_im * (int32_t)sss_ext2[i*2+1]>>shift)));
tmp_im2 = (int16_t)(((tmp_re * (int32_t)sss_ext2[i*2+1])>>shift) + ((tmp_im * (int32_t)sss_ext2[i*2]>>shift)));
// MRC on RX antennas
// sss_ext now contains the compensated SSS
if (aarx==0) {
sss_ext3[i<<1] = tmp_re2;
sss_ext3[1+(i<<1)] = tmp_im2;
} else {
AssertFatal(1==0,"SIDELINK MORE THAN 1 RX ANTENNA NOT YET SUPPORTED\n");
}
}
}
LOG_D(PHY, "SIDELINK SLSS SEARCH: Ch. estimation SSS done\n");
}
/*
#ifdef SL_DEBUG
write_output("rxsig0.m","rxs0",&ue->common_vars.rxdata[0][0],ue->frame_parms.samples_per_subframe,1,1);
write_output("rxdataF0_pss.m","rxF0_pss",&ue->common_vars.rxdataF[0][0],frame_parms->ofdm_symbol_size,1,1);
write_output("rxdataF0_sss.m","rxF0_sss",&ue->common_vars.rxdataF[0][(SSS_SYMBOL_NB-PSS_SYMBOL_NB)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size,1,1);
write_output("pss_ext.m","pss_ext",pss_ext,LENGTH_PSS_NR,1,1);
#endif
*/
#if 0
printf("H*(%d,%d) : (%d,%d)\n",aarx,i,tmp_re,tmp_im);
printf("pss(%d,%d) : (%d,%d)\n",aarx,i,pss[2*i],pss[2*i+1]);
printf("pss_ext(%d,%d) : (%d,%d)\n",aarx,i,pss_ext2[2*i],pss_ext2[2*i+1]);
if (aarx==0) {
chest[i<<1]=tmp_re;
chest[1+(i<<1)]=tmp_im;
}
#endif
// printf("SSSi(%d,%d) : (%d,%d)\n",aarx,i,sss_ext2[i<<1],sss_ext2[1+(i<<1)]);
// printf("SSSo(%d,%d) : (%d,%d)\n",aarx,i,tmp_re2,tmp_im2);
// MRC on RX antennas
#if 0
LOG_M("pssrx.m","pssrx",pss,LENGTH_PSS_NR,1,1);
LOG_M("pss_ext.m","pssext",pss_ext2,LENGTH_PSS_NR,1,1);
LOG_M("psschest.m","pssch",chest,LENGTH_PSS_NR,1,1);
#endif
#if 0
for (int i = 0; i < LENGTH_PSS_NR; i++) {
printf(" sss ext 2 [%d] %d %d at address %p\n", i, sss_ext2[2*i], sss_ext2[2*i+1]);
printf(" sss ref [%d] %d %d at address %p\n", i, d_sss[0][0][i], d_sss[0][0][i]);
printf(" sss ext 3 [%d] %d %d at address %p\n", i, sss_ext3[2*i], sss_ext3[2*i+1]);
}
#endif
#if 0
/* simulate of a phase shift on the signal */
int phase_shift_index = 0;
phase_shift_samples(sss, LENGTH_SSS_NR, phase_re_nr[phase_shift_index], phase_im_nr[phase_shift_index]);
#endif
#if 0
int16_t *ps = (int16_t *)pss_ext;
for (int i = 0; i < LENGTH_SSS_NR; i++) {
printf("sss ref [%i] : %d \n", i, d_sss[0][0][i]);
printf("sss ext [%i] : %d %d \n", i, sss[2*i], sss[2*i+1]);
printf("pss ref [%i] : %d %d \n", i, primary_synchro_nr2[0][2*i], primary_synchro_nr2[0][2*i+1]);
printf("pss ext [%i] : %d %d \n", i, ps[2*i], ps[2*i+1]);
}
#endif
/* for phase evaluation, one uses an array of possible phase shifts */
/* then a correlation is done between received signal with a shift pĥase and the reference signal */
/* Computation of signal with shift phase is based on below formula */
/* cosinus cos(x + y) = cos(x)cos(y) - sin(x)sin(y) */
/* sinus sin(x + y) = sin(x)cos(y) + cos(x)sin(y) */
// now do the SSS detection based on the pre computed SSS sequences
*tot_metric = INT_MIN;
sss = (int16_t*)&sss_ext[0][0][0];
for (uint16_t id1 = 0 ; id1 < SL_NR_NUM_IDs_IN_SSS; id1++) { // all possible SSS Nid1 values
for (phase=0; phase < PHASE_HYPOTHESIS_NUMBER; phase++) { // phase offset between PSS and SSS
metric = 0;
metric_re = 0;
d = (int16_t *)&ue->SL_UE_PHY_PARAMS.init_params.sl_sss_for_sync[Nid2 * SL_NR_NUM_IDs_IN_SSS + id1];
// This is the inner product using one particular value of each unknown parameter
for (int i=0; i < SL_NR_SSS_SEQUENCE_LENGTH; i++) {
metric_re += d[i]*(((sl_phase_re_nr[phase]*sss[2*i])>>15) - ((sl_phase_im_nr[phase]*sss[2*i+1])>>15));
#if 0
printf("i %d, phase %d/%d: metric %d, phase (%d,%d) sss (%d,%d) d %d\n",i,phase,PHASE_HYPOTHESIS_NUMBER,metric_re,phase_re_nr[phase],phase_im_nr[phase],sss[2*i],sss[1+(2*i)],d[i]);
#endif
}
metric = metric_re;
// if the current metric is better than the last save it
if (metric > *tot_metric) {
*tot_metric = metric;
Nid1 = id1;
*phase_max = phase;
LOG_D(PHY, "(phase,Nid1) (%d,%d), metric_phase %d tot_metric %d, phase_max %d \n",phase, Nid1, metric, *tot_metric, *phase_max);
}
}
}
ue->SL_UE_PHY_PARAMS.sync_params.N_sl_id1 = Nid1;
ue->SL_UE_PHY_PARAMS.sync_params.N_sl_id = ue->SL_UE_PHY_PARAMS.sync_params.N_sl_id1 + 336 * ue->SL_UE_PHY_PARAMS.sync_params.N_sl_id2;
LOG_I(NR_PHY, "%sUE[%d]NR-SL SLSS SEARCH: SSS Processing over. id2 from SSS:%d, id1 from PSS:%d, SLSS id:%d\n",KRED,
ue->Mod_id, ue->SL_UE_PHY_PARAMS.sync_params.N_sl_id1, ue->SL_UE_PHY_PARAMS.sync_params.N_sl_id2,
ue->SL_UE_PHY_PARAMS.sync_params.N_sl_id);
#ifdef SL_DEBUG
#define SSS_METRIC_FLOOR_NR (30000)
if (*tot_metric > SSS_METRIC_FLOOR_NR) {
Nid2 = ue->SL_UE_PHY_PARAMS.sync_params.N_sl_id2;
Nid1 = ue->SL_UE_PHY_PARAMS.sync_params.N_sl_id1;
printf("Nid2 %d Nid1 %d tot_metric %d, phase_max %d \n", Nid2, Nid1, *tot_metric, *phase_max);
}
#endif
return;
}
// Right now 2 frames worth of samples get processed for PSS in OAI.
// For PSS in Sidelink, worst case 1 SSB in 16 frames can be present
// Hence 16 frames worth of samples needs to be correlated to find the PSS.
int sl_nr_slss_search(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc, int num_frames) {
sl_nr_ue_phy_params_t *sl_ue = &UE->SL_UE_PHY_PARAMS;
SL_NR_SYNC_PARAMS_t *sync_params = &sl_ue->sync_params;
NR_DL_FRAME_PARMS *sl_fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
int32_t sync_pos = -1;// sync_pos_frame = -1;
int32_t metric_tdd_ncp=0;
uint8_t phase_tdd_ncp = 0;
double im, re;
int ret=-1;
uint16_t rx_slss_id = 65535;
#ifdef SL_DEBUG_SEARCH_SLSS
LOG_D(PHY, "SIDELINK SEARCH SLSS: Function:%s\n", __func__);
#endif
/* Initial synchronisation
*
* 1 radio frame = 10 ms
* <--------------------------------------------------------------------------->
* | Received UE data buffer |
* ----------------------------------------------------------------------------
* <-------------->|psbch|pss|pss|sss|sss|psbch sym5-sym 12|sym13 - guard|
* sync_pos SS/PSBCH block
*/
// initial sync performed on 16 successive frames. Worst case - one PSBCH can be sent in 16 frames.
//If psbch passes on first frame, no need to process second frame
// Problem with the frame approach is that
// --------- SSB can be on the boundary between frames. In this case if only 1 SSB is sent we will miss it.
// rxdata will hold 16 frames + slot worth of samples. This needs to be processed to find the best SSB
for(int frame_index = 0; frame_index < num_frames; frame_index++) {
/* process pss search on received buffer */
sync_pos = sl_nr_pss_correlation(UE, frame_index);
if (sync_pos == -1) {
LOG_I(NR_PHY,"SIDELINK SEARCH SLSS: No PSSS found in this frame\n");
continue;
}
sync_pos += frame_index * sl_fp->samples_per_frame; // position in the num_frames frame samples
for (int pss_sym = 1; pss_sym < 3;pss_sym++) {
// Now Sync pos can point to PSS 1st symbol or 2nd symbol.
// Right now implemented the strategy to try both locations for FFT
// Think about a better correlation strategy
if (pss_sym == 1) { // Check if sync pos points to SYMBOL1 - first symbol of PSS location
if (sync_pos > sl_fp->nb_prefix_samples0 + sl_fp->ofdm_symbol_size + sl_fp->nb_prefix_samples)
sync_params->ssb_offset = sync_pos - (sl_fp->nb_prefix_samples0 + sl_fp->ofdm_symbol_size + sl_fp->nb_prefix_samples);
else
sync_params->ssb_offset = sync_pos + sl_fp->samples_per_frame - (sl_fp->nb_prefix_samples0 + sl_fp->ofdm_symbol_size + sl_fp->nb_prefix_samples);
} else { // Check if sync pos points to SYMBOL2 - second symbol of PSS location
if (sync_pos >= sl_fp->nb_prefix_samples0 + 2*(sl_fp->ofdm_symbol_size + sl_fp->nb_prefix_samples))
sync_params->ssb_offset = sync_pos - (sl_fp->nb_prefix_samples0 + 2*(sl_fp->ofdm_symbol_size + sl_fp->nb_prefix_samples));
else
sync_params->ssb_offset = sync_pos + sl_fp->samples_per_frame - (sl_fp->nb_prefix_samples0 + 2*(sl_fp->ofdm_symbol_size + sl_fp->nb_prefix_samples));
}
#define SL_NR_NUM_SYMBOLS_FOR_PSBCH_NORMAL_CP 14
LOG_I(NR_PHY,"%sUE[%d]SIDELINK SEARCH SLSS: PSS Peak at %d, PSS sym:%d, Estimated PSS position %d\n",KRED,
UE->Mod_id,sync_pos,pss_sym,sync_params->ssb_offset);
int slss_block_samples = (SL_NR_NUM_SYMBOLS_FOR_PSBCH_NORMAL_CP * sl_fp->ofdm_symbol_size) +
(SL_NR_NUM_SYMBOLS_FOR_PSBCH_NORMAL_CP -1) * sl_fp->nb_prefix_samples + sl_fp->nb_prefix_samples0;
int ssb_end_position = sync_params->ssb_offset + slss_block_samples;
LOG_D(PHY, "ssb_end:%d ssb block samples:%d total samples: %d\n", ssb_end_position, slss_block_samples, num_frames * sl_fp->samples_per_frame);
/* check that SSS/PBCH block is continuous inside the received buffer */
if (ssb_end_position < num_frames * sl_fp->samples_per_frame) {
// digital compensation of FFO for SSB symbols
if (UE->UE_fo_compensation){ // This code to be checked. Why do we do this before PSS detection is successful?
double s_time = 1/(1.0e3 * sl_fp->samples_per_subframe); // sampling time
double off_angle = -2 * M_PI * s_time * (sync_params->freq_offset); // offset rotation angle compensation per sample
int start = sync_params->ssb_offset; // start for offset correction is at ssb_offset (pss time position)
// Adapt this for other numerologies number of symbols with larger cp increases TBD
int end = ssb_end_position; // loop over samples in all symbols (ssb size), including prefix
LOG_I(NR_PHY,"%sSLSS SEARCH: FREQ comp of SLSS samples. Freq_OFSET:%d, startpos:%d, end_pos:%d\n",KRED,
sync_params->freq_offset, start, end);
for(int n=start; n<end; n++) {
for (int ar=0; ar<sl_fp->nb_antennas_rx; ar++) {
re = ((double)(((short *)UE->common_vars.rxdata[ar]))[2*n]);
im = ((double)(((short *)UE->common_vars.rxdata[ar]))[2*n+1]);
((short *)UE->common_vars.rxdata[ar])[2*n] = (short)(round(re*cos(n*off_angle) - im*sin(n*off_angle)));
((short *)UE->common_vars.rxdata[ar])[2*n+1] = (short)(round(re*sin(n*off_angle) + im*cos(n*off_angle)));
}
}
}
NR_DL_FRAME_PARMS *frame_parms = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
const uint32_t rxdataF_sz = frame_parms->samples_per_slot_wCP;
__attribute__ ((aligned(32))) c16_t rxdataF[frame_parms->nb_antennas_rx][rxdataF_sz];
/* In order to achieve correct processing for NR prefix samples is forced to 0 and then restored after function call */
for(int symbol=0; symbol<SL_NR_NUM_SYMBOLS_FOR_PSBCH_NORMAL_CP;symbol++) {
sl_nr_slot_fep(UE,
NULL,
symbol,
0,
sync_params->ssb_offset,
rxdataF);
}
sl_nr_extract_sss(UE, NULL, &metric_tdd_ncp, &phase_tdd_ncp, rxdataF);
// save detected cell id to psbch
rx_slss_id = UE->SL_UE_PHY_PARAMS.sync_params.N_sl_id;
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates[frame_parms->nb_antennas_rx][rxdataF_sz];
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_time[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size];
uint8_t decoded_output[4];
for (int symbol = 0; symbol < SL_NR_NUM_SYMBOLS_FOR_PSBCH_NORMAL_CP-1;) {
nr_pbch_channel_estimation(UE,
frame_parms,
rxdataF_sz,
dl_ch_estimates,
dl_ch_estimates_time,
proc,
symbol,
symbol,
0,
0,
rxdataF,
1,
rx_slss_id);
symbol = (symbol == 0) ? 5 : symbol+1;
}
ret = nr_rx_psbch(UE,proc,
rxdataF_sz,
dl_ch_estimates,
frame_parms,
decoded_output,
rxdataF,
rx_slss_id);
if (ret == 0) { // Check this later TBD
// sync at symbol ue->symbol_offset
// computing the offset wrt the beginning of the frame
// SSB located at symbol 0
sync_params->remaining_frames = (num_frames * sl_fp->samples_per_frame - sync_params->ssb_offset)/sl_fp->samples_per_frame;
//ssb_offset points to start of sl-ssb
//rx_offset points to remaining samples needed to fill a frame
sync_params->rx_offset = sync_params->ssb_offset % sl_fp->samples_per_frame;
LOG_I(NR_PHY,"%sUE[%d]SIDELINK SLSS SEARCH: PSBCH RX OK. Remainingframes:%d, rx_offset:%d\n",KRED,
UE->Mod_id,sync_params->remaining_frames, sync_params->rx_offset);
uint32_t psbch_payload = (*(uint32_t *)decoded_output);
//retrieve DFN and slot number from SL-MIB
sync_params->DFN = (((psbch_payload & 0x0700) >> 1) | ((psbch_payload & 0xFE0000) >> 17));
sync_params->slot_offset = (((psbch_payload & 0x010000) >> 10) | ((psbch_payload & 0xFC000000) >> 26));
LOG_I(NR_PHY, "%sUE[%d]SIDELINK SLSS SEARCH: SL-MIB: DFN:%d, slot:%d.\n",KRED,
UE->Mod_id, sync_params->DFN, sync_params->slot_offset);
nr_sl_psbch_rsrp_measurements(sl_ue,frame_parms,rxdataF, false);
UE->init_sync_frame = sync_params->remaining_frames;
UE->rx_offset = sync_params->rx_offset;
nr_sidelink_indication_t sl_indication;
sl_nr_rx_indication_t rx_ind = {0};
uint16_t number_pdus = 1;
nr_fill_sl_indication(&sl_indication, &rx_ind, NULL, proc, UE, NULL);
nr_fill_sl_rx_indication(&rx_ind, SL_NR_RX_PDU_TYPE_SSB, UE, number_pdus, proc, (void *)decoded_output, rx_slss_id);
LOG_D(PHY,"Sidelink SLSS SEARCH PSBCH RX OK. Send SL-SSB TO MAC\n");
if (UE->if_inst && UE->if_inst->sl_indication)
UE->if_inst->sl_indication(&sl_indication);
break;
}
LOG_I(NR_PHY,"SIDELINK SLSS SEARCH: SLSS ID: %d metric %d, phase %d, psbch CRC %s\n",
sl_ue->sync_params.N_sl_id,metric_tdd_ncp,phase_tdd_ncp,(ret == 0) ? "OK" : "NOT OK");
} else {
LOG_W(PHY,"SIDELINK SLSS SEARCH: Error: Not enough samples to process PSBCH. sync_pos %d\n", sync_pos);
}
}
if (ret == 0) break;
}
if (ret!=0) { // PSBCH not found so indicate sync to higher layers and configure frame parameters
LOG_E(PHY,"SIDELINK SLSS SEARCH: PSBCH not received. Estimated PSS position:%d\n", sync_pos);
}
return ret;
}

View File

@@ -244,7 +244,7 @@ int nr_pbch_channel_level(struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER
return(avg2);
}
static void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL],
void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL],
struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL],
int nb_re,
struct complex16 rxdataF_comp[][PBCH_MAX_RE_PER_SYMBOL],
@@ -254,7 +254,6 @@ static void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][PBCH_MAX
vect128 *dl_ch128 = (vect128 *)dl_ch_estimates_ext[aarx];
vect128 *rxdataF128 = (vect128 *)rxdataF_ext[aarx];
vect128 *rxdataF_comp128 = (vect128 *)rxdataF_comp[aarx];
for (int re=0; re<nb_re; re+=12) {
*rxdataF_comp128++ = mulByConjugate128(rxdataF128++, dl_ch128++, output_shift);
*rxdataF_comp128++ = mulByConjugate128(rxdataF128++, dl_ch128++, output_shift);
@@ -300,7 +299,7 @@ void nr_pbch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms,
#endif
}
static void nr_pbch_unscrambling(int16_t *demod_pbch_e,
void nr_pbch_unscrambling(int16_t *demod_pbch_e,
uint16_t Nid,
uint8_t nushift,
uint16_t M,
@@ -362,7 +361,7 @@ static void nr_pbch_unscrambling(int16_t *demod_pbch_e,
}
}
static void nr_pbch_quantize(int16_t *pbch_llr8,
void nr_pbch_quantize(int16_t *pbch_llr8,
int16_t *pbch_llr,
uint16_t len) {
for (int i=0; i<len; i++) {
@@ -505,7 +504,7 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
0, 0, pbch_a_prime, &pbch_a_interleaved);
//polar decoding de-rate matching
uint64_t tmp=0;
decoderState = polar_decoder_int16(pbch_e_rx,(uint64_t *)&tmp,0,
decoderState = polar_decoder_int16(pbch_e_rx,(uint64_t *)&tmp,NULL,0,
NR_POLAR_PBCH_MESSAGE_TYPE, NR_POLAR_PBCH_PAYLOAD_BITS, NR_POLAR_PBCH_AGGREGATION_LEVEL);
pbch_a_prime = tmp;

View File

@@ -0,0 +1,269 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "PHY/defs_nr_UE.h"
#include "PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h"
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
#include "common/utils/LOG/log.h"
#include "PHY/TOOLS/phy_scope_interface.h"
//#define DEBUG_PSBCH
//Reuse already existing PBCH functions
extern int nr_pbch_channel_level(struct complex16 dl_ch_estimates_ext[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
NR_DL_FRAME_PARMS *frame_parms,
int nb_re);
extern void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
struct complex16 dl_ch_estimates_ext[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
int nb_re,
struct complex16 rxdataF_comp[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
NR_DL_FRAME_PARMS *frame_parms,
uint8_t output_shift);
extern void nr_pbch_unscrambling(int16_t *demod_pbch_e,
uint16_t Nid,
uint8_t nushift,
uint16_t M,
uint16_t length,
uint8_t bitwise,
uint32_t unscrambling_mask,
uint32_t pbch_a_prime,
uint32_t *pbch_a_interleaved);
extern void nr_pbch_quantize(int16_t *pbch_llr8,
int16_t *pbch_llr,
uint16_t len);
static void nr_psbch_extract(uint32_t rxdataF_sz,
c16_t rxdataF[][rxdataF_sz],
int estimateSz,
struct complex16 dl_ch_estimates[][estimateSz],
struct complex16 rxdataF_ext[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
struct complex16 dl_ch_estimates_ext[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
uint32_t symbol,
NR_DL_FRAME_PARMS *frame_params)
{
uint16_t rb;
uint8_t i,j,aarx;
struct complex16 *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext;
const uint8_t nb_rb = SL_NR_NUM_PSBCH_RBS_IN_ONE_SYMBOL;
AssertFatal((symbol == 0 || symbol >= 5), "SIDELINK: PSBCH DMRS not contained in symbol %d \n", symbol);
for (aarx=0; aarx<frame_params->nb_antennas_rx; aarx++) {
unsigned int rx_offset = frame_params->first_carrier_offset + frame_params->ssb_start_subcarrier;
rx_offset = rx_offset % frame_params->ofdm_symbol_size;
rxF = &rxdataF[aarx][symbol*frame_params->ofdm_symbol_size];
rxF_ext = &rxdataF_ext[aarx][0];
dl_ch0 = &dl_ch_estimates[aarx][symbol*frame_params->ofdm_symbol_size];
dl_ch0_ext = &dl_ch_estimates_ext[aarx][0];
#ifdef DEBUG_PSBCH
LOG_I(PHY, "extract_rbs: rx_offset=%d, symbol %u\n", (rx_offset + (symbol*frame_params->ofdm_symbol_size)),symbol);
#endif
for (rb=0; rb<nb_rb; rb++) {
j=0;
for (i=0; i<NR_NB_SC_PER_RB; i++) {
if (i%4 != 0) {
rxF_ext[j]=rxF[rx_offset];
dl_ch0_ext[j]=dl_ch0[i];
#ifdef DEBUG_PSBCH
LOG_I(PHY,"rxF ext[%d] = (%d,%d) rxF [%u]= (%d,%d)\n",(9*rb) + j,
((int16_t *)&rxF_ext[j])[0],
((int16_t *)&rxF_ext[j])[1],
rx_offset,
((int16_t *)&rxF[rx_offset])[0],
((int16_t *)&rxF[rx_offset])[1]);
LOG_I(PHY,"dl ch0 ext[%d] = (%d,%d) dl_ch0 [%d]= (%d,%d)\n", (9*rb) + j,
((int16_t *)&dl_ch0_ext[j])[0],
((int16_t *)&dl_ch0_ext[j])[1],
i,
((int16_t *)&dl_ch0[i])[0],
((int16_t *)&dl_ch0[i])[1]);
#endif
j++;
}
rx_offset=(rx_offset+1)%(frame_params->ofdm_symbol_size);
}
rxF_ext += SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_RB;
dl_ch0_ext += SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_RB;
dl_ch0 += NR_NB_SC_PER_RB;
}
#ifdef DEBUG_PSBCH
char filename[40], varname[25];
sprintf(filename,"psbch_dlch_sym_%d.m", symbol);
sprintf(varname,"psbch_dlch%d.m", symbol);
LOG_M(filename, varname, (void*)dl_ch0, frame_params->ofdm_symbol_size, 1, 1);
sprintf(filename,"psbch_dlchext_sym_%d.m", symbol);
sprintf(varname,"psbch_dlchext%d.m", symbol);
LOG_M(filename, varname, (void*)&dl_ch_estimates_ext[0][0], SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL , 1, 1);
#endif
}
return;
}
int nr_rx_psbch(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
int estimateSz,
struct complex16 dl_ch_estimates[][estimateSz],
NR_DL_FRAME_PARMS *frame_parms,
uint8_t *decoded_output,
c16_t rxdataF[][frame_parms->samples_per_slot_wCP],
uint16_t slss_id)
{
uint32_t decoderState=0;
int psbch_e_rx_idx = 0;
int16_t psbch_e_rx[SL_NR_POLAR_PSBCH_E_NORMAL_CP]= {0};
int16_t psbch_unClipped[SL_NR_POLAR_PSBCH_E_NORMAL_CP]= {0};
#ifdef DEBUG_PSBCH
write_output("psbch_rxdataF.m","psbchrxF",
&rxdataF[0][0],frame_parms->ofdm_symbol_size*SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP,1,1);
#endif
// symbol refers to symbol within SSB. symbol_offset is the offset of the SSB wrt start of slot
double log2_maxh = 0;
// 0 for Normal Cyclic Prefix and 1 for EXT CyclicPrefix
const int numsym = (frame_parms->Ncp) ? SL_NR_NUM_SYMBOLS_SSB_EXT_CP
: SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP;
for (int symbol=0; symbol<numsym;) {
const uint16_t nb_re = SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL;
uint16_t nb_re2 = (nb_re/12)*12 + ((nb_re % 12)>0 ? 12 : 0);
__attribute__ ((aligned(32))) struct complex16 rxdataF_ext[frame_parms->nb_antennas_rx][nb_re2];
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_ext[frame_parms->nb_antennas_rx][nb_re2];
//memset(dl_ch_estimates_ext,0, sizeof dl_ch_estimates_ext);
nr_psbch_extract(frame_parms->samples_per_slot_wCP,
rxdataF,
estimateSz,
dl_ch_estimates,
rxdataF_ext,
dl_ch_estimates_ext,
symbol,
frame_parms);
#ifdef DEBUG_PSBCH
LOG_I(PHY,"PSBCH RX Symbol %d ofdm size %d\n",symbol, frame_parms->ofdm_symbol_size );
#endif
int max_h=0;
if (symbol == 0) {
max_h = nr_pbch_channel_level(dl_ch_estimates_ext,
frame_parms,
nb_re);
//log2_maxh = 3+(log2_approx(max_h)/2);
log2_maxh = 5 +(log2_approx(max_h)/2);// LLR32 crc error. LLR 16 CRC works
}
#ifdef DEBUG_PSBCH
LOG_I(PHY,"PSBCH RX log2_maxh = %f (%d)\n", log2_maxh, max_h);
#endif
__attribute__ ((aligned(32))) struct complex16 rxdataF_comp[frame_parms->nb_antennas_rx][nb_re2];
nr_pbch_channel_compensation(rxdataF_ext,
dl_ch_estimates_ext,
nb_re,
rxdataF_comp,
frame_parms,
log2_maxh); // log2_maxh+I0_shift
nr_pbch_quantize(psbch_e_rx + psbch_e_rx_idx,
(short *)rxdataF_comp[0],
SL_NR_NUM_PSBCH_DATA_BITS_IN_ONE_SYMBOL);
//Unnecessary copy. Used only for SCOPE ... TBD... to remove this.
memcpy(psbch_unClipped + psbch_e_rx_idx, rxdataF_comp[0], SL_NR_NUM_PSBCH_DATA_BITS_IN_ONE_SYMBOL*sizeof(int16_t));
psbch_e_rx_idx += SL_NR_NUM_PSBCH_DATA_BITS_IN_ONE_SYMBOL;
//SKIP 2 SL-PSS AND 2 SL-SSS symbols
//Symbols carrying PSBCH 0, 5-12
symbol = (symbol == 0) ? 5 : symbol + 1;
}
UEscopeCopy(ue, psbchRxdataF_comp, psbch_unClipped, sizeof(struct complex16), frame_parms->nb_antennas_rx, psbch_e_rx_idx/2,0);
UEscopeCopy(ue, psbchLlr, psbch_e_rx, sizeof(int16_t), frame_parms->nb_antennas_rx, psbch_e_rx_idx,0);
#ifdef DEBUG_PSBCH
write_output("psbch_rxdataFcomp.m","psbch_rxFcomp",psbch_unClipped,SL_NR_NUM_PSBCH_DATA_RE_IN_ALL_SYMBOLS,1,1);
#endif
//un-scrambling
LOG_D(PHY, "PSBCH RX POLAR DECODING: total PSBCH bits:%d, rx_slss_id:%d\n", psbch_e_rx_idx, slss_id);
nr_pbch_unscrambling(psbch_e_rx, slss_id, 0, 0, psbch_e_rx_idx,
0, 0, 0, NULL);
//polar decoding de-rate matching
uint64_t tmp=0;
decoderState = polar_decoder_int16(psbch_e_rx,(uint64_t *)&tmp,NULL,0,
SL_NR_POLAR_PSBCH_MESSAGE_TYPE, SL_NR_POLAR_PSBCH_PAYLOAD_BITS, SL_NR_POLAR_PSBCH_AGGREGATION_LEVEL);
uint32_t psbch_payload = tmp;
if(decoderState) {
LOG_E(PHY,"%d:%d PSBCH RX: NOK \n",proc->frame_rx, proc->nr_slot_rx);
return(decoderState);
}
// Decoder reversal
uint32_t a_reversed=0;
for (int i=0; i<SL_NR_POLAR_PSBCH_PAYLOAD_BITS; i++)
a_reversed |= (((uint64_t)psbch_payload>>i)&1)<<(31-i);
psbch_payload = a_reversed;
*((uint32_t *)decoded_output) = psbch_payload;
#ifdef DEBUG_PSBCH
for (int i=0; i<4; i++) {
LOG_I(PHY, "decoded_output[%d]:%x\n", i, decoded_output[i]);
}
#endif
ue->symbol_offset = 0;
//retrieve DFN and slot number from SL-MIB
uint32_t DFN = 0, slot_offset = 0;
DFN = (((psbch_payload & 0x0700) >> 1) | ((psbch_payload & 0xFE0000) >> 17));
slot_offset = (((psbch_payload & 0x010000) >> 10) | ((psbch_payload & 0xFC000000) >> 26));
LOG_D(PHY, "PSBCH RX SL-MIB:%x, decoded DFN:slot %d:%d, %x\n",psbch_payload, DFN, slot_offset, *(uint32_t *)decoded_output);
return 0;
}

View File

@@ -0,0 +1,381 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "PHY/defs_nr_UE.h"
#include "PHY/LTE_REFSIG/lte_refsig.h"
#include "PHY/NR_REFSIG/nr_mod_table.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h"
/*
This function performs PSBCH SCrambling as described in 38.211.
Input parameter "output" is scrambled and the scrambled output is stored in this parameter.
id - SLSS ID used for C_INIT
length is the length of the buffer.
*/
//#define SL_DEBUG
void sl_psbch_scrambling(uint32_t *output, uint32_t id, uint16_t length)
{
uint32_t x1, x2, s=0;
// x1 is set in lte_gold_generic
x2 = id; // C_INIT
#ifdef SL_DEBUG
printf("SIDELINK: Function %s\n", __func__);
printf("Scrambling params: length %d id %d \n", length, id);
#endif
#ifdef SL_DEBUG
for (int i=0; i<56;i++) {
printf("\nBEFORE SCRAMBLING output[%d]:0x%x\n",i,output[i]);
}
#endif
// get initial 32 scrambing bits
s = lte_gold_generic(&x1, &x2, 1);
#ifdef SL_DEBUG
printf("s: %04x\t", s);
#endif
// scramble in 32bit chunks
int i = 0;
while(i+32 <= length) {
output[i>>5] ^= s;
i += 32;
s = lte_gold_generic(&x1, &x2, 0);
#ifdef SL_DEBUG
printf("s: %04x\t", s);
#endif
}
// scramble remaining bits
for (; i < length; ++i) {
output[i>>5] ^= ((s>>(i&0x1f)&1)<<(i&0x1f));
}
#ifdef SL_DEBUG
for (int i=0; i<56;i++) {
printf("\nAFTER SCRAMBLING output[%d]:0x%x\n",i,output[i]);
}
#endif
}
/*
This function RE MAPS PSS, SSS sequences as described in 38.211.
txF is the data in frequency domain, sync_seq = PSS or SSS seq
startsym = 1 for PSS, 3 for SSS
re_offset = sample which points to first RE + SSB start RE
scaling factor = scaling factor used for PSS, SSS (determined according to PSBCH pwr)
symbol size = OFDM symbol size used for RE Mapping
*/
void sl_map_pss_or_sss(struct complex16 *txF, int16_t *sync_seq, uint16_t startsym,
uint16_t re_offset, uint16_t scaling_factor, uint16_t symbol_size)
{
#ifdef SL_DEBUG
printf("%s. DEBUG PSBCH TX: RE MAPPING of PSS/SSS \n", __func__);
printf("Input Params - StartSYM:%d, NUMSYM:%d, RE_OFFSET:%d, num_REs:%d, scaling_factor:%d, symbol_size:%d\n",
startsym, SL_NR_NUM_PSS_OR_SSS_SYMBOLS,re_offset, SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL, scaling_factor, symbol_size);
#endif
// RE Mapping of SL-PSS, SL-SSS
for (int l = startsym;l < (startsym + SL_NR_NUM_PSS_OR_SSS_SYMBOLS);l++) {
int k = re_offset % symbol_size;
int index = 0, offset = 0;
for (int m = 0;m < SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL;m++) {
offset = l*symbol_size + k;
if ((m < 2) || (m >= (SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL - 3))) {
txF[offset].r = 0; //Set REs 0,1,129,130,131 = 0
#ifdef SL_DEBUG
printf("sym:%d, RE:%d, txF[%d]:%d.%d \n", l, m, offset, txF[offset].r,txF[offset].i);
#endif
} else {
txF[offset].r = (sync_seq[index] * scaling_factor) >> 15;
#ifdef SL_DEBUG
printf("sym:%d, RE:%d, txF[%d]:%d.%d, syncseq[%d]:%d \n", l, m, offset, txF[offset].r,txF[offset].i, index, sync_seq[index]);
#endif
index++;
}
txF[offset].i = 0;
k = (k + 1) % symbol_size;
}
}
}
/*
This function Generates the PSBCH DATA Modulation symbols and RE MAPS PSBCH Modulated symbols
and PSBCH DMRS sequences as described in 38.211.
txF is the data in frequency domain
payload is the PSBCH payload (SL-MIB given by higher layers)
id - SLSS ID used for knowing which DMRS sequence to be used.
Cp - NORMAL of extended Cyclic prefix
startsym = 0 and then PSBCH is mapped from symbols 5-13 if normal , 5-11 if extended
re_offset = sample which points to first RE + SSB start RE
scaling factor = scaling factor used for PSS, SSS (determined according to PSBCH pwr)
symbol size = OFDM symbol size used for RE Mapping
*/
void sl_generate_and_map_psbch(struct complex16 *txF, uint32_t *payload, uint16_t id,
uint16_t cp, uint16_t re_offset, uint16_t scaling_factor, uint16_t symbol_size,
struct complex16 *psbch_dmrs)
{
uint64_t psbch_a_reversed = 0;
uint16_t num_psbch_modsym = 0, numsym = 0;
uint8_t idx = 0;
uint32_t encoder_output[SL_NR_POLAR_PSBCH_E_DWORD];
struct complex16 psbch_modsym[SL_NR_NUM_PSBCH_MODULATED_SYMBOLS];
LOG_D(PHY, "PSBCH TX: Generation accg to 38.212, 38.211. SLSS id:%d\n", id);
// Encoder reversal
for (int i=0; i<SL_NR_POLAR_PSBCH_PAYLOAD_BITS; i++)
psbch_a_reversed |= (((uint64_t)*payload>>i)&1)<<(31-i);
#ifdef SL_DEBUG
printf("DEBUG PSBCH TX: 38.212 PSBCH CRC + Channel coding (POLAR) + Rate Matching:\n");
printf("PSBCH payload:%x, Reversed Payload:%016lx\n",*payload, psbch_a_reversed);
#endif
/// CRC, coding and rate matching
polar_encoder_fast(&psbch_a_reversed, (void*)encoder_output, NULL, 0, 0,
SL_NR_POLAR_PSBCH_MESSAGE_TYPE,
SL_NR_POLAR_PSBCH_PAYLOAD_BITS,
SL_NR_POLAR_PSBCH_AGGREGATION_LEVEL);
#ifdef SL_DEBUG
for (int i=0; i<SL_NR_POLAR_PSBCH_E_DWORD; i++)
printf("encoderoutput[%d]: 0x%08x\t", i, encoder_output[i]);
printf("\n");
#endif
/// 38.211 Scrambling
if (cp) { // EXT Cyclic prefix
sl_psbch_scrambling(encoder_output, id, SL_NR_POLAR_PSBCH_E_EXT_CP); //for Extended Cyclic prefix
num_psbch_modsym = SL_NR_POLAR_PSBCH_E_EXT_CP/2;
numsym = SL_NR_NUM_SYMBOLS_SSB_EXT_CP;
AssertFatal(1==0, "EXT CP is not yet supported\n");
}
else { // Normal CP
sl_psbch_scrambling(encoder_output, id, SL_NR_POLAR_PSBCH_E_NORMAL_CP); //for Cyclic prefix
num_psbch_modsym = SL_NR_POLAR_PSBCH_E_NORMAL_CP/2;
numsym = SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP;
}
LOG_D(PHY,"PSBCH TX: 38.211 Scrambling done. Number of bits:%d \n",
SL_NR_POLAR_PSBCH_E_NORMAL_CP);
#ifdef SL_DEBUG
printf("38211 STEP: PSBCH Scrambling \n");
for (int i=0; i<SL_NR_POLAR_PSBCH_E_NORMAL_CP/32; i++)
printf("Scrambleroutput[%d]: 0x%08x\t", i, encoder_output[i]);
printf("\n");
#endif
#ifdef SL_DEBUG
printf("SIDELINK PSBCH TX: 38211 STEP: QPSK Modulation of PSBCH symbols:%d, symbols in PSBCH:%d\n", num_psbch_modsym, numsym);
#endif
/// 38.211 QPSK modulation
for (int j=0; j<num_psbch_modsym; j++) {
idx = ((encoder_output[(j<<1)>>5]>>((j<<1)&0x1f))&3);
psbch_modsym[j].r = nr_qpsk_mod_table[2*idx];
psbch_modsym[j].i = nr_qpsk_mod_table[(2*idx)+1];
#ifdef SL_DEBUG
printf("idx %d, psbch_modsym[%d]-r:%d, i:%d\n", idx, j, psbch_modsym[j].r, psbch_modsym[j].i);
#endif
}
// RE MApping of PSBCH and PSBCH DMRS
int index = 0, dmrs_index = 0;
const int numre=SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL;
#ifdef SL_DEBUG
LOG_M("sl_psbch_data_symbols.m", "psbch_sym", (void*)psbch_modsym, num_psbch_modsym, 1, 1);
LOG_M("sl_psbch_dmrs_symbols.m", "psbch_dmrs", (void*)psbch_dmrs, SL_NR_NUM_PSBCH_DMRS_RE, 1, 1);
#endif
#ifdef SL_DEBUG
printf("\nMapping Sidelink PSBCH DMRS, PSBCH modulation symbols to 132 REs\n");
#endif
#ifdef SL_DEBUG
printf("%s. DEBUG PSBCH TX: RE MAPPING of PSBCH DATA AND DMRS \n", __func__);
printf("Input Params - StartSYM:%d, NUMSYM:%d, RE_OFFSET:%d, num_REs:%d, scaling_factor:%d, symbol_size:%d\n",
0, numsym,re_offset, numre, scaling_factor, symbol_size);
#endif
for (int l=0;l < numsym;) {
int k = re_offset % symbol_size;
int symbol_offset = l*symbol_size;
int offset = 0;
for (int m=0; m < numre;m++) {
// Maps PSBCH DMRS in every 4th RE ex:0,4,....128
// Maps PSBCH in all other REs ex: 1,2,3,5,6,...127,129,130,131
offset = symbol_offset + k;
#ifdef SL_DEBUG
printf("symbol:%d, symbol_offset:%d, k:%d, re:%d, sampleoffset:%d ", l, symbol_offset, k, m, offset);
#endif
if (m % 4 == 0) {
txF[offset].r = (psbch_dmrs[dmrs_index].r * scaling_factor) >> 15;
txF[offset].i = (psbch_dmrs[dmrs_index].i * scaling_factor) >> 15;
#ifdef SL_DEBUG
printf("txF[%d]:%d,%d, psbch_dmrs[%d]:%d,%d ", offset, txF[offset].r,
txF[offset].i, dmrs_index, psbch_dmrs[dmrs_index].r, psbch_dmrs[dmrs_index].i);
#endif
dmrs_index++;
} else {
txF[offset].r = (psbch_modsym[index].r * scaling_factor) >> 15;
txF[offset].i = (psbch_modsym[index].i * scaling_factor) >> 15;
#ifdef SL_DEBUG
printf("txF[%d]:%d,%d, psbch_modsym[%d]:%d,%d\n", offset, txF[offset].r,
txF[offset].i, index ,psbch_modsym[index].r, psbch_modsym[index].i);
#endif
index++;
}
k = (k + 1) % symbol_size;
}
LOG_D(PHY, "PSBCH TX: 38211 STEP: RE MAPPING OF PSBCH, PSBCH DMRS DONE. symbol:%d, first RE offset:%d, Last RE offset:%d, Num PSBCH DATA REs:%d, Num PSBCH DMRS REs:%d\n",
l, symbol_offset+re_offset, offset, index, dmrs_index);
l = (l == 0) ? 5: l+1;
}
}
/*
This function prepares the PSBCH block and RE MAPS PSS, SSS, PSBCH DATA, PSBCH DMRS into buffer txF.
Called by the L1 Scheduler when MAC triggers PHY to send PSBCH
UE is the UE context.
frame, slot points to the TTI in which PSBCH TX will be transmitted
*/
void nr_tx_psbch(PHY_VARS_NR_UE *UE, uint32_t frame_tx,
uint32_t slot_tx,
sl_nr_tx_config_psbch_pdu_t *psbch_vars,
c16_t **txdataF)
{
sl_nr_ue_phy_params_t *sl_ue_phy_params = &UE->SL_UE_PHY_PARAMS;
uint16_t slss_id = psbch_vars->tx_slss_id;
NR_DL_FRAME_PARMS *sl_fp = &sl_ue_phy_params->sl_frame_params;
uint32_t psbch_payload = *((uint32_t *)psbch_vars->psbch_payload);
LOG_D(PHY,"PSBCH TX: slss-id %d, psbch payload %x \n", slss_id, psbch_payload);
// Insert FN and Slot number into SL-MIB
uint32_t mask = ~(0x700 | 0xFE0000 | 0x10000 | 0xFC000000);
psbch_payload &= mask;
psbch_payload |= ((frame_tx%1024)<<1) & 0x700;
psbch_payload |= ((frame_tx%1024)<<17) & 0xFE0000;
psbch_payload |= (slot_tx<<10) & 0x10000;
psbch_payload |= (slot_tx<<26) & 0xFC000000;
#ifdef SL_DEBUG
printf("DEBUG PSBCH TX: DFN, SLOT included. psbch_a :0x%08x, frame:%d, slot:%d\n",
psbch_payload, frame_tx, slot_tx);
#endif
LOG_D(PHY,"PSBCH TX: Frame.Slot %d.%d. Payload::0x%08x, slssid:%d\n",
frame_tx, slot_tx, psbch_payload, slss_id);
// GENERATE Sidelink PSS,SSS Sequences, PSBCH DMRS Symbols, PSBCH Symbols
int16_t *sl_pss = &sl_ue_phy_params->init_params.sl_pss[slss_id/336][0];
int16_t *sl_sss = &sl_ue_phy_params->init_params.sl_sss[slss_id][0];
uint16_t re_offset = sl_fp->first_carrier_offset + sl_fp->ssb_start_subcarrier;
uint16_t symbol_size = sl_fp->ofdm_symbol_size;
// TBD: Need to be replaced by function which calculates scaling factor based on psbch tx power
uint16_t scaling_factor = AMP;
struct complex16 *txF = &txdataF[0][0];
uint16_t startsym = SL_NR_PSS_START_SYMBOL;
#ifdef SL_DEBUG
printf("DEBUG PSBCH TX: MAP PSS. startsym:%d, PSS RE START:%d, scaling factor:%d\n",
startsym, re_offset, scaling_factor);
#endif
sl_map_pss_or_sss(txF, sl_pss, startsym, re_offset, scaling_factor, symbol_size); // PSS
startsym += SL_NR_NUM_PSS_SYMBOLS;
#ifdef SL_DEBUG
printf("DEBUG PSBCH TX: MAP SSS. startsym:%d, SSS RE START:%d, scaling factor:%d\n",
startsym, re_offset, scaling_factor);
#endif
sl_map_pss_or_sss(txF, sl_sss, startsym, re_offset, scaling_factor, symbol_size); // SSS
#ifdef SL_DEBUG
printf("DEBUG PSBCH TX: MAP PSBCH DATA AND DMRS. cyclicPrefix:%d, PSS RE START:%d, scaling factor:%d\n",
sl_fp->Ncp, re_offset, scaling_factor);
#endif
struct complex16 *psbch_dmrs = &sl_ue_phy_params->init_params.psbch_dmrs_modsym[slss_id][0];
sl_generate_and_map_psbch(txF, &psbch_payload, slss_id,
sl_fp->Ncp, re_offset, scaling_factor, symbol_size,
psbch_dmrs);
#ifdef SL_DEBUG
printf("DEBUG PSBCH TX: txdataF Prepared\n");
#endif
#ifdef SL_DEBUG
LOG_M("sl_psbch_block.m", "sl_txF", (void*)txdataF[0], symbol_size*14, 1, 1);
#endif
}

View File

@@ -0,0 +1,75 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file PHY/NR_UE_TRANSPORT/nr_pscch_tx.c
* \brief Top-level routines for generating and decoding the PSCCH physical channel
* \author R. Knopp
* \date 2023
* \version 0.1
* \company Eurecom
* \email:
* \note
* \warning
*/
//#include "PHY/defs.h"
#include "PHY/impl_defs_nr.h"
#include "PHY/defs_nr_common.h"
#include "PHY/defs_nr_UE.h"
//#include "PHY/extern.h"
#include "PHY/NR_UE_TRANSPORT/pucch_nr.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
#include <openair1/PHY/CODING/nrSmallBlock/nr_small_block_defs.h>
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "T.h"
uint32_t nr_generate_dci(void *gNB, PHY_VARS_NR_UE *ue,
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
int32_t *txdataF,
int16_t amp,
NR_DL_FRAME_PARMS *frame_parms,
int slot);
uint32_t nr_generate_sci1(const PHY_VARS_NR_UE *ue,
c16_t *txdataF,
const NR_DL_FRAME_PARMS *frame_parms,
const int16_t amp,
const int nr_slot_tx,
const sl_nr_tx_config_pscch_pssch_pdu_t *pscch_pssch_pdu)
{
nfapi_nr_dl_tti_pdcch_pdu_rel15_t pdcch_pdu_rel15={0};
// for SCI we put the startRB and number of RBs for PSCCH in the first 2 FAPI FreqDomainResource fields
pdcch_pdu_rel15.FreqDomainResource[0] = pscch_pssch_pdu->startrb;
pdcch_pdu_rel15.FreqDomainResource[1] = pscch_pssch_pdu->pscch_numrbs;
pdcch_pdu_rel15.StartSymbolIndex = 1;
pdcch_pdu_rel15.DurationSymbols = pscch_pssch_pdu->pscch_numsym;
pdcch_pdu_rel15.numDlDci = 1;
pdcch_pdu_rel15.dci_pdu[0].ScramblingId = pscch_pssch_pdu->pscch_dmrs_scrambling_id;
pdcch_pdu_rel15.dci_pdu[0].PayloadSizeBits = pscch_pssch_pdu->pscch_sci_payload_len;
// for SCI we put the number of PRBs in the FAPI AggregationLevel field
pdcch_pdu_rel15.dci_pdu[0].AggregationLevel = pscch_pssch_pdu->pscch_numrbs*pscch_pssch_pdu->pscch_numsym;
pdcch_pdu_rel15.dci_pdu[0].ScramblingRNTI = 1010;
*(uint64_t*)pdcch_pdu_rel15.dci_pdu[0].Payload = *(uint64_t *)pscch_pssch_pdu->pscch_sci_payload;
return(nr_generate_dci(NULL,(PHY_VARS_NR_UE *)ue,&pdcch_pdu_rel15,(int32_t *)txdataF,amp,(NR_DL_FRAME_PARMS*)frame_parms,nr_slot_tx));
}

View File

@@ -0,0 +1,70 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file PHY/NR_UE_TRANSPORT/pucch_nr.c
* \brief Top-level routines for generating and decoding the PSFCH physical channel
* \author R. Knopp
* \date 2023
* \version 0.1
* \company Eurecom
* \email:
* \note
* \warning
*/
//#include "PHY/defs.h"
#include "PHY/impl_defs_nr.h"
#include "PHY/defs_nr_common.h"
#include "PHY/defs_nr_UE.h"
//#include "PHY/extern.h"
#include "PHY/NR_UE_TRANSPORT/pucch_nr.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
#include <openair1/PHY/CODING/nrSmallBlock/nr_small_block_defs.h>
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "T.h"
void nr_generate_psfch0(const PHY_VARS_NR_UE *ue,
c16_t **txdataF,
const NR_DL_FRAME_PARMS *frame_parms,
const int16_t amp,
const int nr_slot_tx,
const sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu)
{
fapi_nr_ul_config_pucch_pdu pucch_pdu;
pucch_pdu.start_symbol_index = psfch_pdu->start_symbol_index;
pucch_pdu.hopping_id = psfch_pdu->hopping_id;
pucch_pdu.prb_start = psfch_pdu->prb;
pucch_pdu.initial_cyclic_shift = psfch_pdu->initial_cyclic_shift;
pucch_pdu.mcs = psfch_pdu->mcs;
pucch_pdu.nr_of_symbols = psfch_pdu->nr_of_symbols;
pucch_pdu.n_bit = psfch_pdu->bit_len_harq;
pucch_pdu.bwp_start = psfch_pdu->sl_bwp_start;
pucch_pdu.freq_hop_flag = psfch_pdu->freq_hop_flag;
pucch_pdu.group_hop_flag = psfch_pdu->group_hop_flag;
pucch_pdu.second_hop_prb = psfch_pdu->second_hop_prb;
pucch_pdu.sequence_hop_flag = psfch_pdu->sequence_hop_flag;
nr_generate_pucch0(ue, txdataF, frame_parms, amp, nr_slot_tx, &pucch_pdu);
}

View File

@@ -41,6 +41,9 @@
#define NR_PUSCH_x 2 // UCI placeholder bit TS 38.212 V15.4.0 subclause 5.3.3.1
#define NR_PUSCH_y 3 // UCI placeholder bit
// Additional memory allocation, because of applying the filter and the memory offset to ensure memory alignment
#define FILTER_MARGIN 32
// Functions below implement 36-211 and 36-212
/** @addtogroup _PHY_TRANSPORT_
@@ -211,6 +214,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
NR_UE_ULSCH_t *ulsch,
sl_nr_tx_config_pscch_pssch_pdu_t *pscch_pssch_pdu,
NR_DL_FRAME_PARMS* frame_parms,
uint8_t harq_pid,
unsigned int G);
@@ -252,7 +256,7 @@ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE,
const uint8_t slot,
const NR_DL_FRAME_PARMS *frame_parms,
const uint8_t n_antenna_ports,
c16_t **txdataF);
c16_t **txdataF, uint32_t linktype);
int8_t clean_UE_ulsch(PHY_VARS_NR_UE *UE, uint8_t gNB_id);
@@ -264,6 +268,7 @@ void nr_dlsch_unscrambling(int16_t* llr,
int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
int pscch_flag,
int32_t pdcch_est_size,
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
int16_t *pdcch_e_rx,
@@ -362,13 +367,15 @@ void nr_pdcch_unscrambling(int16_t *z,
uint16_t scrambling_RNTI,
uint32_t length,
uint16_t pdcch_DMRS_scrambling_id,
int16_t *z2);
int16_t *z2,int sci_flag);
uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
int pscch_flag,
int16_t *pdcch_e_rx,
fapi_nr_dci_indication_t *dci_ind,
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15);
void *ind,
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15,
int16_t *rsrp_dBm);
/** \brief This function is the top-level entry point to PDSCH demodulation, after frequency-domain transformation and channel estimation. It performs
@@ -410,6 +417,57 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t
void dump_nrdlsch(PHY_VARS_NR_UE *ue,uint8_t gNB_id,uint8_t nr_slot_rx,unsigned int *coded_bits_per_codeword,int round, unsigned char harq_pid);
void nr_a_sum_b(c16_t *input_x, c16_t *input_y, unsigned short nb_rb);
int nr_rx_psbch(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
int estimateSz,
struct complex16 dl_ch_estimates[][estimateSz],
NR_DL_FRAME_PARMS *frame_parms,
uint8_t *decoded_output,
c16_t rxdataF[][frame_parms->samples_per_slot_wCP],
uint16_t slss_id);
void nr_tx_psbch(PHY_VARS_NR_UE *UE, uint32_t frame_tx, uint32_t slot_tx,
sl_nr_tx_config_psbch_pdu_t *psbch_vars,
c16_t **txdataF);
int sl_nr_slss_search(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc, int num_frames);
uint32_t nr_generate_sci1(const PHY_VARS_NR_UE *ue,
c16_t *txdataF,
const NR_DL_FRAME_PARMS *frame_parms,
const int16_t amp,
const int nr_slot_tx,
const sl_nr_tx_config_pscch_pssch_pdu_t *pscch_pssch_pdu);
void nr_generate_psfch0(const PHY_VARS_NR_UE *ue,
c16_t **txdataF,
const NR_DL_FRAME_PARMS *frame_parms,
const int16_t amp,
const int nr_slot_tx,
const sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu);
int8_t nr_ue_decode_pucch0(PHY_VARS_NR_UE *ue,
int frame,
int slot,
c16_t rxdataF[][ue->SL_UE_PHY_PARAMS.sl_frame_params.samples_per_slot_wCP],
nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu,
nfapi_nr_pucch_pdu_t *pucch_pdu);
int8_t nr_ue_decode_psfch0(PHY_VARS_NR_UE *ue,
int frame,
int slot,
c16_t rxdataF[][ue->SL_UE_PHY_PARAMS.sl_frame_params.samples_per_slot_wCP],
const sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu);
int nr_csi_rs_sinr_estimation(const PHY_VARS_NR_UE *ue,
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
const uint8_t N_ports,
uint8_t mem_offset,
const int32_t csi_rs_estimated_channel_freq[][N_ports][ue->frame_parms.ofdm_symbol_size + FILTER_MARGIN],
const uint32_t interference_plus_noise_power,
const int16_t log2_re,
int32_t *precoded_sinr_dB);
/**@}*/
#endif

View File

@@ -0,0 +1,337 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file PHY/NR_TRANSPORT/pucch_rx.c
* \brief Top-level routines for decoding the PUCCH physical channel
* \author A. Mico Pereperez, Padarthi Naga Prasanth, Francesco Mani, Raymond Knopp
* \date 2020
* \version 0.2
* \company Eurecom
* \email:
* \note
* \warning
*/
#include<stdio.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include "PHY/impl_defs_nr.h"
#include "PHY/defs_nr_common.h"
#include "PHY/defs_gNB.h"
#include "PHY/sse_intrin.h"
#include "PHY/NR_UE_TRANSPORT/pucch_nr.h"
#include <openair1/PHY/CODING/nrSmallBlock/nr_small_block_defs.h>
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
#include "PHY/NR_REFSIG/nr_refsig.h"
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "nfapi/oai_integration/vendor_ext.h"
#include "nfapi/oai_integration/vendor_ext.h"
#include "executables/nr-uesoftmodem.h"
#include "T.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
//#define DEBUG_NR_PUCCH_RX 1
int get_pucch0_cs_lut_index(PHY_VARS_NR_UE *ue, nfapi_nr_pucch_pdu_t* pucch_pdu) {
int i = 0;
#ifdef DEBUG_NR_PUCCH_RX
LOG_I(NR_PHY, "getting index for LUT with %d entries, Nid %d\n", ue->pucch0_lut.nb_id, pucch_pdu->hopping_id);
#endif
for (i=0; i<ue->pucch0_lut.nb_id; i++) {
if (ue->pucch0_lut.Nid[i] == pucch_pdu->hopping_id) break;
}
#ifdef DEBUG_NR_PUCCH_RX
LOG_I(NR_PHY, "found index %d\n", i);
#endif
if (i < ue->pucch0_lut.nb_id) return(i);
#ifdef DEBUG_NR_PUCCH_RX
LOG_I(NR_PHY, "Initializing PUCCH0 LUT index %i with Nid %d\n", i, pucch_pdu->hopping_id);
#endif
// initialize
ue->pucch0_lut.Nid[ue->pucch0_lut.nb_id] = pucch_pdu->hopping_id;
for (int slot=0; slot<10<<pucch_pdu->subcarrier_spacing; slot++)
for (int symbol=0; symbol<14; symbol++)
ue->pucch0_lut.lut[ue->pucch0_lut.nb_id][slot][symbol] = (int)floor(nr_cyclic_shift_hopping(pucch_pdu->hopping_id, 0, 0, 0, symbol, slot) / 0.5235987756);
ue->pucch0_lut.nb_id++;
return(ue->pucch0_lut.nb_id-1);
}
int8_t nr_ue_decode_psfch0(PHY_VARS_NR_UE *ue,
int frame,
int slot,
c16_t rxdataF[][ue->SL_UE_PHY_PARAMS.sl_frame_params.samples_per_slot_wCP],
const sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu) {
int8_t ack_nack_rcvd = -1;
nfapi_nr_pucch_pdu_t pucch_pdu;
pucch_pdu.freq_hop_flag = psfch_pdu->freq_hop_flag;
pucch_pdu.group_hop_flag = psfch_pdu->group_hop_flag;
pucch_pdu.sequence_hop_flag = psfch_pdu->sequence_hop_flag;
pucch_pdu.second_hop_prb = psfch_pdu->second_hop_prb;
pucch_pdu.nr_of_symbols = psfch_pdu->nr_of_symbols;
pucch_pdu.start_symbol_index = psfch_pdu->start_symbol_index;
pucch_pdu.hopping_id = psfch_pdu->hopping_id;
pucch_pdu.prb_start = psfch_pdu->prb;
pucch_pdu.prb_size = 1;
pucch_pdu.bwp_start = psfch_pdu->sl_bwp_start;
pucch_pdu.initial_cyclic_shift = psfch_pdu->initial_cyclic_shift;
pucch_pdu.bit_len_harq = psfch_pdu->bit_len_harq;
pucch_pdu.sr_flag = 0;
pucch_pdu.subcarrier_spacing = 1;
ack_nack_rcvd = nr_ue_decode_pucch0(ue,
frame,
slot,
rxdataF,
NULL,
&pucch_pdu);
return ack_nack_rcvd;
}
int8_t nr_ue_decode_pucch0(PHY_VARS_NR_UE *ue,
int frame,
int slot,
c16_t rxdataF[][ue->SL_UE_PHY_PARAMS.sl_frame_params.samples_per_slot_wCP],
nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu,
nfapi_nr_pucch_pdu_t *pucch_pdu)
{
NR_DL_FRAME_PARMS *frame_parms = get_softmodem_params()->sl_mode ? &ue->SL_UE_PHY_PARAMS.sl_frame_params : &ue->frame_parms;
int soffset = 0;
int nr_sequences;
const uint8_t *mcs;
AssertFatal(pucch_pdu->sr_flag == 0, "SR flag MUST be 0 in SL\n");
AssertFatal(pucch_pdu->bit_len_harq == 0 || pucch_pdu->bit_len_harq == 1, "Invalid value for bit_len_harq %d\n", pucch_pdu->bit_len_harq);
if(pucch_pdu->bit_len_harq == 0){
mcs = table1_mcs;
nr_sequences = 1;
}
else if(pucch_pdu->bit_len_harq == 1){
mcs = table1_mcs;
nr_sequences = 4 >> 1;
}
AssertFatal(nr_sequences == 1 || nr_sequences == 2, "nr_sequences must be either 1 or 2, nr_sequences %d\n", nr_sequences);
LOG_D(PHY, "%s pucch0: nr_symbols %d, start_symbol %d, prb_start %d, second_hop_prb %d, group_hop_flag %d, sequence_hop_flag %d, O_ACK %d, O_SR %d, mcs %d, initial_cyclic_shift %d, subcarrier_spacing %d\n",
__FUNCTION__,
pucch_pdu->nr_of_symbols,
pucch_pdu->start_symbol_index,
pucch_pdu->prb_start,
pucch_pdu->second_hop_prb,
pucch_pdu->group_hop_flag,
pucch_pdu->sequence_hop_flag,
pucch_pdu->bit_len_harq,
pucch_pdu->sr_flag,
mcs[0],
pucch_pdu->initial_cyclic_shift,
pucch_pdu->subcarrier_spacing);
int cs_ind = get_pucch0_cs_lut_index(ue, pucch_pdu);
/*
* Implement TS 38.211 Subclause 6.3.2.3.1 Sequence generation
*
*/
/*
* Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2
*/
/*
* in TS 38.213 Subclause 9.2.1 it is said that:
* for PUCCH format 0 or PUCCH format 1, the index of the cyclic shift
* is indicated by higher layer parameter PUCCH-F0-F1-initial-cyclic-shift
*/
/*
* Implementing TS 38.211 Subclause 6.3.2.3.1, the sequence x(n) shall be generated according to:
* x(l*12+n) = r_u_v_alpha_delta(n)
*/
// the value of u,v (delta always 0 for PUCCH) has to be calculated according to TS 38.211 Subclause 6.3.2.2.1
uint8_t u[2] = {0}, v[2] = {0};
// // x_n contains the sequence r_u_v_alpha_delta(n)
int n, i;
int prb_offset[2] = {pucch_pdu->bwp_start + pucch_pdu->prb_start, pucch_pdu->bwp_start + pucch_pdu->prb_start};
pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag << 1);
nr_group_sequence_hopping(pucch_GroupHopping,
pucch_pdu->hopping_id,
0,
slot,
&u[0],
&v[0]); // calculating u and v value first hop
LOG_D(PHY, "pucch0: u %d, v %d\n", u[0], v[0]);
if (pucch_pdu->freq_hop_flag == 1) {
nr_group_sequence_hopping(pucch_GroupHopping,
pucch_pdu->hopping_id,
1,
slot,
&u[1],
&v[1]); // calculating u and v value second hop
LOG_D(PHY, "pucch0 second hop: u %d, v %d\n", u[1], v[1]);
prb_offset[1] = pucch_pdu->bwp_start + pucch_pdu->second_hop_prb;
}
AssertFatal(pucch_pdu->nr_of_symbols < 3, "nr_of_symbols %d not allowed\n", pucch_pdu->nr_of_symbols);
uint32_t re_offset[2] = {0};
const int16_t *x_re[2], *x_im[2];
x_re[0] = table_5_2_2_2_2_Re[u[0]];
x_im[0] = table_5_2_2_2_2_Im[u[0]];
x_re[1] = table_5_2_2_2_2_Re[u[1]];
x_im[1] = table_5_2_2_2_2_Im[u[1]];
c64_t xr[frame_parms->nb_antennas_rx][pucch_pdu->nr_of_symbols][12] __attribute__((aligned(32)));
int64_t xrtmag = 0, xrtmag_next = 0;
uint8_t maxpos = 0;
uint8_t index = 0;
LOG_D(NR_PHY, "prb_size %d\n", pucch_pdu->prb_size);
int nb_re_pucch = 12*pucch_pdu->prb_size; // prb size is 1
int32_t rp[frame_parms->nb_antennas_rx][pucch_pdu->nr_of_symbols][nb_re_pucch];
memset(rp, 0, sizeof(rp));
int32_t *tmp_rp = NULL;
for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
uint8_t l2 = l + pucch_pdu->start_symbol_index;
re_offset[l] = (12 * prb_offset[l]) + frame_parms->first_carrier_offset;
if (re_offset[l] >= frame_parms->ofdm_symbol_size)
re_offset[l] -= frame_parms->ofdm_symbol_size;
for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) {
LOG_D(NR_PHY, "soffset %i, soffset + l2*frame_parms->ofdm_symbol_size %i %i re_offset[%d] %i\n",
soffset, soffset + l2*frame_parms->ofdm_symbol_size,
(soffset + l2*frame_parms->ofdm_symbol_size + nb_re_pucch), l, re_offset[l]);
for (int z = soffset + l2*frame_parms->ofdm_symbol_size + re_offset[l]; z < (soffset + l2*frame_parms->ofdm_symbol_size + re_offset[l] + nb_re_pucch); z++)
LOG_D(NR_PHY, "%4d.%2d z %d rxdataF (%d,%d)\n", frame, slot, z, rxdataF[aa][z].r, rxdataF[aa][z].i);
tmp_rp = (int32_t *)&rxdataF[aa][soffset + l2 * frame_parms->ofdm_symbol_size];
if(re_offset[l] + nb_re_pucch > frame_parms->ofdm_symbol_size) {
int neg_length = frame_parms->ofdm_symbol_size - re_offset[l];
int pos_length = nb_re_pucch - neg_length;
memcpy1((void*)rp[aa][l], (void*)&tmp_rp[re_offset[l]], neg_length*sizeof(int32_t));
memcpy1((void*)&rp[aa][l][neg_length], (void*)tmp_rp, pos_length*sizeof(int32_t));
}
else
memcpy1((void*)rp[aa][l], (void*)&tmp_rp[re_offset[l]], nb_re_pucch*sizeof(int32_t));
c16_t *r = (c16_t*)&rp[aa][l];
for (n=0; n<nb_re_pucch; n++) {
xr[aa][l][n].r = (int32_t)x_re[l][n] * r[n].r + (int32_t)x_im[l][n] * r[n].i;
xr[aa][l][n].i = (int32_t)x_re[l][n] * r[n].i - (int32_t)x_im[l][n] * r[n].r;
#ifdef DEBUG_NR_PUCCH_RX
LOG_I(NR_PHY, "x (%d,%d), r%d.%d (%d,%d), xr (%lld,%lld)\n",
x_re[l][n], x_im[l][n], l2, re_offset[l], r[n].r, r[n].i, xr[aa][l][n].r, xr[aa][l][n].i);
#endif
}
}
}
int seq_index = 0;
int64_t temp;
for(i=0; i<nr_sequences; i++) {
c64_t corr[frame_parms->nb_antennas_rx][2];
for (int aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
seq_index = (pucch_pdu->initial_cyclic_shift+
mcs[i]+
ue->pucch0_lut.lut[cs_ind][slot][l+pucch_pdu->start_symbol_index])%12;
#ifdef DEBUG_NR_PUCCH_RX
LOG_I(NR_PHY, "PUCCH symbol %d seq %d, seq_index %d, mcs %d , slot %d, cs_ind %d\n",
l, i, seq_index, mcs[i], slot, cs_ind);
#endif
corr[aa][l] = (c64_t){0};
for (n = 0; n < 12; n++) {
corr[aa][l].r += xr[aa][l][n].r * idft12_re[seq_index][n] + xr[aa][l][n].i * idft12_im[seq_index][n];
corr[aa][l].i += xr[aa][l][n].r * idft12_im[seq_index][n] - xr[aa][l][n].i * idft12_re[seq_index][n];
}
corr[aa][l].r >>= 31;
corr[aa][l].i >>= 31;
}
}
LOG_D(PHY,"PUCCH IDFT[%d/%d] = (%ld,%ld)=>%f\n",
mcs[i], seq_index, corr[0][0].r, corr[0][0].i,
10*log10((double)squaredMod(corr[0][0])));
if (pucch_pdu->nr_of_symbols == 2)
LOG_D(PHY,"PUCCH 2nd symbol IDFT[%d/%d] = (%ld,%ld)=>%f\n",
mcs[i], seq_index, corr[0][1].r, corr[0][1].i,
10*log10((double)squaredMod(corr[0][1])));
if (pucch_pdu->freq_hop_flag == 0) {
if (pucch_pdu->nr_of_symbols == 1) {// non-coherent correlation
temp = 0;
for (int aa=0; aa<frame_parms->nb_antennas_rx; aa++)
temp += squaredMod(corr[aa][0]);
} else {
temp = 0;
for (int aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
c64_t corr2;
csum(corr2, corr[aa][0], corr[aa][1]);
// coherent combining of 2 symbols and then complex modulus for single-frequency case
temp += corr2.r*corr2.r + corr2.i*corr2.i;
}
}
} else if (pucch_pdu->freq_hop_flag == 1) {
// full non-coherent combining of 2 symbols for frequency-hopping case
temp = 0;
for (int aa=0; aa<frame_parms->nb_antennas_rx; aa++)
temp += squaredMod(corr[aa][0]) + squaredMod(corr[aa][1]);
}
else AssertFatal(1==0,"shouldn't happen\n");
LOG_D(PHY, "Sequence %d temp %ld vs. xrtmag %ld xrtmag_next %ld, slot %d rx atnennas %u\n",
i, temp, xrtmag, xrtmag_next, slot, frame_parms->nb_antennas_rx);
if (temp > xrtmag) {
xrtmag_next = xrtmag;
xrtmag = temp;
LOG_D(PHY,"Sequence %d xrtmag %ld xrtmag_next %ld, slot %d\n", i, xrtmag, xrtmag_next, slot);
maxpos = i;
int64_t temp2 = 0,temp3 = 0;;
for (int aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
temp2 += squaredMod(corr[aa][0]);
if (pucch_pdu->nr_of_symbols == 2)
temp3 += squaredMod(corr[aa][1]);
}
}
else if (temp > xrtmag_next)
xrtmag_next = temp;
}
#ifdef DEBUG_NR_PUCCH_RX
LOG_D(NR_PHY, "PUCCH 0 : maxpos %d\n", maxpos);
#endif
index = maxpos;
uint8_t ack_nack = !(index&0x01);
LOG_D(PHY,
"[PSFCH RX] %d.%d HARQ %s\n",
frame,
slot,
ack_nack == 0 ? "ACK" : "NACK");
return ack_nack;
}

View File

@@ -47,15 +47,7 @@ void nr_get_carrier_frequencies(PHY_VARS_NR_UE *ue, uint64_t *dl_carrier, uint64
}
void nr_get_carrier_frequencies_sl(PHY_VARS_NR_UE *ue, uint64_t *sl_carrier) {
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
if (ue->if_freq!=0) {
*sl_carrier = ue->if_freq;
} else {
*sl_carrier = fp->sl_CarrierFreq;
}
}
void nr_rf_card_config_gain(openair0_config_t *openair0_cfg,
double rx_gain_off){

View File

@@ -38,11 +38,13 @@
#include "PHY/CODING/nrLDPC_extern.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "executables/nr-uesoftmodem.h"
//#define DEBUG_ULSCH_CODING
int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
NR_UE_ULSCH_t *ulsch,
sl_nr_tx_config_pscch_pssch_pdu_t *pscch_pssch_pdu,
NR_DL_FRAME_PARMS* frame_parms,
uint8_t harq_pid,
unsigned int G) {
@@ -53,44 +55,43 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
///////////
unsigned int crc = 1;
NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid];
uint16_t nb_rb = ulsch->pusch_pdu.rb_size;
uint32_t A = ulsch->pusch_pdu.pusch_data.tb_size<<3;
NR_UL_UE_HARQ_t *harq_process = get_softmodem_params()->sl_mode ? &ue->sl_harq_processes[harq_pid] : &ue->ul_harq_processes[harq_pid];
uint16_t nb_rb = pscch_pssch_pdu == NULL ? ulsch->pusch_pdu.rb_size : pscch_pssch_pdu->l_subch * pscch_pssch_pdu->subchannel_size;
uint32_t A = (pscch_pssch_pdu == NULL ? ulsch->pusch_pdu.pusch_data.tb_size : pscch_pssch_pdu->tb_size)<<3;
uint32_t *pz = &harq_process->Z;
uint8_t mod_order = ulsch->pusch_pdu.qam_mod_order;
uint8_t mod_order = pscch_pssch_pdu == NULL ? ulsch->pusch_pdu.qam_mod_order : pscch_pssch_pdu->mod_order;
int ndi = pscch_pssch_pdu==NULL ? ulsch->pusch_pdu.pusch_data.new_data_indicator:pscch_pssch_pdu->ndi;
int num_layers = pscch_pssch_pdu == NULL ? ulsch->pusch_pdu.nrOfLayers:pscch_pssch_pdu->num_layers;
int rv_index = pscch_pssch_pdu == NULL ? ulsch->pusch_pdu.pusch_data.rv_index:pscch_pssch_pdu->rv_index;
int tbslbrm = pscch_pssch_pdu==NULL?ulsch->pusch_pdu.tbslbrm:pscch_pssch_pdu->tbslbrm;
uint16_t Kr=0;
uint32_t r_offset=0;
uint32_t F=0;
// target_code_rate is in 0.1 units
float Coderate = (float) ulsch->pusch_pdu.target_code_rate / 10240.0f;
float Coderate = (float) (pscch_pssch_pdu == NULL ? ulsch->pusch_pdu.target_code_rate : pscch_pssch_pdu->target_coderate) / 10240.0f;
if (pscch_pssch_pdu) memcpy(harq_process->a,pscch_pssch_pdu->slsch_payload,A>>3);
///////////
/////////////////////////////////////////////////////////////////////////////////////////
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_IN);
LOG_D(NR_PHY, "ulsch coding nb_rb %d, Nl = %d\n", nb_rb, ulsch->pusch_pdu.nrOfLayers);
LOG_D(NR_PHY, "ulsch coding A %d G %d mod_order %d Coderate %f\n", A, G, mod_order, Coderate);
LOG_D(NR_PHY, "%s coding nb_rb %d, Nl = %d\n", pscch_pssch_pdu == NULL ? "ULSCH":"SLSCH",nb_rb, num_layers);
LOG_D(NR_PHY, "%s coding A %d G %d mod_order %d Coderate %f\n", pscch_pssch_pdu == NULL ? "ULSCH" : "SLSCH",A, G, mod_order, Coderate);
LOG_D(NR_PHY, "harq_pid %d harq_process->ndi %d, pusch_data.new_data_indicator %d\n",
harq_pid,harq_process->ndi,ulsch->pusch_pdu.pusch_data.new_data_indicator);
harq_pid,harq_process->ndi,ndi);
if (harq_process->first_tx == 1 ||
harq_process->ndi != ulsch->pusch_pdu.pusch_data.new_data_indicator) { // this is a new packet
harq_process->ndi != ndi) { // this is a new packet
#ifdef DEBUG_ULSCH_CODING
printf("encoding thinks this is a new packet \n");
#endif
harq_process->first_tx = 0;
///////////////////////// a---->| add CRC |---->b /////////////////////////
///////////
/*
int i;
printf("ulsch (tx): \n");
for (i=0;i<(A>>3);i++)
printf("%02x.",harq_process->a[i]);
printf("\n");
*/
int max_payload_bytes = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*ulsch->pusch_pdu.nrOfLayers*1056;
int max_payload_bytes = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*num_layers*1056;
if (A > 3824) {
// Add 24-bit crc (polynomial A) to payload
@@ -145,7 +146,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
&harq_process->F,
harq_process->BG);
if (harq_process->C>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*ulsch->pusch_pdu.nrOfLayers) {
if (harq_process->C>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*num_layers) {
LOG_E(PHY,"nr_segmentation.c: too many segments %d, B %d\n",harq_process->C,harq_process->B);
return(-1);
}
@@ -217,8 +218,8 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
///////////
///////////////////////////////////////////////////////////////////////////////
LOG_D(PHY,"setting ndi to %d from pusch_data\n", ulsch->pusch_pdu.pusch_data.new_data_indicator);
harq_process->ndi = ulsch->pusch_pdu.pusch_data.new_data_indicator;
LOG_D(PHY,"setting ndi to %d from pusch_data\n", ndi);
harq_process->ndi = ndi;
}
F = harq_process->F;
Kr = harq_process->K;
@@ -236,19 +237,19 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
LOG_D(PHY,"Rate Matching, Code segment %d (coded bits (G) %u, unpunctured/repeated bits per code segment %d, mod_order %d, nb_rb %d, rvidx %d)...\n",
r,
G,
Kr*3,
Kr>>3,
mod_order,nb_rb,
ulsch->pusch_pdu.pusch_data.rv_index);
rv_index);
//start_meas(rm_stats);
///////////////////////// d---->| Rate matching bit selection |---->e /////////////////////////
///////////
uint32_t E = nr_get_E(G, harq_process->C, mod_order, ulsch->pusch_pdu.nrOfLayers, r);
uint32_t E = nr_get_E(G, harq_process->C, mod_order, num_layers, r);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RATE_MATCHING_LDPC, VCD_FUNCTION_IN);
start_meas(&ue->ulsch_rate_matching_stats);
if (nr_rate_matching_ldpc(ulsch->pusch_pdu.tbslbrm,
if (nr_rate_matching_ldpc(tbslbrm,
harq_process->BG,
*pz,
harq_process->d[r],
@@ -256,7 +257,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
harq_process->C,
F,
Kr-F-2*(*pz),
ulsch->pusch_pdu.pusch_data.rv_index,
rv_index,
E) == -1)
return -1;

View File

@@ -42,6 +42,7 @@
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
#include "PHY/NR_TRANSPORT/nr_sch_dmrs.h"
#include "PHY/NR_TRANSPORT/nr_dci.h"
#include "PHY/defs_nr_common.h"
#include "PHY/TOOLS/tools_defs.h"
#include "executables/nr-softmodem.h"
@@ -93,6 +94,55 @@ void nr_pusch_codeword_scrambling_uci(uint8_t *in,
}
}
void nr_pusch_codeword_scrambling_sci(uint32_t *in,
uint32_t size,
uint32_t Nid,
uint32_t* out)
{
uint8_t reset, b_idx;
uint32_t x1 = 0, x2 = 0, s = 0;
reset = 1;
x2 = (Nid<<15) + 1010;
for (int i=0; i<size; i++) {
b_idx = i&0x1f;
if (b_idx==0) {
s = lte_gold_generic(&x1, &x2, reset);
reset = 0;
if (i)
out++;
}
*out ^= (((in[i])&1) ^ ((s>>b_idx)&1))<<b_idx;
//printf("i %d b_idx %d in %d s 0x%08x out 0x%08x\n", i, b_idx, in[i], s, *out);
}
}
void nr_pusch_codeword_scrambling_sci_2layer(uint32_t *in,
uint32_t size,
uint32_t Nid,
uint32_t* out)
{
uint8_t reset, b_idx;
uint32_t x1 = 0, x2 = 0, s = 0;
reset = 1;
x2 = (Nid<<15) + 1010;
for (int i=0; i<size; i+=4) {
b_idx = i&0x1f;
if (b_idx==0) {
s = lte_gold_generic(&x1, &x2, reset);
reset = 0;
if (i)
out++;
}
*out ^= (((in[i])&1) ^ ((s>>b_idx)&1))<<b_idx;
*out ^= (((in[i+1])&1) ^ ((s>>(b_idx+1))&1))<<(b_idx+1);
*out ^= (((in[i])&1) ^ ((s>>b_idx)&1))<<(b_idx+2);
*out ^= (((in[i+1])&1) ^ ((s>>(b_idx+1))&1))<<(b_idx+3);
//printf("i %d b_idx %d in %d s 0x%08x out 0x%08x\n", i, b_idx, in[i], s, *out);
}
}
void nr_pusch_codeword_scrambling(uint8_t *in,
uint32_t size,
uint32_t Nid,
@@ -106,6 +156,8 @@ void nr_pusch_codeword_scrambling(uint8_t *in,
nr_codeword_scrambling(in, size, 0, Nid, n_RNTI, out);
}
int dmrs_pscch_mask[2] = {7,15} ;
void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
const unsigned char harq_pid,
const uint32_t frame,
@@ -122,60 +174,116 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
int i;
int sample_offsetF, N_RE_prime;
NR_DL_FRAME_PARMS *frame_parms = &UE->frame_parms;
bool is_csi_rs_slot = false;
if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS)
is_csi_rs_slot = true;
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params = is_csi_rs_slot ? (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)&phy_data->nr_sl_pssch_pscch_pdu.nr_sl_csi_rs_pdu : NULL;
if (csi_params)
LOG_D(NR_PHY, "Tx start_rb %i, cdm_type %i, csi_type %i, freq_density %i, nr_of_rbs %i, row %i symb_l0 %i is_csi_rs_slot %i\n",
csi_params->start_rb, csi_params->cdm_type, csi_params->csi_type, csi_params->freq_density, csi_params->nr_of_rbs, csi_params->row, csi_params->symb_l0, is_csi_rs_slot);
int N_PRB_oh = 0; // higher layer (RRC) parameter xOverhead in PUSCH-ServingCellConfig
uint16_t number_dmrs_symbols = 0;
NR_UE_ULSCH_t *ulsch_ue = &phy_data->ulsch;
NR_UL_UE_HARQ_t *harq_process_ul_ue = &UE->ul_harq_processes[harq_pid];
sl_nr_tx_config_pscch_pssch_pdu_t *pscch_pssch_pdu = &phy_data->nr_sl_pssch_pscch_pdu;
NR_UL_UE_HARQ_t *harq_process_ul_ue = get_softmodem_params()->sl_mode ? &UE->sl_harq_processes[harq_pid] : &UE->ul_harq_processes[harq_pid];
const nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &ulsch_ue->pusch_pdu;
int start_symbol = pusch_pdu->start_symbol_index;
uint16_t ul_dmrs_symb_pos = pusch_pdu->ul_dmrs_symb_pos;
uint8_t number_of_symbols = pusch_pdu->nr_of_symbols;
uint8_t dmrs_type = pusch_pdu->dmrs_config_type;
uint16_t start_rb = pusch_pdu->rb_start;
uint16_t nb_rb = pusch_pdu->rb_size;
uint8_t Nl = pusch_pdu->nrOfLayers;
uint8_t mod_order = pusch_pdu->qam_mod_order;
uint16_t rnti = pusch_pdu->rnti;
uint8_t cdm_grps_no_data = pusch_pdu->num_dmrs_cdm_grps_no_data;
uint16_t start_sc = frame_parms->first_carrier_offset + (start_rb+pusch_pdu->bwp_start)*NR_NB_SC_PER_RB;
NR_DL_FRAME_PARMS *frame_parms = pscch_pssch_pdu == NULL ? &UE->frame_parms : &UE->SL_UE_PHY_PARAMS.sl_frame_params;
int start_symbol = pscch_pssch_pdu == NULL ? pusch_pdu->start_symbol_index : (1+pscch_pssch_pdu->pssch_startsym);
uint16_t ul_dmrs_symb_pos = pscch_pssch_pdu == NULL ? pusch_pdu->ul_dmrs_symb_pos : pscch_pssch_pdu->dmrs_symbol_position;
uint8_t number_of_symbols = pscch_pssch_pdu == NULL ? pusch_pdu->nr_of_symbols : pscch_pssch_pdu->pssch_numsym;
uint8_t dmrs_type = pscch_pssch_pdu == NULL ? pusch_pdu->dmrs_config_type : pusch_dmrs_type1;
uint16_t start_rb = pscch_pssch_pdu == NULL ? pusch_pdu->rb_start : pscch_pssch_pdu->startrb;
uint16_t nb_rb = pscch_pssch_pdu == NULL ? pusch_pdu->rb_size : pscch_pssch_pdu->l_subch * pscch_pssch_pdu->subchannel_size;
uint8_t Nl = pscch_pssch_pdu == NULL ? pusch_pdu->nrOfLayers : pscch_pssch_pdu->num_layers;
uint8_t mod_order = pscch_pssch_pdu == NULL ? pusch_pdu->qam_mod_order : pscch_pssch_pdu->mod_order;
uint16_t rnti = pscch_pssch_pdu == NULL ? pusch_pdu->rnti : 0;
uint8_t cdm_grps_no_data = pscch_pssch_pdu == NULL ? pusch_pdu->num_dmrs_cdm_grps_no_data : 1;
uint16_t start_sc = frame_parms->first_carrier_offset + (start_rb+(pscch_pssch_pdu == NULL ? pusch_pdu->bwp_start:0))*NR_NB_SC_PER_RB;
uint16_t Tpmi = pscch_pssch_pdu == NULL ? pusch_pdu->Tpmi : 0;
if (start_sc >= frame_parms->ofdm_symbol_size)
start_sc -= frame_parms->ofdm_symbol_size;
ulsch_ue->Nid_cell = frame_parms->Nid_cell;
uint8_t first_dmrs_symbol = 0;
bool is_first_dmrs_symbol = true;
for (int i = start_symbol; i < start_symbol + number_of_symbols; i++) {
if((ul_dmrs_symb_pos >> i) & 0x01)
if((ul_dmrs_symb_pos >> i) & 0x01) {
number_dmrs_symbols += 1;
if (is_first_dmrs_symbol) {
first_dmrs_symbol = i;
is_first_dmrs_symbol = false;
}
if (csi_params && csi_params->symb_l0 != 0)
AssertFatal(i != csi_params->symb_l0, "CSI-RS (symb_l0 %d) MUST not be sent in DMRS symbol (%d)\n", csi_params->symb_l0, i);
}
}
if (csi_params && csi_params->symb_l0 != 0)
AssertFatal(csi_params->symb_l0 > pscch_pssch_pdu->pscch_numsym, "CSI-RS (symb_l0 %d) MUST not be sent in PSCCH symbol (%d)\n", csi_params->symb_l0, pscch_pssch_pdu->pscch_numsym);
nb_dmrs_re_per_rb = ((dmrs_type == pusch_dmrs_type1) ? 6:4)*cdm_grps_no_data;
LOG_D(PHY,"ulsch TX %x : start_rb %d nb_rb %d mod_order %d Nl %d Tpmi %d bwp_start %d start_sc %d start_symbol %d num_symbols %d cdmgrpsnodata %d num_dmrs %d dmrs_re_per_rb %d\n",
rnti,start_rb,nb_rb,mod_order,Nl,pusch_pdu->Tpmi,pusch_pdu->bwp_start,start_sc,start_symbol,number_of_symbols,cdm_grps_no_data,number_dmrs_symbols,nb_dmrs_re_per_rb);
//LOG_I(NR_PHY,"%s TX %x : start_rb %d nb_rb %d mod_order %d Nl %d Tpmi %d bwp_start %d start_sc %d start_symbol %d num_symbols %d cdmgrpsnodata %d num_dmrs %d dmrs_re_per_rb %d\n",pscch_pssch_pdu==NULL?"PUSCH":"PSSCH",
// rnti,start_rb,nb_rb,mod_order,Nl,Tpmi,pscch_pssch_pdu==NULL?pusch_pdu->bwp_start:0,start_sc,start_symbol,number_of_symbols,cdm_grps_no_data,number_dmrs_symbols,nb_dmrs_re_per_rb);
// TbD num_of_mod_symbols is set but never used
N_RE_prime = NR_NB_SC_PER_RB*number_of_symbols - nb_dmrs_re_per_rb*number_dmrs_symbols - N_PRB_oh;
uint16_t num_CSI_REs = is_csi_rs_slot ? get_nRECSI_RS(csi_params->freq_density, csi_params->nr_of_rbs) : 0;
int num_CSI_REs_per_RB = is_csi_rs_slot ? (num_CSI_REs/csi_params->nr_of_rbs) : 0;
N_RE_prime = NR_NB_SC_PER_RB * number_of_symbols - nb_dmrs_re_per_rb * number_dmrs_symbols - N_PRB_oh - num_CSI_REs_per_RB;
harq_process_ul_ue->num_of_mod_symbols = N_RE_prime*nb_rb;
/////////////////////////ULSCH coding/////////////////////////
///////////
int sci2_re = pscch_pssch_pdu ? get_NREsci2(pscch_pssch_pdu->sci2_alpha_times_100,
pscch_pssch_pdu->sci2_payload_len,
pscch_pssch_pdu->sci2_beta_offset,
pscch_pssch_pdu->pssch_numsym,
pscch_pssch_pdu->pscch_numsym,
pscch_pssch_pdu->pscch_numrbs,
pscch_pssch_pdu->l_subch,
pscch_pssch_pdu->subchannel_size,
get_softmodem_params()->sl_mode ? 1 : pscch_pssch_pdu->mcs,
pscch_pssch_pdu->mcs_table): 0 ;
//if (pscch_pssch_pdu) LOG_I(NR_PHY,"dmrs_symbol_position %x, pscch_numsym %d\n",pscch_pssch_pdu->dmrs_symbol_position,pscch_pssch_pdu->pscch_numsym);
AssertFatal(pscch_pssch_pdu->pscch_numsym==2 || pscch_pssch_pdu->pscch_numsym==3,"illegal pscch_numsym %d\n",pscch_pssch_pdu->pscch_numsym);
int sci1_dmrs_overlap = pscch_pssch_pdu ? pscch_pssch_pdu->dmrs_symbol_position & dmrs_pscch_mask[pscch_pssch_pdu->pscch_numsym-2] : 0;
uint16_t sci1_re = pscch_pssch_pdu->pscch_numsym * pscch_pssch_pdu->pscch_numrbs * NR_NB_SC_PER_RB;
unsigned int G = (pscch_pssch_pdu==NULL) ? nr_get_G(nb_rb, number_of_symbols,
nb_dmrs_re_per_rb, number_dmrs_symbols, mod_order, Nl):
nr_get_G_SL(nb_rb, number_of_symbols, 6, number_dmrs_symbols, sci1_dmrs_overlap, sci1_re,
pscch_pssch_pdu->pscch_numrbs, sci2_re, num_CSI_REs, mod_order, Nl);
unsigned int G = nr_get_G(nb_rb, number_of_symbols,
nb_dmrs_re_per_rb, number_dmrs_symbols, mod_order, Nl);
// Following code checks, after PSCCH symbols and DMRS symbols, whether PSSCH symbols are used by SCI2 or not,
// If true, then CSI-RS MUST not be sent in those PSSCH symbols containing SCI2.
if (csi_params && csi_params->symb_l0 != 0) {
int32_t next_symbs_sci2_re = 0;
int32_t sci1_re = 12 * pscch_pssch_pdu->pscch_numrbs;
int32_t non_sci1_re = 12 * nb_rb - sci1_re;
next_symbs_sci2_re = first_dmrs_symbol <= pscch_pssch_pdu->pscch_numsym ? sci2_re - (non_sci1_re / 2 - (non_sci1_re * (pscch_pssch_pdu->pscch_numsym - 1)) - (12 * nb_rb) / 2) : sci2_re - (12 * nb_rb) / 2;
int8_t remaining_sci2_symb = next_symbs_sci2_re > 0 ? ceil(next_symbs_sci2_re / (12 * nb_rb)) : 0;
int8_t non_csi_rs_symbs = pscch_pssch_pdu->pscch_numsym + 1 + remaining_sci2_symb; // 1 is for first dmrs symbol
AssertFatal(csi_params->symb_l0 > non_csi_rs_symbs, "CSI-RS MUST not be sent in PSSCH symbol containing SCI2");
}
uint32_t Gsci2 = sci2_re*2*Nl;
trace_NRpdu(DIRECTION_UPLINK,
harq_process_ul_ue->a,
pusch_pdu->pusch_data.tb_size,
pscch_pssch_pdu==NULL?pusch_pdu->pusch_data.tb_size:pscch_pssch_pdu->tb_size,
WS_C_RNTI, rnti, frame, slot, 0, 0);
if (nr_ulsch_encoding(UE, ulsch_ue, frame_parms, harq_pid, G) == -1)
if (nr_ulsch_encoding(UE, ulsch_ue, pscch_pssch_pdu,frame_parms, harq_pid, G) == -1)
return;
uint32_t sci2_encoded_output[sci2_re*2];
if (pscch_pssch_pdu) {
LOG_D(NR_PHY,"Generating SCI2/PSSCH with %d RE, payload %llx\n",sci2_re,*(unsigned long long*)pscch_pssch_pdu->sci2_payload);
// do SCI2 encoding
polar_encoder_fast((uint64_t*)pscch_pssch_pdu->sci2_payload, (void*)sci2_encoded_output, NULL,0, 1,
NR_POLAR_SCI2_MESSAGE_TYPE,
pscch_pssch_pdu->sci2_payload_len, sci2_re);
}
///////////
////////////////////////////////////////////////////////////////////
@@ -185,15 +293,29 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
uint32_t available_bits = G;
uint32_t scrambled_output[(available_bits>>5)+1];
uint32_t scrambled_output_sci[(Gsci2>>5)+1];
memset(scrambled_output, 0, ((available_bits>>5)+1)*sizeof(uint32_t));
memset(scrambled_output_sci, 0, ((Gsci2>>5)+1)*sizeof(uint32_t));
// for (int i=0;i<(Gsci2>>5)+1;i++) LOG_I(NR_PHY,"sci2_encoded[%d] %x\n",i,sci2_encoded_output[i]);
// for (int g=0;g<G;g++) LOG_I(NR_PHY,"coded_output_f[%d] %d\n",g,harq_process_ul_ue->f[g]);
// LOG_I(NR_PHY,"Scrambling with Nid %x\n",phy_data->pscch_Nid);
nr_pusch_codeword_scrambling(harq_process_ul_ue->f,
available_bits,
ulsch_ue->Nid_cell,
rnti,
G,
pscch_pssch_pdu==NULL ? ulsch_ue->Nid_cell : phy_data->pscch_Nid,
pscch_pssch_pdu==NULL ? rnti : 1010,
false,
scrambled_output);
if (pscch_pssch_pdu && Nl==1)
nr_pdcch_scrambling(sci2_encoded_output,
Gsci2,
phy_data->pscch_Nid,1010,
scrambled_output_sci,1);
else if (pscch_pssch_pdu)
nr_pusch_codeword_scrambling_sci_2layer(sci2_encoded_output,
Gsci2,
phy_data->pscch_Nid,
scrambled_output_sci);
/////////////
//////////////////////////////////////////////////////////////////////////
@@ -203,25 +325,39 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
int max_num_re = Nl*number_of_symbols*nb_rb*NR_NB_SC_PER_RB;
int32_t d_mod[max_num_re] __attribute__ ((aligned(16)));
nr_modulation(scrambled_output, // assume one codeword for the moment
available_bits,
mod_order,
(int16_t *)d_mod);
if (Gsci2 > 0) {
nr_modulation(scrambled_output_sci, // assume one codeword for the moment
Gsci2,
2,
(int16_t *)d_mod);
//for (int i=0;i<Gsci2;i+=2) LOG_I(NR_PHY,"SCI2 RE %d/%d: (%d,%d)\n",i/2,Gsci2/2,((int16_t*)d_mod)[i],((int16_t*)d_mod)[i+1]);
int32_t d_mod2[max_num_re] __attribute__ ((aligned(16)));
nr_modulation(scrambled_output, // assume one codeword for the moment
available_bits,
mod_order,
(int16_t *)d_mod2);
LOG_D(NR_PHY,"SCI bits %d (sci2_re %d), PSSCH bits %d (PSCCH RE %d), max_re %d\n",Gsci2,sci2_re,available_bits,available_bits/mod_order,max_num_re);
memcpy(d_mod+sci2_re,d_mod2,available_bits*sizeof(int32_t)/mod_order);
}
else
nr_modulation(scrambled_output, // assume one codeword for the moment
available_bits,
mod_order,
(int16_t *)d_mod);
///////////
////////////////////////////////////////////////////////////////////////
/////////////////////////DMRS Modulation/////////////////////////
///////////
if(pusch_pdu->ul_dmrs_scrambling_id != UE->scramblingID_ulsch[pusch_pdu->scid]) {
if(!pscch_pssch_pdu && pusch_pdu->ul_dmrs_scrambling_id != UE->scramblingID_ulsch[pusch_pdu->scid]) {
UE->scramblingID_ulsch[pusch_pdu->scid] = pusch_pdu->ul_dmrs_scrambling_id;
nr_init_pusch_dmrs(UE, pusch_pdu->scid, pusch_pdu->ul_dmrs_scrambling_id);
}
}
uint32_t ***pusch_dmrs = UE->nr_gold_pusch_dmrs[slot];
uint16_t n_dmrs = (pusch_pdu->bwp_start + start_rb + nb_rb)*((dmrs_type == pusch_dmrs_type1) ? 6:4);
uint16_t n_dmrs = ((pscch_pssch_pdu==NULL ? pusch_pdu->bwp_start : 0) + start_rb + nb_rb)*((dmrs_type == pusch_dmrs_type1) ? 6:4);
int16_t mod_dmrs[n_dmrs<<1] __attribute((aligned(16)));
///////////
@@ -235,7 +371,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
uint8_t L_ptrs, K_ptrs = 0;
uint16_t beta_ptrs = 1; // temp value until power control is implemented
if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
if (!pscch_pssch_pdu && (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS)) {
K_ptrs = pusch_pdu->pusch_ptrs.ptrs_freq_density;
L_ptrs = 1<<pusch_pdu->pusch_ptrs.ptrs_time_density;
@@ -259,11 +395,10 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
int16_t **tx_layers = (int16_t **)malloc16_clear(Nl*sizeof(int16_t *));
for (int nl=0; nl<Nl; nl++)
tx_layers[nl] = (int16_t *)malloc16_clear((available_bits<<1)/mod_order*sizeof(int16_t));
tx_layers[nl] = (int16_t *)malloc16_clear((((available_bits<<1)/mod_order)+(sci2_re<<1))*sizeof(int32_t));
nr_ue_layer_mapping((int16_t *)d_mod,
Nl,
available_bits/mod_order,
(available_bits/mod_order)+sci2_re,
tx_layers);
///////////
@@ -282,7 +417,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
/// Transform-coded "y"-sequences (for definition see 38-211 V15.3.0 2018-09, subsection 6.3.1.4)
int32_t y[max_num_re] __attribute__ ((aligned(16)));
if (pusch_pdu->transform_precoding == transformPrecoder_enabled) {
if (!pscch_pssch_pdu && (pusch_pdu->transform_precoding == transformPrecoder_enabled)) {
uint32_t nb_re_pusch=nb_rb * NR_NB_SC_PER_RB;
uint32_t y_offset = 0;
@@ -312,7 +447,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
LOG_D(PHY,"Transform precoding being done on data- symbol: %d, nb_re_pusch: %d, y_offset: %d\n", l, nb_re_pusch, y_offset);
#ifdef DEBUG_PUSCH_MAPPING
printf("NR_ULSCH_UE: y_offset %u\t nb_re_pusch %u \t Symbol %d \t nb_rb %d \n",
LOG_I(NR_PHY,"NR_ULSCH_UE: y_offset %u\t nb_re_pusch %u \t Symbol %d \t nb_rb %d \n",
y_offset, nb_re_pusch, l, nb_rb);
#endif
}
@@ -357,10 +492,11 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
uint16_t m = 0;
#ifdef DEBUG_PUSCH_MAPPING
printf("NR_ULSCH_UE: Value of CELL ID %d /t, u %d \n", frame_parms->Nid_cell, u);
LOG_I(NR_PHY,"NR_ULSCH_UE: Value of CELL ID %d /t, u %d \n", frame_parms->Nid_cell, u);
#endif
int dmrs_port = get_dmrs_port(nl,pusch_pdu->dmrs_ports);
int dmrs_port = get_dmrs_port(nl,pscch_pssch_pdu ? nl : pusch_pdu->dmrs_ports);
if (dmrs_port < 0) return;
// DMRS params for this dmrs port
get_Wt(Wt, dmrs_port, dmrs_type);
get_Wf(Wf, dmrs_port, dmrs_type);
@@ -371,23 +507,40 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
uint16_t k = start_sc;
uint16_t n = 0;
uint8_t is_dmrs_sym = 0;
uint8_t is_csi_rs_sym = 0;
uint8_t is_ptrs_sym = 0;
uint16_t dmrs_idx = 0, ptrs_idx = 0;
int16_t csi_rs_rb = 0;
int is_pscch_sym = 0;
if (pscch_pssch_pdu && l<(start_symbol + pscch_pssch_pdu->pscch_numsym)) {
is_pscch_sym = 1;
}
if (is_csi_rs_slot && l == csi_params->symb_l0) {
is_csi_rs_sym = 1;
csi_rs_rb = csi_params->start_rb;
}
if ((ul_dmrs_symb_pos >> l) & 0x01) {
is_dmrs_sym = 1;
if (pusch_pdu->transform_precoding == transformPrecoder_disabled){
if (pscch_pssch_pdu || (pusch_pdu->transform_precoding == transformPrecoder_disabled)){
if (dmrs_type == pusch_dmrs_type1)
dmrs_idx = (pusch_pdu->bwp_start + start_rb)*6;
dmrs_idx = ((pscch_pssch_pdu==NULL ? pusch_pdu->bwp_start : 0) + start_rb)*6;
else
dmrs_idx = (pusch_pdu->bwp_start + start_rb)*4;
dmrs_idx = ((pscch_pssch_pdu==NULL ? pusch_pdu->bwp_start : 0) + start_rb)*4;
// TODO: performance improvement, we can skip the modulation of DMRS symbols outside the bandwidth part
// Perform this on gold sequence, not required when SC FDMA operation is done,
LOG_D(PHY,"DMRS in symbol %d\n",l);
nr_modulation(pusch_dmrs[l][pusch_pdu->scid], n_dmrs*2, DMRS_MOD_ORDER, mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated
if (pscch_pssch_pdu == NULL)
nr_modulation(pusch_dmrs[l][pusch_pdu->scid], n_dmrs*2, DMRS_MOD_ORDER, mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated
else {
uint32_t pssch_dmrs[((frame_parms->N_RB_UL * 12) >> 5) + 1];
nr_init_pssch_dmrs_oneshot(frame_parms,phy_data->pscch_Nid,pssch_dmrs,slot,l);
nr_modulation(pssch_dmrs, n_dmrs*2, DMRS_MOD_ORDER, mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated
}
} else {
dmrs_idx = 0;
}
@@ -404,7 +557,18 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
for (i=0; i< nb_rb*NR_NB_SC_PER_RB; i++) {
uint8_t is_dmrs = 0;
uint8_t is_ptrs = 0;
uint8_t is_csi_rs = 0;
if (is_pscch_sym && i==(pscch_pssch_pdu->startrb)) {
i+=(pscch_pssch_pdu->pscch_numrbs*NR_NB_SC_PER_RB);
k+=(pscch_pssch_pdu->pscch_numrbs*NR_NB_SC_PER_RB);
if (is_dmrs_sym) {
dmrs_idx+=(6*pscch_pssch_pdu->pscch_numrbs);
n+=(3*pscch_pssch_pdu->pscch_numrbs);
}
}
LOG_D(NR_PHY, "symbol %d re %d/%d k %d\n", l, i, nb_rb*NR_NB_SC_PER_RB, k);
sample_offsetF = l*frame_parms->ofdm_symbol_size + k;
if (is_dmrs_sym) {
@@ -422,9 +586,26 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
frame_parms->ofdm_symbol_size);
}
if (is_csi_rs_sym) {
if ((k >= csi_params->start_rb * NR_NB_SC_PER_RB) && (i % NR_NB_SC_PER_RB == 0) && (csi_rs_rb < csi_params->nr_of_rbs)) {
csi_rs_params_t table_params;
get_csi_rs_params_from_table(csi_params, &table_params);
port_freq_indices_t *port_freq_indices = (port_freq_indices_t *)malloc(table_params.ports*sizeof(port_freq_indices));
get_csi_rs_freq_ind_sl(frame_parms, csi_rs_rb, csi_params, &table_params, port_freq_indices);
if (k == port_freq_indices[nl].k) {
is_csi_rs = 1;
csi_rs_rb++;
LOG_D(NR_PHY, "Tx port_freq_indices.p %i, port_freq_indices.k %d, is_csi_rs %d, k = %i, RE %i, csi_rs_rb %i\n",
port_freq_indices[nl].p, port_freq_indices[nl].k, is_csi_rs, k, i, csi_rs_rb);
}
free(port_freq_indices);
port_freq_indices = NULL;
}
}
if (is_dmrs == 1) {
// if transform precoding is enabled
if (pusch_pdu->transform_precoding == transformPrecoder_enabled) {
if (!pscch_pssch_pdu && pusch_pdu->transform_precoding == transformPrecoder_enabled) {
((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*dmrs_seq[2*dmrs_idx]) >> 15;
((int16_t*)tx_precoding[nl])[((sample_offsetF)<<1) + 1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*dmrs_seq[(2*dmrs_idx) + 1]) >> 15;
} else {
@@ -433,7 +614,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
}
#ifdef DEBUG_PUSCH_MAPPING
printf("DMRS: Layer: %d\t, dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t dmrs: %d %d\n",
LOG_I(NR_PHY,"DMRS: Layer: %d\t, dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t dmrs: %d %d\n",
nl, dmrs_idx, l, k, k_prime, n, ((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1],
((int16_t*)tx_precoding[nl])[((sample_offsetF)<<1) + 1]);
#endif
@@ -448,9 +629,14 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
((int16_t*)tx_precoding[nl])[((sample_offsetF)<<1) + 1] = (beta_ptrs*AMP*mod_ptrs[(ptrs_idx<<1) + 1]) >> 15;
ptrs_idx++;
} else if (!is_dmrs_sym || allowed_xlsch_re_in_dmrs_symbol(k, start_sc, frame_parms->ofdm_symbol_size, cdm_grps_no_data, dmrs_type)) {
if (pusch_pdu->transform_precoding == transformPrecoder_disabled) {
((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1] = ((int16_t *)tx_layers[nl])[m<<1];
((int16_t*)tx_precoding[nl])[((sample_offsetF)<<1) + 1] = ((int16_t *)tx_layers[nl])[(m<<1) + 1];
if (pscch_pssch_pdu || pusch_pdu->transform_precoding == transformPrecoder_disabled) {
if (!is_csi_rs) {
((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1] = ((int16_t *)tx_layers[nl])[m<<1];
((int16_t*)tx_precoding[nl])[((sample_offsetF)<<1) + 1] = ((int16_t *)tx_layers[nl])[(m<<1) + 1];
} else {
((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1] = 0;
((int16_t*)tx_precoding[nl])[((sample_offsetF)<<1) + 1] = 0;
}
}
else {
((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1] = ((int16_t *) y)[m<<1];
@@ -458,12 +644,13 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
}
#ifdef DEBUG_PUSCH_MAPPING
printf("DATA: layer %d\t m %d\t l %d \t k %d \t tx_precoding: %d %d\n",
LOG_I(NR_PHY,"DATA: layer %d\t m %d\t l %d \t k %d \t tx_precoding: %d %d\n",
nl, m, l, k, ((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1],
((int16_t*)tx_precoding[nl])[((sample_offsetF)<<1) + 1]);
#endif
m++;
if (!is_csi_rs)
m++;
} else {
((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1] = 0;
@@ -489,14 +676,23 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
for (int ap=0; ap<frame_parms->nb_antennas_tx; ap++) {
for (int l=start_symbol; l<start_symbol+number_of_symbols; l++) {
uint16_t k = start_sc;
int is_pscch_sym = 0;
if (pscch_pssch_pdu && l<(start_symbol + pscch_pssch_pdu->pscch_numsym)) {
is_pscch_sym = 1;
}
for (int rb=0; rb<nb_rb; rb++) {
if (is_pscch_sym && rb==(pscch_pssch_pdu->startrb)) {
k+=(pscch_pssch_pdu->pscch_numrbs*NR_NB_SC_PER_RB);
if (k>=frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size;
rb=pscch_pssch_pdu->startrb+pscch_pssch_pdu->pscch_numrbs;
}
//get pmi info
uint8_t pmi=pusch_pdu->Tpmi;
uint8_t pmi=Tpmi;
if (pmi == 0) {//unitary Precoding
if (k + NR_NB_SC_PER_RB <= frame_parms->ofdm_symbol_size) { // RB does not cross DC
if (ap<pusch_pdu->nrOfLayers)
if (ap<Nl)
memcpy(&txdataF[ap][l*frame_parms->ofdm_symbol_size + k],
&tx_precoding[ap][2*(l*frame_parms->ofdm_symbol_size + k)],
NR_NB_SC_PER_RB*sizeof(int32_t));
@@ -507,7 +703,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
} else { // RB does cross DC
int neg_length = frame_parms->ofdm_symbol_size - k;
int pos_length = NR_NB_SC_PER_RB - neg_length;
if (ap<pusch_pdu->nrOfLayers) {
if (ap<Nl) {
memcpy(&txdataF[ap][l*frame_parms->ofdm_symbol_size + k],
&tx_precoding[ap][2*(l*frame_parms->ofdm_symbol_size + k)],
neg_length*sizeof(int32_t));
@@ -536,17 +732,17 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
W_prec = nr_W_1l_2p[pmi][ap];
break;
case 2://2 antenna ports
if (pusch_pdu->nrOfLayers == 1)//1 layer
if (Nl == 1)//1 layer
W_prec = nr_W_1l_2p[pmi][ap];
else//2 layers
W_prec = nr_W_2l_2p[pmi][ap];
break;
case 4://4 antenna ports
if (pusch_pdu->nrOfLayers == 1)//1 layer
if (Nl == 1)//1 layer
W_prec = nr_W_1l_4p[pmi][ap];
else if (pusch_pdu->nrOfLayers == 2)//2 layers
else if (Nl == 2)//2 layers
W_prec = nr_W_2l_4p[pmi][ap];
else if (pusch_pdu->nrOfLayers == 3)//3 layers
else if (Nl == 3)//3 layers
W_prec = nr_W_3l_4p[pmi][ap];
else//4 layers
W_prec = nr_W_4l_4p[pmi][ap];
@@ -559,7 +755,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
for (int i=0; i<NR_NB_SC_PER_RB; i++) {
int32_t re_offset = l*frame_parms->ofdm_symbol_size + k;
int32_t precodatatx_F = nr_layer_precoder(tx_precoding, W_prec, pusch_pdu->nrOfLayers, re_offset);
int32_t precodatatx_F = nr_layer_precoder(tx_precoding, W_prec, Nl, re_offset);
((int16_t*)txdataF[ap])[(re_offset<<1)] = ((int16_t *) &precodatatx_F)[0];
((int16_t*)txdataF[ap])[(re_offset<<1) + 1] = ((int16_t *) &precodatatx_F)[1];
@@ -572,9 +768,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
} // symbol loop
}// port loop
NR_UL_UE_HARQ_t *harq_process_ulsch=NULL;
harq_process_ulsch = &UE->ul_harq_processes[harq_pid];
harq_process_ulsch->status = SCH_IDLE;
harq_process_ul_ue->status = SCH_IDLE;
for (int nl = 0; nl < Nl; nl++) {
free_and_zero(tx_layers[nl]);
@@ -591,15 +785,18 @@ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE,
const uint8_t slot,
const NR_DL_FRAME_PARMS *frame_parms,
const uint8_t n_antenna_ports,
c16_t **txdataF)
c16_t **txdataF,
uint32_t linktype)
{
const int tx_offset = frame_parms->get_samples_slot_timestamp(slot, frame_parms, 0);
c16_t **txdata = UE->common_vars.txData;
LOG_D(NR_PHY,"Applying TX rotation for slot %d linktype %d\n",slot,linktype);
for(int ap = 0; ap < n_antenna_ports; ap++) {
apply_nr_rotation_TX(frame_parms,
txdataF[ap],
frame_parms->symbol_rotation[1],
frame_parms->symbol_rotation[linktype],
slot,
frame_parms->N_RB_UL,
0,

View File

@@ -59,14 +59,14 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
const fapi_nr_ul_config_pucch_pdu *pucch_pdu)
{
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch0] start function at slot(nr_slot_tx)=%d\n",nr_slot_tx);
LOG_I(NR_PHY, "\t [nr_generate_pucch0] start function at slot(nr_slot_tx)=%d\n", nr_slot_tx);
#endif
/*
* Implement TS 38.211 Subclause 6.3.2.3.1 Sequence generation
*
*/
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch0] sequence generation\n");
LOG_I(NR_PHY, "\t [nr_generate_pucch0] sequence generation\n");
#endif
/*
* Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2
@@ -91,11 +91,19 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
// the value of u,v (delta always 0 for PUCCH) has to be calculated according to TS 38.211 Subclause 6.3.2.2.1
uint8_t u[2]={0,0},v[2]={0,0};
LOG_D(PHY,"pucch0: slot %d nr_symbols %d, start_symbol %d, prb_start %d, second_hop_prb %d, group_hop_flag %d, sequence_hop_flag %d, mcs %d\n",
nr_slot_tx,pucch_pdu->nr_of_symbols,pucch_pdu->start_symbol_index,pucch_pdu->prb_start,pucch_pdu->second_hop_prb,pucch_pdu->group_hop_flag,pucch_pdu->sequence_hop_flag,pucch_pdu->mcs);
LOG_D(PHY, "pucch0: slot %d nr_symbols %d, start_symbol %d, prb_start %d, second_hop_prb %d, group_hop_flag %d, sequence_hop_flag %d, mcs %d bwp_start %d hopping_id %d\n",
nr_slot_tx, pucch_pdu->nr_of_symbols,
pucch_pdu->start_symbol_index,
pucch_pdu->prb_start,
pucch_pdu->second_hop_prb,
pucch_pdu->group_hop_flag,
pucch_pdu->sequence_hop_flag,
pucch_pdu->mcs,
pucch_pdu->bwp_start,
pucch_pdu->hopping_id);
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch0] sequence generation: variable initialization for test\n");
LOG_I(NR_PHY, "\t [nr_generate_pucch0] sequence generation: variable initialization for test\n");
#endif
// x_n contains the sequence r_u_v_alpha_delta(n)
int16_t x_n_re[2][24],x_n_im[2][24];
@@ -104,10 +112,10 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1);
// we proceed to calculate alpha according to TS 38.211 Subclause 6.3.2.2.2
int prb_offset[2]={startingPRB,startingPRB};
nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,0,nr_slot_tx,&u[0],&v[0]); // calculating u and v value
int prb_offset[2] = {startingPRB, startingPRB};
nr_group_sequence_hopping(pucch_GroupHopping, pucch_pdu->hopping_id, 0, nr_slot_tx, &u[0], &v[0]); // calculating u and v value
if (pucch_pdu->freq_hop_flag == 1) {
nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,1,nr_slot_tx,&u[1],&v[1]); // calculating u and v value
nr_group_sequence_hopping(pucch_GroupHopping, pucch_pdu->hopping_id, 1, nr_slot_tx, &u[1], &v[1]); // calculating u and v value
prb_offset[1] = pucch_pdu->second_hop_prb + pucch_pdu->bwp_start;
}
for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
@@ -117,7 +125,7 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
pucch_pdu->start_symbol_index,
nr_slot_tx);
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \t(for symbol l=%d)\n",u[l],v[l],alpha,l);
LOG_I(NR_PHY, "\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \t(for symbol l=%d)\n", u[l], v[l], alpha, l);
#endif
for (int n=0; n<12; n++) {
@@ -126,8 +134,8 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
x_n_im[l][n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u[l]][n])>>15)
+ (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u[l]][n])>>15))); // Im part of base sequence shifted by alpha
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \tx_n(l=%d,n=%d)=(%d,%d)\n",
u[l],v[l],alpha,l,n,x_n_re[l][n],x_n_im[l][n]);
LOG_I(NR_PHY, "\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \tx_n(l=%d,n=%d)=(%d, %d)\n",
u[l], v[l], alpha, l, n, x_n_re[l][n], x_n_im[l][n]);
#endif
}
}
@@ -140,15 +148,15 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
uint8_t l2;
for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
l2=l+pucch_pdu->start_symbol_index;
l2 = l + pucch_pdu->start_symbol_index;
re_offset = (12*prb_offset[l]) + frame_parms->first_carrier_offset;
if (re_offset>= frame_parms->ofdm_symbol_size)
re_offset-=frame_parms->ofdm_symbol_size;
if (re_offset >= frame_parms->ofdm_symbol_size)
re_offset -= frame_parms->ofdm_symbol_size;
//txptr = &txdataF[0][re_offset];
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch0] symbol %d PRB %d (%u)\n",l,prb_offset[l],re_offset);
#endif
LOG_I(NR_PHY, "\t [nr_generate_pucch0] symbol %d PRB %d (%u)\n", l, prb_offset[l], re_offset);
#endif
for (int n=0; n<12; n++) {
txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset].r = (int16_t)(((int32_t)(amp) * x_n_re[l][n])>>15);
@@ -157,14 +165,14 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
//((int16_t *)txptr[0][re_offset])[1] = (int16_t)((int32_t)amp * x_n_im[(12*l)+n])>>15;
//txptr[re_offset] = (x_n_re[(12*l)+n]<<16) + x_n_im[(12*l)+n];
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch0] mapping to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \ttxptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
LOG_I(NR_PHY, "\t [nr_generate_pucch0] mapping to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \ttxptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
amp, frame_parms->ofdm_symbol_size, frame_parms->N_RB_DL, frame_parms->first_carrier_offset, (l2 * frame_parms->ofdm_symbol_size) + re_offset,
l2, n, txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset].r,
txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset].i);
#endif
re_offset++;
if (re_offset>= frame_parms->ofdm_symbol_size)
re_offset-=frame_parms->ofdm_symbol_size;
if (re_offset >= frame_parms->ofdm_symbol_size)
re_offset -= frame_parms->ofdm_symbol_size;
}
}
}
@@ -645,7 +653,7 @@ static void nr_uci_encoding(uint64_t payload,
AssertFatal(nrofPRB<=16,"Number of PRB >16\n");
} else if (A>=12) {
AssertFatal(A<65,"Polar encoding not supported yet for UCI with more than 64 bits\n");
polar_encoder_fast(&payload, b, 0,0,
polar_encoder_fast(&payload, b, NULL,0,0,
NR_POLAR_UCI_PUCCH_MESSAGE_TYPE,
A,
nrofPRB);

View File

@@ -64,10 +64,11 @@ float Limits_KPI_gNB[4][2] = {
@UE: These are the (default) lower and upper threshold values for BLER and Throughput at the UE side.
These threshold values can be further updated in run-time through the option 'Configs' in the drop-down list
*/
float Limits_KPI_ue[2][2] = {
float Limits_KPI_ue[3][2] = {
// {lower Limit, Upper Limit}
{0.0, 0.8}, // DL BLER
{0.2, 10} // Throughput in Mbs
{0.2, 10}, // Throughput in Mbs
{0,60} //psbch RSRP db/RE
};
/* This class creates the window when choosing the option 'Configs' to configure the threshold values. */
@@ -176,6 +177,9 @@ KPIListSelectUE::KPIListSelectUE(QWidget *parent) : QComboBox(parent)
this->addItem("Time Adv.", static_cast<int>(PlotTypeUE::timingAdvance));
this->addItem("Configs", static_cast<int>(PlotTypeUE::config));
this->addItem("LLR PSBCH", static_cast<int>(PlotTypeUE::psbchLLR));
this->addItem("I/Q PSBCH", static_cast<int>(PlotTypeUE::psbchIQ));
this->addItem("PSBCH RSRP dB/RE", static_cast<int>(PlotTypeUE::psbchRSRP));
}
WaterFall::WaterFall(complex16 *values, NR_DL_FRAME_PARMS *frame_parms, QWidget *parent) : QWidget(parent), values(values), frame_parms(frame_parms)
@@ -891,6 +895,8 @@ float PainterWidgetUE::getValue()
case PlotTypeUE::timingAdvance:
return (float)this->ue->timing_advance;
case PlotTypeUE::psbchRSRP:
return (float)this->ue->SL_UE_PHY_PARAMS.psbch.rsrp_dB_per_RE;
default:
return 0;
@@ -901,15 +907,22 @@ scopeGraphData_t *PainterWidgetUE::getPlotValue()
{
scopeData_t *scope = (scopeData_t *)this->ue->scopeData;
scopeGraphData_t **data = (scopeGraphData_t **)scope->liveData;
bool is_sl = this->ue->sl_mode;
switch (this->plotType) {
case PlotTypeUE::CIR:
return data[pbchDlChEstimateTime];
return (is_sl ? data[psbchDlChEstimateTime] : data[pbchDlChEstimateTime]);
case PlotTypeUE::pbchLLR:
return data[pbchLlr];
case PlotTypeUE::pbchIQ:
return data[pbchRxdataF_comp];
case PlotTypeUE::psbchLLR:
return data[psbchLlr];
case PlotTypeUE::psbchIQ:
return data[psbchRxdataF_comp];
case PlotTypeUE::pdcchLLR:
return data[pdcchLlr];
@@ -980,13 +993,14 @@ void PainterWidgetUE::makeConnections(int type)
break;
}
case PlotTypeUE::CIR: {
if (!data[pbchDlChEstimateTime]) {
enum scopeDataType typ = (this->ue->sl_mode) ? psbchDlChEstimateTime : pbchDlChEstimateTime;
if (!data[typ]) {
newChart = new QChart();
this->plotType = PlotTypeUE::empty;
this->comboBox->setCurrentIndex(static_cast<int>(PlotTypeUE::empty));
break;
}
newChart = new CIRPlot((complex16 *)(data[pbchDlChEstimateTime] + 1), data[pbchDlChEstimateTime]->lineSz);
newChart = new CIRPlot((complex16 *)(data[typ] + 1), data[typ]->lineSz);
break;
}
@@ -1010,6 +1024,26 @@ void PainterWidgetUE::makeConnections(int type)
newChart = new IQPlotUE((complex16 *)(data[pbchRxdataF_comp] + 1), data[pbchRxdataF_comp]->lineSz, this);
break;
}
case PlotTypeUE::psbchLLR: {
if (!data[psbchLlr]) {
newChart = new QChart();
this->plotType = PlotTypeUE::empty;
this->comboBox->setCurrentIndex(static_cast<int>(PlotTypeUE::empty));
break;
}
newChart = new LLRPlotUE((int16_t *)(data[psbchLlr] + 1), data[psbchLlr]->lineSz, this);
break;
}
case PlotTypeUE::psbchIQ: {
if (!data[psbchRxdataF_comp]) {
newChart = new QChart();
this->plotType = PlotTypeUE::empty;
this->comboBox->setCurrentIndex(static_cast<int>(PlotTypeUE::empty));
break;
}
newChart = new IQPlotUE((complex16 *)(data[psbchRxdataF_comp] + 1), data[psbchRxdataF_comp]->lineSz, this);
break;
}
case PlotTypeUE::pdcchLLR: {
if (!data[pdcchLlr]) {
newChart = new QChart();
@@ -1079,7 +1113,10 @@ void PainterWidgetUE::makeConnections(int type)
newChart = new KPIPlot(this);
break;
}
case PlotTypeUE::psbchRSRP: {
newChart = new KPIPlot(this,Limits_KPI_ue[2]);
break;
}
default:
break;
}
@@ -1164,6 +1201,7 @@ void *nrgNBQtscopeThread(void *arg)
void *nrUEQtscopeThread(void *arg)
{
PHY_VARS_NR_UE *ue = (PHY_VARS_NR_UE *)arg;
bool is_sl = ue->sl_mode;
sleep(1);
@@ -1197,14 +1235,16 @@ void *nrUEQtscopeThread(void *arg)
mainLayout.addWidget(&pwidgetueCombo2, 1, 1);
KPIListSelectUE combo3;
combo3.setCurrentIndex(static_cast<int>(PlotTypeUE::pbchLLR));
if (is_sl) combo3.setCurrentIndex(static_cast<int>(PlotTypeUE::psbchLLR));
else combo3.setCurrentIndex(static_cast<int>(PlotTypeUE::psbchLLR));
PainterWidgetUE pwidgetueCombo3(&config, &combo3, ue);
mainLayout.addWidget(&combo3, 2, 0);
mainLayout.addWidget(&pwidgetueCombo3, 3, 0);
KPIListSelectUE combo4;
combo4.setCurrentIndex(static_cast<int>(PlotTypeUE::pbchIQ));
if (is_sl) combo4.setCurrentIndex(static_cast<int>(PlotTypeUE::psbchIQ));
else combo4.setCurrentIndex(static_cast<int>(PlotTypeUE::psbchIQ));
PainterWidgetUE pwidgetueCombo4(&config, &combo4, ue);
mainLayout.addWidget(&combo4, 2, 1);

View File

@@ -81,7 +81,10 @@ enum class PlotTypeUE {
pdschRBs,
frequencyOffset,
timingAdvance,
config
config,
psbchLLR,
psbchIQ,
psbchRSRP,
};
/// This abstract class defines an interface how the KPIPlot class can access values for the different KPI plot types

View File

@@ -771,14 +771,17 @@ static void ueTimeResponse (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int
*/
static void ueChannelResponse (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
enum scopeDataType typ = (phy_vars_ue->sl_mode) ? psbchDlChEstimateTime : pbchDlChEstimateTime;
// Channel Impulse Response
if (!data[pbchDlChEstimateTime])
if (!data[typ])
return;
const scopeSample_t *tmp=(scopeSample_t *)(data[pbchDlChEstimateTime]+1);
genericPowerPerAntena(graph, data[pbchDlChEstimateTime]->colSz,
const scopeSample_t *tmp=(scopeSample_t *)(data[typ]+1);
genericPowerPerAntena(graph, data[typ]->colSz,
&tmp,
data[pbchDlChEstimateTime]->lineSz);
data[typ]->lineSz);
}
static void ueFreqWaterFall (scopeGraphData_t **data, OAIgraph_t *graph,PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id ) {
@@ -832,14 +835,17 @@ static void uePbchFrequencyResp (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue
}
*/
static void uePbchLLR (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
enum scopeDataType typ = (phy_vars_ue->sl_mode) ? psbchLlr : pbchLlr;
// PBCH LLRs
if ( !data[pbchLlr])
if ( !data[typ])
return;
const int sz=data[pbchLlr]->lineSz;
//const int antennas=data[pbchLlr]->colSz;
const int sz=data[typ]->lineSz;
//const int antennas=data[typ]->colSz;
// We take the first antenna only for now
int16_t *llrs = (int16_t *) (data[pbchLlr]+1);
int16_t *llrs = (int16_t *) (data[typ]+1);
float *llr_pbch=NULL, *bit_pbch=NULL;
int nx = sz;
#ifdef WEBSRVSCOPE
@@ -855,12 +861,15 @@ static void uePbchLLR (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_
}
static void uePbchIQ (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
enum scopeDataType typ = (phy_vars_ue->sl_mode) ? psbchRxdataF_comp : pbchRxdataF_comp;
// PBCH I/Q of MF Output
if (!data[pbchRxdataF_comp])
if (!data[typ])
return;
scopeSample_t *pbch_comp = (scopeSample_t *) (data[pbchRxdataF_comp]+1);
const int sz=data[pbchRxdataF_comp]->lineSz;
scopeSample_t *pbch_comp = (scopeSample_t *) (data[typ]+1);
const int sz=data[typ]->lineSz;
int newsz = sz;
float *I=NULL, *Q=NULL;
#ifdef WEBSRVSCOPE

View File

@@ -67,6 +67,9 @@ enum scopeDataType {
pdschRxdataF_comp,
commonRxdataF,
gNBRxdataF,
psbchDlChEstimateTime,
psbchLlr,
psbchRxdataF_comp,
MAX_SCOPE_TYPES
};

View File

@@ -47,7 +47,7 @@
#include <execinfo.h>
#include <getopt.h>
#include <sys/sysinfo.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

View File

@@ -34,6 +34,7 @@
#define __PHY_DEFS_GNB__H__
#include "defs_nr_common.h"
#include "defs_nr_UE.h"
#include "CODING/nrPolar_tools/nr_polar_pbch_defs.h"
#include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h"
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
@@ -43,6 +44,7 @@
#include "PHY/CODING/nrLDPC_decoder/nrLDPC_types.h"
#include "executables/rt_profiling.h"
#include "nfapi_nr_interface_scf.h"
#include "sidelink_nr_ue_interface.h"
#define MAX_NUM_RU_PER_gNB 8
#define MAX_PUCCH0_NID 8
@@ -188,6 +190,10 @@ typedef struct {
typedef struct {
/// Nfapi ULSCH PDU
nfapi_nr_pusch_pdu_t ulsch_pdu;
/// PSSCH PDU
sl_nr_rx_config_pssch_sci_pdu_t *pssch_pdu;
/// SLSCH PDU
sl_nr_rx_config_pssch_pdu_t *slsch_pdu;
/// Index of current HARQ round for this DLSCH
uint8_t round;
bool new_rx;
@@ -264,7 +270,7 @@ typedef struct {
int pusch_delay_max_val;
} NR_ULSCH_delay_t;
typedef struct {
typedef struct NR_gNB_ULSCH_s {
uint32_t frame;
uint32_t slot;
/// Pointers to 16 HARQ processes for the ULSCH
@@ -325,7 +331,7 @@ typedef struct {
} NR_gNB_COMMON;
typedef struct {
typedef struct NR_gNB_PUSCH_s {
/// \brief Holds the received data in the frequency domain for the allocated RBs in repeated format.
/// - first index: rx antenna id [0..nb_antennas_rx[
/// - second index: ? [0..2*ofdm_symbol_size[
@@ -548,7 +554,7 @@ typedef struct gNB_L1_proc_t_s {
gNB_L1_rxtx_proc_t L1_proc, L1_proc_tx;
} gNB_L1_proc_t;
typedef struct {
typedef struct PHY_MEASUREMENTS_gNB_s {
// common measurements
//! estimated noise power (linear)
unsigned int n0_power[MAX_NUM_RU_PER_gNB];
@@ -782,6 +788,7 @@ typedef struct PHY_VARS_gNB_s {
typedef struct LDPCDecode_s {
PHY_VARS_gNB *gNB;
struct PHY_VARS_NR_UE_s *UE;
NR_UL_gNB_HARQ_t *ulsch_harq;
t_nrLDPC_dec_params decoderParms;
NR_gNB_ULSCH_t *ulsch;

View File

@@ -37,8 +37,10 @@
#define _Atomic(X) std::atomic< X >
#endif
#include "defs_nr_common.h"
#include "PHY/defs_nr_common.h"
#include "PHY/defs_gNB.h"
#include "CODING/nrPolar_tools/nr_polar_pbch_defs.h"
#include "PHY/defs_nr_sl_UE.h"
#include <stdio.h>
#include <stdlib.h>
@@ -48,6 +50,7 @@
#include "common_lib.h"
#include "fapi_nr_ue_interface.h"
#include "assertions.h"
#include <stdbool.h>
#ifdef MEX
#define msg mexPrintf
@@ -94,6 +97,8 @@
#include "impl_defs_top.h"
#include "impl_defs_nr.h"
// This is for ULSCH RX structures used for Sidelink
#include "defs_gNB.h"
#include "time_meas.h"
#include "PHY/CODING/coding_defs.h"
#include "PHY/TOOLS/tools_defs.h"
@@ -108,6 +113,14 @@
#include "radio/COMMON/common_lib.h"
#include "NR_IF_Module.h"
#define MAX_PUCCH0_NID 8
typedef struct {
int nb_id;
int Nid[MAX_PUCCH0_NID];
int lut[MAX_PUCCH0_NID][160][14];
} NR_UE_PUCCH0_LUT_t;
/// Context data structure for gNB subframe processing
typedef struct {
/// Component Carrier index
@@ -309,7 +322,7 @@ typedef struct {
#define NR_PSBCH_MAX_NB_MOD_SYMBOLS 99
#define NR_PSBCH_DMRS_LENGTH 297 // in mod symbols
#define NR_PSBCH_DMRS_LENGTH_DWORD 20 // ceil(2(QPSK)*NR_PBCH_DMRS_LENGTH/32)
#define NR_SLSCH_RX_MAX 2
/* NR Sidelink PSBCH payload fields
TODO: This will be removed in the future and
filled in by the upper layers once developed. */
@@ -362,7 +375,7 @@ typedef struct UE_NR_SCAN_INFO_s {
} UE_NR_SCAN_INFO_t;
/// Top-level PHY Data Structure for UE
typedef struct {
typedef struct PHY_VARS_NR_UE_s {
/// \brief Module ID indicator for this instance
uint8_t Mod_id;
/// \brief Component carrier ID for this PHY instance
@@ -435,7 +448,7 @@ typedef struct {
uint8_t prs_active_gNBs;
NR_DL_UE_HARQ_t dl_harq_processes[2][NR_MAX_DLSCH_HARQ_PROCESSES];
NR_UL_UE_HARQ_t ul_harq_processes[NR_MAX_ULSCH_HARQ_PROCESSES];
NR_UL_UE_HARQ_t sl_harq_processes[NR_MAX_SLSCH_HARQ_PROCESSES];
//Paging parameters
uint32_t IMSImod1024;
uint32_t PF;
@@ -649,6 +662,25 @@ typedef struct {
notifiedFIFO_t phy_config_ind;
notifiedFIFO_t *tx_resume_ind_fifo[NR_MAX_SLOTS_PER_FRAME];
int tx_wait_for_dlsch[NR_MAX_SLOTS_PER_FRAME];
//Sidelink parameters
sl_nr_sidelink_mode_t sl_mode;
sl_nr_ue_phy_params_t SL_UE_PHY_PARAMS;
struct PHY_MEASUREMENTS_gNB_s *sl_measurements;
int max_nb_slsch;
// we use the gNB ULSCH context for SLSCH reception
struct NR_gNB_ULSCH_s *slsch;
struct NR_gNB_PUSCH_s *pssch_vars;
bool phy_config_request_sent;
int pscch_dmrs_gold_init;
/// PDCCH DMRS for TX
uint32_t ***nr_gold_pscch_dmrs;
/// PSCCH DMRS for RX
uint32_t ***nr_gold_pscch;
/// PSSCH signal detection threshold
int pssch_thres;
// PUCCH0 Look-up table for cyclic-shifts
NR_UE_PUCCH0_LUT_t pucch0_lut;
} PHY_VARS_NR_UE;
typedef struct {
@@ -670,11 +702,27 @@ typedef struct {
typedef struct nr_phy_data_tx_s {
NR_UE_ULSCH_t ulsch;
NR_UE_PUCCH pucch_vars;
//Sidelink Tx action decided by MAC
sl_nr_tx_config_type_enum_t sl_tx_action;
sl_nr_tx_config_psbch_pdu_t psbch_vars;
sl_nr_tx_config_pscch_pssch_pdu_t nr_sl_pssch_pscch_pdu;
uint32_t pscch_Nid;
} nr_phy_data_tx_t;
typedef struct nr_phy_data_s {
bool active;
NR_UE_PDCCH_CONFIG phy_pdcch_config;
NR_UE_DLSCH_t dlsch[2];
//Sidelink Rx action decided by MAC
sl_nr_rx_config_type_enum_t sl_rx_action;
sl_nr_rx_config_pscch_pdu_t nr_sl_pscch_pdu;
sl_nr_rx_config_pssch_sci_pdu_t nr_sl_pssch_sci_pdu;
sl_nr_rx_config_pssch_pdu_t nr_sl_pssch_pdu;
sl_nr_tti_csi_rs_pdu_t nr_sl_csi_rs_pdu;
sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu_list;
uint8_t num_psfch_pdus;
} nr_phy_data_t;
/* this structure is used to pass both UE phy vars and
* proc to the function UE_thread_rxn_txnp4

View File

@@ -169,8 +169,6 @@ struct NR_DL_FRAME_PARMS {
/// Frame type (0 FDD, 1 TDD)
frame_type_t frame_type;
uint8_t tdd_config;
/// Sidelink Cell ID
uint16_t Nid_SL;
/// Cell ID
uint16_t Nid_cell;
/// subcarrier spacing (15,30,60,120)
@@ -306,4 +304,34 @@ typedef struct {
#define KHz (1000UL)
#define MHz (1000*KHz)
static const int16_t idft12_re[12][12] = {
{23170,23170,23170,23170,23170,23170,23170,23170,23170,23170,23170,23170},
{23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585,0,11585,20066},
{23170,11585,-11585,-23170,-11585,11585,23170,11585,-11585,-23170,-11585,11585},
{23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170,0},
{23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585},
{23170,-20066,11585,0,-11585,20066,-23170,20066,-11585,0,11585,-20066},
{23170,-23170,23170,-23170,23170,-23170,23170,-23170,23170,-23170,23170,-23170},
{23170,-20066,11585,0,-11585,20066,-23170,20066,-11585,0,11585,-20066},
{23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585},
{23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170,0},
{23170,11585,-11585,-23170,-11585,11585,23170,11585,-11585,-23170,-11585,11585},
{23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585,0,11585,20066}
};
static const int16_t idft12_im[12][12] = {
{0,0,0,0,0,0,0,0,0,0,0,0},
{0,11585,20066,23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585},
{0,20066,20066,0,-20066,-20066,0,20066,20066,0,-20066,-20066},
{0,23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170},
{0,20066,-20066,0,20066,-20066,0,20066,-20066,0,20066,-20066},
{0,11585,-20066,23170,-20066,11585,0,-11585,20066,-23170,20066,-11585},
{0,0,0,0,0,0,0,0,0,0,0,0},
{0,-11585,20066,-23170,20066,-11585,0,11585,-20066,23170,-20066,11585},
{0,-20066,20066,0,-20066,20066,0,-20066,20066,0,-20066,20066},
{0,-23170,0,23170,0,-23170,0,23170,0,-23170,0,23170},
{0,-20066,-20066,0,20066,20066,0,-20066,-20066,0,20066,20066},
{0,-11585,-20066,-23170,-20066,-11585,0,11585,20066,23170,20066,11585}
};
#endif

View File

@@ -0,0 +1,223 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file PHY/defs_nr_sl_UE.h
\brief Top-level defines and structure definitions
\author
\date
\version
\company Fraunhofer
\email:
\note
\warning
*/
#ifndef _DEFS_NR_SL_UE_H_
#define _DEFS_NR_SL_UE_H_
#include "PHY/types.h"
#include "PHY/defs_nr_common.h"
#include "nfapi/open-nFAPI/nfapi/public_inc/sidelink_nr_ue_interface.h"
#include "common/utils/time_meas.h"
// (33*(13-4))
// Normal CP - NUM_SSB_Symbols = 13. 4 symbols for PSS, SSS
#define SL_NR_NUM_PSBCH_DMRS_RE 297
//ceil(2(QPSK)*SL_NR_NUM_PSBCH_DMRS_RE/32)
#define SL_NR_NUM_PSBCH_DMRS_RE_DWORD 20
//11 RBs for PSBCH in one symbol * 12 REs
#define SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL 132
//3 DMRS REs per RB * 11 RBS in one symbol
#define SL_NR_NUM_PSBCH_DMRS_RE_IN_ONE_SYMBOL 33
//9 PSBCH DATA REs * 11 RBS in one symbol
#define SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL 99
#define SL_NR_NUM_PSBCH_RBS_IN_ONE_SYMBOL 11
// SL_NR_POLAR_PSBCH_E_NORMAL_CP/2 bits because QPSK used for PSBCH.
// 11 * (12-3 DMRS REs) * 9 symbols for PSBCH
#define SL_NR_NUM_PSBCH_MODULATED_SYMBOLS 891
#define SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_RB 9
#define SL_NR_NUM_PSBCH_DMRS_RE_IN_ONE_RB 3
// 11 * (12-3 DMRS REs) * 9 symbols for PSBCH
#define SL_NR_NUM_PSBCH_DATA_RE_IN_ALL_SYMBOLS 891
#define SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP 13
#define SL_NR_NUM_SYMBOLS_SSB_EXT_CP 11
#define SL_NR_NUM_PSS_SYMBOLS 2
#define SL_NR_NUM_SSS_SYMBOLS 2
#define SL_NR_PSS_START_SYMBOL 1
#define SL_NR_SSS_START_SYMBOL 3
#define SL_NR_NUM_PSS_OR_SSS_SYMBOLS 2
#define SL_NR_PSS_SEQUENCE_LENGTH 127
#define SL_NR_SSS_SEQUENCE_LENGTH 127
#define SL_NR_NUM_IDs_IN_PSS 2
#define SL_NR_NUM_IDs_IN_SSS 336
#define SL_NR_NUM_SLSS_IDs 672
#define SL_NR_PSBCH_REPETITION_IN_FRAMES 16
typedef enum sl_nr_sidelink_mode {
SL_NOT_SUPPORTED = 0,
SL_MODE1_SUPPORTED,
SL_MODE2_SUPPORTED
} sl_nr_sidelink_mode_t;
//(11*(12-3 DMRS REs) * 2 (QPSK used)
#define SL_NR_NUM_PSBCH_DATA_BITS_IN_ONE_SYMBOL 198
typedef struct SL_NR_UE_INIT_PARAMS {
//gold sequences for PSBCH DMRS
uint32_t psbch_dmrs_gold_sequences[SL_NR_NUM_SLSS_IDs][SL_NR_NUM_PSBCH_DMRS_RE_DWORD]; // Gold sequences for PSBCH DMRS
//PSBCH DMRS QPSK modulated symbols for all possible SLSS Ids
struct complex16 psbch_dmrs_modsym[SL_NR_NUM_SLSS_IDs][SL_NR_NUM_PSBCH_DMRS_RE];
// Scaled values
int16_t sl_pss[SL_NR_NUM_IDs_IN_PSS][SL_NR_PSS_SEQUENCE_LENGTH];
int16_t sl_sss[SL_NR_NUM_SLSS_IDs][SL_NR_SSS_SEQUENCE_LENGTH];
// Contains Not scaled values just the simple generated sequence
int16_t sl_pss_for_sync[SL_NR_NUM_IDs_IN_PSS][SL_NR_PSS_SEQUENCE_LENGTH];
int16_t sl_sss_for_sync[SL_NR_NUM_SLSS_IDs][SL_NR_SSS_SEQUENCE_LENGTH];
int32_t **sl_pss_for_correlation; // IFFT samples for correlation
} SL_NR_UE_INIT_PARAMS_t;
typedef struct SL_NR_SYNC_PARAMS {
// Indicating start of SSB block in the initial set of samples
uint32_t ssb_offset;
// Freq Offset calculated
int32_t freq_offset;
uint32_t remaining_frames;
uint32_t rx_offset;
uint32_t slot_offset;
uint16_t N_sl_id2; //id2 determined from PSS during sync ref UE selection
uint16_t N_sl_id1; //id2 determined from SSS during sync ref UE selection
uint16_t N_sl_id; //ID calculated from ID1 and ID2
int32_t psbch_rsrp; //rsrp of the decoded psbch during sync ref ue selection
uint32_t DFN; // DFN calculated after sync ref UE search
} SL_NR_SYNC_PARAMS_t;
typedef struct SL_NR_UE_PSSCH {
// AVG POWER OF PSSCH DMRS in dB/RE
int16_t rsrp_dB_per_RE;
// AVG POWER OF PSSCH DMRS in dBm/RE
int16_t rsrp_dBm_per_RE;
// STATS - CRC Errors observed during PSSCH reception (per HARQ round)
uint32_t rx_errors[8];
// STATS - CRC Errors observed during PSSCH SCI2 reception
uint32_t rx_sci2_errors;
// STATS - Receptions with CRC OK
uint32_t rx_ok;
// STATS - Receptions with CRC OK
uint32_t rx_sci2_ok;
// STATS - transmissions of PSSCH by the UE
uint32_t num_pssch_tx;
// STATS - transmissions of PSSCH by the UE
uint32_t num_pssch_sci2_tx;
} SL_NR_UE_PSSCH_t;
typedef struct SL_NR_UE_PSCCH {
// AVG POWER OF PSCCH DMRS in dB/RE
int16_t rsrp_dB_per_RE;
// AVG POWER OF PSCCH DMRS in dBm/RE
int16_t rsrp_dBm_per_RE;
// STATS - Receptions with CRC OK
uint32_t rx_ok;
// STATS - transmissions of PSBCH by the UE
uint32_t num_pscch_tx;
} SL_NR_UE_PSCCH_t;
typedef struct SL_NR_UE_PSBCH {
// AVG POWER OF PSBCH DMRS in dB/RE
int16_t rsrp_dB_per_RE;
// AVG POWER OF PSBCH DMRS in dBm/RE
int16_t rsrp_dBm_per_RE;
// STATS - CRC Errors observed during PSBCH reception
uint32_t rx_errors;
// STATS - Receptions with CRC OK
uint32_t rx_ok;
// STATS - transmissions of PSBCH by the UE
uint32_t num_psbch_tx;
} SL_NR_UE_PSBCH_t;
typedef struct SL_NR_UE_PSFCH {
// STATS - transmissions of PSFCH by the UE
uint32_t num_psfch_tx;
uint32_t num_psfch_rx;
} SL_NR_UE_PSFCH_t;
typedef struct sl_nr_ue_phy_params {
SL_NR_UE_INIT_PARAMS_t init_params;
SL_NR_SYNC_PARAMS_t sync_params;
// sidelink phy parameters used for psbch reception/txn
SL_NR_UE_PSBCH_t psbch;
// sidelink phy parameters used for pscch reception/txn
SL_NR_UE_PSCCH_t pscch;
// sidelink phy parameters used for pssch reception/txn
SL_NR_UE_PSSCH_t pssch;
// sidelink phy parameters used for psfch reception/txn
SL_NR_UE_PSFCH_t psfch;
//Configuration parameters from MAC
sl_nr_phy_config_request_t sl_config;
NR_DL_FRAME_PARMS sl_frame_params;
time_stats_t phy_proc_sl_tx;
time_stats_t phy_proc_sl_rx;
time_stats_t channel_estimation_stats;
time_stats_t ue_sl_indication_stats;
} sl_nr_ue_phy_params_t;
#endif

View File

@@ -98,6 +98,8 @@ SystemInformationBlockType1_nr_t;
#define NR_DOWNLINK_SLOT (0x01)
#define NR_UPLINK_SLOT (0x02)
#define NR_MIXED_SLOT (0x03)
#define NR_SIDELINK_SLOT (0x04)
#define NON_NR_SIDELINK_SLOT (0x05)
#define FRAME_DURATION_MICRO_SEC (10000) /* frame duration in microsecond */

View File

@@ -270,7 +270,7 @@
/* FFS_NR_TODO it defines ue capability which is the number of slots */
/* - between reception of pdsch and tarnsmission of its acknowlegment */
/* - between reception of un uplink grant and its related transmission */
#define NR_UE_CAPABILITY_SLOT_RX_TO_TX (3)
#define NR_UE_CAPABILITY_SLOT_RX_TO_TX (4)
#ifndef NO_RAT_NR
#define DURATION_RX_TO_TX (NR_UE_CAPABILITY_SLOT_RX_TO_TX) /* for NR this will certainly depends to such UE capability which is not yet defined */
@@ -280,6 +280,7 @@
#define NR_MAX_ULSCH_HARQ_PROCESSES (NR_MAX_HARQ_PROCESSES) /* cf 38.214 6.1 UE procedure for receiving the physical uplink shared channel */
#define NR_MAX_DLSCH_HARQ_PROCESSES (NR_MAX_HARQ_PROCESSES) /* cf 38.214 5.1 UE procedure for receiving the physical downlink shared channel */
#define NR_MAX_SLSCH_HARQ_PROCESSES (NR_MAX_HARQ_PROCESSES)
#endif
/// Data structure for transmission.

View File

@@ -281,7 +281,7 @@ static void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
ulsch->active = false;
ulsch_harq->round = 0;
LOG_D(PHY, "ULSCH received ok \n");
nr_fill_indication(gNB, ulsch->frame, ulsch->slot, rdata->ulsch_id, rdata->harq_pid, 0, 0);
nr_fill_indication((void*)gNB, ulsch->frame, ulsch->slot, rdata->ulsch_id, rdata->harq_pid, 0, 0);
//dumpsig=1;
} else {
LOG_D(PHY,
@@ -301,7 +301,7 @@ static void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
r);
ulsch->handled = 1;
LOG_D(PHY, "ULSCH %d in error\n",rdata->ulsch_id);
nr_fill_indication(gNB, ulsch->frame, ulsch->slot, rdata->ulsch_id, rdata->harq_pid, 1, 0);
nr_fill_indication((void*)gNB, ulsch->frame, ulsch->slot, rdata->ulsch_id, rdata->harq_pid, 1, 0);
// dumpsig=1;
}
ulsch->last_iteration_cnt = rdata->decodeIterations;
@@ -406,14 +406,15 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int
start_meas(&gNB->ulsch_decoding_stats);
int nbDecode =
nr_ulsch_decoding(gNB, ULSCH_id, gNB->pusch_vars[ULSCH_id].llr, frame_parms, pusch_pdu, frame_rx, slot_rx, harq_pid, G);
nr_ulsch_decoding(gNB, NULL, ULSCH_id, gNB->pusch_vars[ULSCH_id].llr, frame_parms, pusch_pdu, frame_rx, slot_rx, harq_pid, G, NULL, NULL, NULL, -1);
stop_meas(&gNB->ulsch_decoding_stats);
return nbDecode;
}
void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, uint8_t harq_pid, uint8_t crc_flag, int dtx_flag)
void nr_fill_indication(void* p, int frame, int slot_rx, int ULSCH_id, uint8_t harq_pid, uint8_t crc_flag, int dtx_flag)
{
PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)p;
if (!get_softmodem_params()->reorder_thread_disable)
pthread_mutex_lock(&gNB->UL_INFO_mutex);
@@ -889,7 +890,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH, 1);
start_meas(&gNB->rx_pusch_stats);
nr_rx_pusch(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid);
nr_rx_pusch(gNB, NULL, gNB->common_vars.rxdataF, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid);
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ULSCH_id];
pusch_vars->ulsch_power_tot = 0;
pusch_vars->ulsch_noise_power_tot = 0;

View File

@@ -30,7 +30,7 @@
#define __openair_SCHED_H__
#include "PHY/defs_nr_UE.h"
#include <stdbool.h>
/*enum THREAD_INDEX { OPENAIR_THREAD_INDEX = 0,
TOP_LEVEL_SCHEDULER_THREAD_INDEX,
@@ -181,15 +181,52 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
int pscch_flag,
int32_t pdcch_est_size,
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
nr_phy_data_t *phy_data,
int n_ss,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
int16_t *rsrp_dBm);
int nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
int get_nRECSI_RS(uint8_t freq_density,
uint16_t nr_of_rbs);
void psbch_pscch_pssch_processing(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
nr_phy_data_t *phy_data);
int phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
nr_phy_data_tx_t *phy_data);
/*! \brief This function prepares the sl indication to pass to the MAC
*/
void nr_fill_sl_indication(nr_sidelink_indication_t *sl_ind,
sl_nr_rx_indication_t *rx_ind,
sl_nr_sci_indication_t *sci_ind,
UE_nr_rxtx_proc_t *proc,
PHY_VARS_NR_UE *ue,
void *phy_data);
void nr_fill_sl_rx_indication(sl_nr_rx_indication_t *rx_ind,
uint8_t pdu_type,
PHY_VARS_NR_UE *ue,
uint16_t n_pdus,
UE_nr_rxtx_proc_t *proc,
void *typeSpecific,
uint16_t rx_slss_id);
void nr_postDecode_slsch(PHY_VARS_NR_UE *UE, notifiedFIFO_elt_t *req,
UE_nr_rxtx_proc_t *proc,
nr_phy_data_t *phy_data,
int8_t *ack_nack_rcvd,
uint8_t num_acks);
typedef struct {
ldpcDecode_t *rdata;
bool rxok;
} slsch_status_t;
#endif

View File

@@ -389,7 +389,12 @@ void configure_ta_command(PHY_VARS_NR_UE *ue, fapi_nr_ta_command_pdu *ta_command
int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){
bool found = false;
if(scheduled_response != NULL){
if (scheduled_response->sl_rx_config || scheduled_response->sl_tx_config) {
sl_handle_scheduled_response(scheduled_response);
return 0;
}
module_id_t module_id = scheduled_response->module_id;
uint8_t cc_id = scheduled_response->CC_id;
@@ -661,3 +666,141 @@ void nr_ue_synch_request(nr_synch_request_t *synch_request)
PHY_vars_UE_g[synch_request->Mod_id][synch_request->CC_id]->synch_request.received_synch_request = 1;
}
int8_t nr_ue_sl_phy_config_request(nr_sl_phy_config_t *phy_config)
{
sl_nr_phy_config_request_t *sl_config = &PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->SL_UE_PHY_PARAMS.sl_config;
if(phy_config != NULL) {
memcpy(sl_config,&phy_config->sl_config_req,sizeof(sl_nr_phy_config_request_t));
PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->phy_config_request_sent = true;
}
return 0;
}
/*
* MAC sends the scheduled response with either TX configrequest for Sidelink Transmission requests
* or RX config request for Sidelink Reception requests.
* This procedure handles these TX/RX config requests received in this slot and configures PHY
* with a TTI action to be performed in this slot(TTI)
*/
int8_t sl_handle_scheduled_response(nr_scheduled_response_t *scheduled_response) {
module_id_t module_id = scheduled_response->module_id;
uint8_t cc_id = scheduled_response->CC_id;
uint32_t slot = scheduled_response->slot;
uint32_t frame = scheduled_response->frame;
const char *sl_rx_action[] = {"NONE", "RX_PSBCH", "RX_PSCCH", "RX_SCI2_ON_PSSCH", "RX_SLSCH_ON_PSSCH", "RX_PSFCH", "RX_SLSCH_ON_PSSCH_CSI_RS"};
const char *sl_tx_action[] = {"TX_PSBCH", "TX_PSCCH_PSSCH", "TX_PSCCH_PSSCH_PSFCH", "TX_PSCCH_PSSCH_CSI_RS"};
NR_UE_CSI_RS *csirs_vars = PHY_vars_UE_g[module_id][cc_id]->csirs_vars[0];
if(scheduled_response->sl_rx_config != NULL) {
sl_nr_rx_config_request_t *sl_rx_config = scheduled_response->sl_rx_config;
nr_phy_data_t *phy_data = (nr_phy_data_t *)scheduled_response->phy_data;
sl_nr_tti_csi_rs_pdu_t *csirs_config_pdu;
AssertFatal(sl_rx_config->number_pdus == SL_NR_RX_CONFIG_LIST_NUM,
"sl_rx_config->number_pdus incorrect\n");
switch(sl_rx_config->sl_rx_config_list[0].pdu_type) {
case SL_NR_CONFIG_TYPE_RX_PSBCH:
phy_data->sl_rx_action = SL_NR_CONFIG_TYPE_RX_PSBCH;
LOG_D(PHY, "Recvd CONFIG_TYPE_RX_PSBCH\n");
break;
case SL_NR_CONFIG_TYPE_RX_PSCCH:
phy_data->sl_rx_action = SL_NR_CONFIG_TYPE_RX_PSCCH;
phy_data->nr_sl_pscch_pdu = sl_rx_config->sl_rx_config_list[0].rx_pscch_config_pdu;
LOG_D(NR_PHY, "Recvd CONFIG_TYPE_RX_PSCCH\n");
break;
case SL_NR_CONFIG_TYPE_RX_PSSCH_SCI:
phy_data->sl_rx_action = SL_NR_CONFIG_TYPE_RX_PSSCH_SCI;
phy_data->nr_sl_pssch_sci_pdu = sl_rx_config->sl_rx_config_list[0].rx_sci2_config_pdu;
LOG_D(NR_PHY, "Recvd CONFIG_TYPE_RX_PSSCH_SCI\n");
break;
case SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH:
case SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_PSFCH:
case SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_CSI_RS:
phy_data->sl_rx_action = sl_rx_config->sl_rx_config_list[0].pdu_type;
phy_data->nr_sl_pssch_pdu = sl_rx_config->sl_rx_config_list[0].rx_pssch_config_pdu;
LOG_D(NR_PHY, "%4d.%2d Recvd %s\n", frame, slot, sl_rx_action[phy_data->sl_rx_action]);
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_CSI_RS) {
csirs_config_pdu = &sl_rx_config->sl_rx_config_list[0].rx_csi_rs_config_pdu;
memcpy((void*)&(csirs_vars->csirs_config_pdu), (void*)csirs_config_pdu, sizeof(sl_nr_tti_csi_rs_pdu_t));
csirs_vars->active = true;
}
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_PSFCH) {
phy_data->psfch_pdu_list = calloc(sl_rx_config->sl_rx_config_list[0].num_psfch_pdus, sizeof(sl_nr_tx_rx_config_psfch_pdu_t));
memcpy((void*)phy_data->psfch_pdu_list, (void*)sl_rx_config->sl_rx_config_list[0].rx_psfch_pdu_list,
sl_rx_config->sl_rx_config_list[0].num_psfch_pdus * sizeof(sl_nr_tx_rx_config_psfch_pdu_t));
phy_data->num_psfch_pdus = sl_rx_config->sl_rx_config_list[0].num_psfch_pdus;
}
break;
default:
AssertFatal(0,"Incorrect sl_rx config req pdutype \n");
break;
}
LOG_D(PHY, "[UE%d] TTI %d:%d, SL-RX action:%s\n",
module_id,frame,slot,
sl_rx_action[phy_data->sl_rx_action]);
} else if(scheduled_response->sl_tx_config != NULL) {
sl_nr_tx_config_request_t *sl_tx_config = scheduled_response->sl_tx_config;
nr_phy_data_tx_t *phy_data_tx = (nr_phy_data_tx_t *)scheduled_response->phy_data;
AssertFatal(sl_tx_config->number_pdus == SL_NR_TX_CONFIG_LIST_NUM,
"sl_tx_config->number_pdus incorrect \n");
switch(sl_tx_config->tx_config_list[0].pdu_type) {
case SL_NR_CONFIG_TYPE_TX_PSBCH:
phy_data_tx->sl_tx_action = SL_NR_CONFIG_TYPE_TX_PSBCH;
LOG_D(PHY, "Recvd CONFIG_TYPE_%s\n", sl_tx_action[phy_data_tx->sl_tx_action - SL_NR_CONFIG_TYPE_TX_PSBCH]);
*((uint32_t *)phy_data_tx->psbch_vars.psbch_payload) =
*((uint32_t *) sl_tx_config->tx_config_list[0].tx_psbch_config_pdu.psbch_payload);
phy_data_tx->psbch_vars.psbch_tx_power =
sl_tx_config->tx_config_list[0].tx_psbch_config_pdu.psbch_tx_power;
phy_data_tx->psbch_vars.tx_slss_id =
sl_tx_config->tx_config_list[0].tx_psbch_config_pdu.tx_slss_id;
break;
case SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH:
case SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS:
case SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH: {
sl_nr_tx_config_pscch_pssch_pdu_t *tx_config_pdu = &sl_tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu;
phy_data_tx->sl_tx_action = sl_tx_config->tx_config_list[0].pdu_type;
phy_data_tx->nr_sl_pssch_pscch_pdu = *tx_config_pdu;
LOG_D(PHY, "Recvd CONFIG_TYPE_%s in (%d.%d) PSCCH startRB %hhu, PSCCH numRB %hhu\n",
sl_tx_action[phy_data_tx->sl_tx_action - SL_NR_CONFIG_TYPE_TX_PSBCH],
frame, slot,
phy_data_tx->nr_sl_pssch_pscch_pdu.startrb,
phy_data_tx->nr_sl_pssch_pscch_pdu.pscch_numrbs);
LOG_D(NR_PHY, "format 1A length %hu :%llx, format 2x length %hu : %llx, PSSCH mcs %hu, PSSCH tbslrm %u\n",
phy_data_tx->nr_sl_pssch_pscch_pdu.pscch_sci_payload_len,
(unsigned long long)*phy_data_tx->nr_sl_pssch_pscch_pdu.pscch_sci_payload,
phy_data_tx->nr_sl_pssch_pscch_pdu.sci2_payload_len,
(unsigned long long)*phy_data_tx->nr_sl_pssch_pscch_pdu.sci2_payload,
phy_data_tx->nr_sl_pssch_pscch_pdu.mcs,
phy_data_tx->nr_sl_pssch_pscch_pdu.tbslbrm);
if (phy_data_tx->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS) {
phy_data_tx->nr_sl_pssch_pscch_pdu.nr_sl_csi_rs_pdu = tx_config_pdu->nr_sl_csi_rs_pdu;
}
uint8_t current_harq_pid = tx_config_pdu->harq_pid;
NR_UL_UE_HARQ_t *harq_process = &PHY_vars_UE_g[module_id][cc_id]->sl_harq_processes[current_harq_pid];
harq_process->status = ACTIVE;
}
break;
default:
AssertFatal(0,"Incorrect sl_tx config req pdutype \n");
break;
}
LOG_D(PHY, "[UE%d] TTI %d:%d, SL-TX action:%s slss_id:%d, sl-mib:%x, psbch pwr:%d\n",
module_id,frame,slot,
sl_tx_action[phy_data_tx->sl_tx_action - SL_NR_CONFIG_TYPE_TX_PSBCH],
phy_data_tx->psbch_vars.tx_slss_id,
*((uint32_t *)phy_data_tx->psbch_vars.psbch_payload),
phy_data_tx->psbch_vars.psbch_tx_power);
}
return 0;
}

View File

@@ -40,12 +40,14 @@
/**\brief NR UE FAPI-like P7 messages, scheduled response from L2 indicating L1
\param scheduled_response including transmission config(dl_config, ul_config) and data transmission (tx_req)*/
int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response);
int8_t sl_handle_scheduled_response(nr_scheduled_response_t *scheduled_response);
int8_t nr_ue_scheduled_response_stub(nr_scheduled_response_t *scheduled_response);
/**\brief NR UE FAPI-like P5 message, physical configuration from L2 to configure L1
\param scheduled_response including transmission config(dl_config, ul_config) and data transmission (tx_req)*/
int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config);
int8_t nr_ue_sl_phy_config_request(nr_sl_phy_config_t *phy_config);
/**\brief NR UE FAPI message to schedule a synchronization with target gNB
\param synch_request including target_Nid_cell*/

View File

@@ -291,7 +291,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n
pucch_procedures_ue_nr(ue, proc, phy_data, (c16_t **)&txdataF);
LOG_D(PHY, "Sending Uplink data \n");
nr_ue_pusch_common_procedures(ue, proc->nr_slot_tx, &ue->frame_parms, ue->frame_parms.nb_antennas_tx, (c16_t **)txdataF);
nr_ue_pusch_common_procedures(ue, proc->nr_slot_tx, &ue->frame_parms, ue->frame_parms.nb_antennas_tx, (c16_t **)txdataF,link_type_ul);
nr_ue_prach_procedures(ue, proc);
@@ -422,17 +422,22 @@ unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int N_RB_UL, int nb
int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
int pscch_flag,
int32_t pdcch_est_size,
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
nr_phy_data_t *phy_data,
int n_ss,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
int16_t *rsrp_dBm)
{
int frame_rx = proc->frame_rx;
int nr_slot_rx = proc->nr_slot_rx;
unsigned int dci_cnt=0;
fapi_nr_dci_indication_t dci_ind = {0};
sl_nr_sci_indication_t sci_ind = {0};
nr_downlink_indication_t dl_indication;
nr_sidelink_indication_t sl_indication;
NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config;
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &phy_pdcch_config->pdcch_config[n_ss];
@@ -444,7 +449,7 @@ int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
int16_t pdcch_e_rx[pdcch_e_rx_size];
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_IN);
nr_rx_pdcch(ue, proc, pdcch_est_size, pdcch_dl_ch_estimates, pdcch_e_rx, rel15, rxdataF);
nr_rx_pdcch(ue, proc, pscch_flag, pdcch_est_size, pdcch_dl_ch_estimates, pdcch_e_rx, rel15, rxdataF);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_OUT);
@@ -455,7 +460,7 @@ int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
n_ss);
#endif
dci_cnt = nr_dci_decoding_procedure(ue, proc, pdcch_e_rx, &dci_ind, rel15);
dci_cnt = nr_dci_decoding_procedure(ue, proc, pscch_flag, pdcch_e_rx, pscch_flag==0 ? (void*)&dci_ind : (void*)&sci_ind, rel15, rsrp_dBm);
#ifdef NR_PDCCH_SCHED_DEBUG
LOG_I(PHY,"<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Ending function nr_dci_decoding_procedure() -> dci_cnt=%u\n",dci_cnt);
@@ -464,21 +469,35 @@ int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DCI_DECODING, VCD_FUNCTION_OUT);
for (int i=0; i<dci_cnt; i++) {
LOG_D(PHY,"[UE %d] AbsSubFrame %d.%d: DCI %i of %d total DCIs found --> rnti %x : format %d\n",
ue->Mod_id,frame_rx%1024,nr_slot_rx,
i + 1,
dci_cnt,
dci_ind.dci_list[i].rnti,
dci_ind.dci_list[i].dci_format);
if (pscch_flag==0)
LOG_D(PHY,"[UE %d] AbsSubFrame %d.%d: DCI %i of %d total DCIs found --> rnti %x : format %d\n",
ue->Mod_id,frame_rx%1024,nr_slot_rx,
i + 1,
dci_cnt,
dci_ind.dci_list[i].rnti,
dci_ind.dci_list[i].dci_format);
else
LOG_D(PHY,"[UE %d] AbsSubFrame %d.%d: SCI 1A %i of %d total SCIs found \n",
ue->Mod_id,frame_rx%1024,nr_slot_rx,
i + 1,
dci_cnt);
}
dci_ind.number_of_dcis = dci_cnt;
// fill dl_indication message
nr_fill_dl_indication(&dl_indication, &dci_ind, NULL, proc, ue, phy_data);
// send to mac
ue->if_inst->dl_indication(&dl_indication);
if (pscch_flag == 0) {
dci_ind.number_of_dcis = dci_cnt;
// fill dl_indication message
nr_fill_dl_indication(&dl_indication, &dci_ind, NULL, proc, ue, phy_data);
// send to mac
ue->if_inst->dl_indication(&dl_indication);
}
else {
sci_ind.number_of_SCIs = dci_cnt;
// fill sl_indication message
nr_fill_sl_indication(&sl_indication, NULL, &sci_ind, proc, ue, phy_data);
// send to mac
ue->if_inst->sl_indication(&sl_indication);
}
stop_meas(&ue->dlsch_rx_pdcch_stats);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT);
@@ -875,12 +894,15 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
for (int i=1; i<4; i++) {
nr_slot_fep(ue,
fp,
proc,
(ssb_start_symbol+i)%(fp->symbols_per_slot),
rxdataF);
rxdataF,
link_type_dl);
start_meas(&ue->dlsch_channel_estimation_stats);
nr_pbch_channel_estimation(ue,
&ue->frame_parms,
estimateSz,
dl_ch_estimates,
dl_ch_estimates_time,
@@ -889,7 +911,9 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
i-1,
ssb_index&7,
ssb_slot_2 == nr_slot_rx,
rxdataF);
rxdataF,
false,
fp->Nid_cell);
stop_meas(&ue->dlsch_channel_estimation_stats);
}
@@ -939,9 +963,11 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
for(int j = prs_config->SymbolStart; j < (prs_config->SymbolStart+prs_config->NumPRSSymbols); j++)
{
nr_slot_fep(ue,
fp,
proc,
(j%fp->symbols_per_slot),
rxdataF);
rxdataF,
link_type_dl);
}
nr_prs_channel_estimation(rsc_id,
i,
@@ -978,9 +1004,11 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
start_meas(&ue->ofdm_demod_stats);
nr_slot_fep(ue,
fp,
proc,
l,
rxdataF);
rxdataF,
link_type_dl);
}
// Hold the channel estimates in frequency domain.
@@ -995,18 +1023,20 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
nr_pdcch_channel_estimation(ue,
proc,
0,
l,
&phy_pdcch_config->pdcch_config[n_ss].coreset,
fp->first_carrier_offset,
phy_pdcch_config->pdcch_config[n_ss].BWPStart,
pdcch_est_size,
pdcch_dl_ch_estimates,
rxdataF);
rxdataF,
NULL);
stop_meas(&ue->ofdm_demod_stats);
}
dci_cnt = dci_cnt + nr_ue_pdcch_procedures(ue, proc, pdcch_est_size, pdcch_dl_ch_estimates, phy_data, n_ss, rxdataF);
dci_cnt = dci_cnt + nr_ue_pdcch_procedures(ue, proc, 0, pdcch_est_size, pdcch_dl_ch_estimates, phy_data, n_ss, rxdataF, NULL);
}
LOG_D(PHY,"[UE %d] Frame %d, nr_slot_rx %d: found %d DCIs\n", ue->Mod_id, frame_rx, nr_slot_rx, dci_cnt);
phy_pdcch_config->nb_search_space = 0;
@@ -1039,9 +1069,11 @@ void pdsch_processing(PHY_VARS_NR_UE *ue,
for (uint16_t m=start_symb_sch;m<(nb_symb_sch+start_symb_sch) ; m++){
nr_slot_fep(ue,
&ue->frame_parms,
proc,
m, //to be updated from higher layer
rxdataF);
rxdataF,
link_type_dl);
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_OUT);
@@ -1116,7 +1148,7 @@ void pdsch_processing(PHY_VARS_NR_UE *ue,
}
l_csiim[symb_idx] = ue->csiim_vars[gNB_id]->csiim_config_pdu.l_csiim[symb_idx];
if(nr_slot_fep_done == false) {
nr_slot_fep(ue, proc, ue->csiim_vars[gNB_id]->csiim_config_pdu.l_csiim[symb_idx], rxdataF);
nr_slot_fep(ue, &ue->frame_parms, proc, ue->csiim_vars[gNB_id]->csiim_config_pdu.l_csiim[symb_idx], rxdataF, link_type_dl);
}
}
nr_ue_csi_im_procedures(ue, proc, rxdataF);
@@ -1127,7 +1159,7 @@ void pdsch_processing(PHY_VARS_NR_UE *ue,
if ((ue->csirs_vars[gNB_id]) && (ue->csirs_vars[gNB_id]->active == 1)) {
for(int symb = 0; symb < NR_SYMBOLS_PER_SLOT; symb++) {
if(is_csi_rs_in_symbol(ue->csirs_vars[gNB_id]->csirs_config_pdu,symb)) {
nr_slot_fep(ue, proc, symb, rxdataF);
nr_slot_fep(ue, &ue->frame_parms, proc, symb, rxdataF, link_type_dl);
}
}
nr_ue_csi_rs_procedures(ue, proc, rxdataF);

View File

@@ -0,0 +1,843 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#define _GNU_SOURCE
#include "PHY/defs_nr_UE.h"
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
#include "openair1/PHY/NR_TRANSPORT/nr_ulsch.h"
#include "openair1/PHY/NR_TRANSPORT/nr_transport_proto.h"
#include "common/utils/LOG/log.h"
#include "common/utils/utils.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "intertask_interface.h"
#include "T.h"
#include "PHY/MODULATION/modulation_UE.h"
#include "PHY/NR_UE_ESTIMATION/nr_estimation.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "executables/nr-uesoftmodem.h"
#include "common/utils/colors.h"
void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, uint8_t harq_pid, uint8_t crc_flag, int dtx_flag) {
AssertFatal(1==0,"Should never get here\n");
}
NR_gNB_PHY_STATS_t *get_phy_stats(PHY_VARS_gNB *gNB, uint16_t rnti) {
return(NULL);
}
void nr_fill_sl_indication(nr_sidelink_indication_t *sl_ind,
sl_nr_rx_indication_t *rx_ind,
sl_nr_sci_indication_t *sci_ind,
UE_nr_rxtx_proc_t *proc,
PHY_VARS_NR_UE *ue,
void *phy_data)
{
memset((void*)sl_ind, 0, sizeof(nr_sidelink_indication_t));
sl_ind->gNB_index = proc->gNB_id;
sl_ind->module_id = ue->Mod_id;
sl_ind->cc_id = ue->CC_id;
sl_ind->frame_rx = proc->frame_rx;
sl_ind->slot_rx = proc->nr_slot_rx;
sl_ind->frame_tx = proc->frame_tx;
sl_ind->slot_tx = proc->nr_slot_tx;
sl_ind->phy_data = phy_data;
sl_ind->slot_type = SIDELINK_SLOT_TYPE_RX;
if (rx_ind) {
sl_ind->rx_ind = rx_ind; // hang on rx_ind instance
sl_ind->sci_ind = NULL;
}
if (sci_ind) {
sl_ind->rx_ind = NULL;
sl_ind->sci_ind = sci_ind;
}
}
void nr_fill_sl_rx_indication(sl_nr_rx_indication_t *rx_ind,
uint8_t pdu_type,
PHY_VARS_NR_UE *ue,
uint16_t n_pdus,
UE_nr_rxtx_proc_t *proc,
void *typeSpecific,
uint16_t rx_slss_id)
{
if (n_pdus > 1){
LOG_E(PHY, "In %s: multiple number of SL PDUs not supported yet...\n", __FUNCTION__);
}
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
switch (pdu_type){
case SL_NR_RX_PDU_TYPE_SLSCH:
case SL_NR_RX_PDU_TYPE_SLSCH_PSFCH: {
sl_nr_slsch_pdu_t *rx_slsch_pdu = &rx_ind->rx_indication_body[n_pdus - 1].rx_slsch_pdu;
slsch_status_t *slsch_status = (slsch_status_t *)typeSpecific;
rx_slsch_pdu->pdu = slsch_status->rdata->ulsch_harq->b;
rx_slsch_pdu->pdu_length = slsch_status->rdata->ulsch_harq->TBS;
rx_slsch_pdu->harq_pid = slsch_status->rdata->harq_pid;
rx_slsch_pdu->ack_nack = (slsch_status->rxok==true) ? 1 : 0;
LOG_D(NR_MAC, "%4d.%2d Received %s SLSCH\n", rx_ind->sfn, rx_ind->slot, rx_slsch_pdu->ack_nack ? "Correct" : "Incorrect");
if (slsch_status->rxok==true) ue->SL_UE_PHY_PARAMS.pssch.rx_ok++;
else ue->SL_UE_PHY_PARAMS.pssch.rx_errors[0]++;
}
break;
case FAPI_NR_RX_PDU_TYPE_SSB: {
sl_nr_ssb_pdu_t *ssb_pdu = &rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu;
if(typeSpecific) {
uint8_t *psbch_decoded_output = (uint8_t *)typeSpecific;
memcpy(ssb_pdu->psbch_payload, psbch_decoded_output, sizeof(4));//4 bytes of PSBCH payload bytes
ssb_pdu->rsrp_dbm = sl_phy_params->psbch.rsrp_dBm_per_RE;
ssb_pdu->rx_slss_id = rx_slss_id;
ssb_pdu->decode_status = true;
LOG_D(PHY, "SL-IND: SSB to MAC. rsrp:%d, slssid:%d, payload:%x\n",
ssb_pdu->rsrp_dbm,ssb_pdu->rx_slss_id,
*((uint32_t *)(ssb_pdu->psbch_payload)) );
}
else
ssb_pdu->decode_status = false;
}
break;
default:
break;
}
rx_ind->rx_indication_body[n_pdus -1].pdu_type = pdu_type;
rx_ind->number_pdus = n_pdus;
}
extern int dmrs_pscch_mask[2];
int nr_slsch_procedures(PHY_VARS_NR_UE *ue, int frame_rx, int slot_rx, int SLSCH_id, UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data, bool is_csi_rs_slot, int8_t *ack_nack_rcvd, int num_acks) {
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
NR_DL_FRAME_PARMS *fp = &sl_phy_params->sl_frame_params;
sl_nr_rx_config_pssch_pdu_t *slsch_pdu = &phy_data->nr_sl_pssch_pdu; //ue->slsch[SLSCH_id].harq_process->slsch_pdu;
sl_nr_rx_config_pssch_sci_pdu_t *pssch_pdu = &phy_data->nr_sl_pssch_sci_pdu; //ue->slsch[SLSCH_id].harq_process->pssch_pdu;
uint8_t freq_density = 0;
uint8_t nr_of_rbs = 0;
if (is_csi_rs_slot) {
freq_density = ue->csirs_vars[0]->csirs_config_pdu.freq_density;
nr_of_rbs = ue->csirs_vars[0]->csirs_config_pdu.nr_of_rbs;
AssertFatal((freq_density == 1) || (nr_of_rbs > 0), "CSI-RS parameters are not properly configured\n");
}
int harq_pid = slsch_pdu->harq_pid;
uint16_t nb_re_dmrs;
uint16_t start_symbol = 1;
uint16_t number_symbols = pssch_pdu->pssch_numsym;
ue->slsch[SLSCH_id].harq_process->harq_to_be_cleared=true;
uint8_t number_dmrs_symbols = 0;
for (int l = start_symbol; l < start_symbol + number_symbols; l++)
number_dmrs_symbols += ((pssch_pdu->dmrs_symbol_position)>>l)&0x01;
nb_re_dmrs = 6;
uint32_t rb_size = pssch_pdu->num_subch*pssch_pdu->subchannel_size;
int sci1_dmrs_overlap = pssch_pdu->dmrs_symbol_position & dmrs_pscch_mask[pssch_pdu->pscch_numsym-2];
int sci2_re = get_NREsci2_2(pssch_pdu->sci2_alpha_times_100,
pssch_pdu->sci2_len,
pssch_pdu->sci2_beta_offset,
pssch_pdu->pssch_numsym,
pssch_pdu->pscch_numsym,
pssch_pdu->pscch_numrbs,
pssch_pdu->l_subch,
pssch_pdu->subchannel_size,
pssch_pdu->targetCodeRate,
0);
uint8_t nr_rbs_w_csi_rs = nr_of_rbs / freq_density;
uint8_t subcarriers_used = get_nrUE_params()->nb_antennas_tx > 2 ? 2 : get_nrUE_params()->nb_antennas_tx;
int num_CSI_REs = is_csi_rs_slot ? nr_rbs_w_csi_rs * subcarriers_used : 0;
uint16_t sci1_re = pssch_pdu->pscch_numsym * pssch_pdu->pscch_numrbs * NR_NB_SC_PER_RB;
uint32_t G = nr_get_G_SL(rb_size,
number_symbols,
nb_re_dmrs,
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
sci1_dmrs_overlap,
sci1_re,
pssch_pdu->pscch_numrbs,
sci2_re,
num_CSI_REs,
pssch_pdu->mod_order,
pssch_pdu->num_layers);
AssertFatal(G>0,"G is 0 : rb_size %u, number_symbols %d, nb_re_dmrs %d, number_dmrs_symbols %d, qam_mod_order %u, nrOfLayer %u\n",
rb_size,
number_symbols,
nb_re_dmrs,
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
pssch_pdu->mod_order,
pssch_pdu->num_layers);
LOG_D(NR_PHY,"slot %d rb_size %d, number_symbols %d, nb_re_dmrs %d, dmrs symbol positions %d, number_dmrs_symbols %d, qam_mod_order %d, nrOfLayer %d\n",
slot_rx,
rb_size,
number_symbols,
nb_re_dmrs,
pssch_pdu->dmrs_symbol_position,
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
pssch_pdu->mod_order,
pssch_pdu->num_layers);
nr_ulsch_layer_demapping(ue->pssch_vars[SLSCH_id].llr,
pssch_pdu->num_layers,
pssch_pdu->mod_order,
G,
ue->pssch_vars[SLSCH_id].llr_layers);
//for (int g=0;g<G;g++) LOG_I(NR_PHY,"prescrambling_llr[%d] %d\n",g,ue->pssch_vars[SLSCH_id].llr[g]);
//----------------------------------------------------------
//------------------- ULSCH unscrambling -------------------
//----------------------------------------------------------
//LOG_I(NR_PHY,"SLSCH, unscrambling with Nid %x\n",pssch_pdu->Nid);
nr_ulsch_unscrambling(ue->pssch_vars[SLSCH_id].llr, G, pssch_pdu->Nid, 1010);
// for (int g=0;g<32;g++) LOG_I(NR_PHY,"unscrambling_llr[%d] %d\n",g,ue->pssch_vars[SLSCH_id].llr[g]);
//----------------------------------------------------------
//--------------------- ULSCH decoding ---------------------
//----------------------------------------------------------
nfapi_nr_pusch_pdu_t pusch_pdu;
pusch_pdu.rb_size = rb_size;
pusch_pdu.qam_mod_order = pssch_pdu->mod_order;
pusch_pdu.mcs_index = slsch_pdu->mcs;
pusch_pdu.nrOfLayers = pssch_pdu->num_layers;
pusch_pdu.pusch_data.tb_size=slsch_pdu->tb_size;
uint32_t A = slsch_pdu->tb_size<<3;
pusch_pdu.target_code_rate=slsch_pdu->target_coderate;
float Coderate = (float) (slsch_pdu->target_coderate) / 10240.0f;
pusch_pdu.pusch_data.rv_index=slsch_pdu->rv_index;
if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25){
pusch_pdu.maintenance_parms_v3.ldpcBaseGraph=2;
}
else{
pusch_pdu.maintenance_parms_v3.ldpcBaseGraph=1;
}
pusch_pdu.maintenance_parms_v3.tbSizeLbrmBytes=slsch_pdu->tbslbrm>>3;
LOG_D(NR_PHY, "%4d.%2d Calling nr_ulsch_decoding\n", frame_rx, slot_rx);
int nbDecode =
nr_ulsch_decoding(NULL, ue, SLSCH_id, ue->pssch_vars[SLSCH_id].llr, fp, &pusch_pdu, frame_rx, slot_rx, harq_pid, G, proc, phy_data, ack_nack_rcvd, num_acks);
return nbDecode;
}
void nr_postDecode_slsch(PHY_VARS_NR_UE *UE, notifiedFIFO_elt_t *req,UE_nr_rxtx_proc_t *proc,nr_phy_data_t *phy_data, int8_t *ack_nack_rcvd, uint8_t num_acks)
{
ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req);
NR_UL_gNB_HARQ_t *slsch_harq = rdata->ulsch_harq;
NR_gNB_ULSCH_t *slsch = rdata->ulsch;
int r = rdata->segment_r;
sl_nr_rx_config_pssch_pdu_t *slsch_pdu = &phy_data->nr_sl_pssch_pdu;//UE->slsch[rdata->ulsch_id].harq_process->slsch_pdu;
bool decodeSuccess = (rdata->decodeIterations <= rdata->decoderParms.numMaxIter);
slsch_harq->processedSegments++;
LOG_D(NR_PHY,
"processing result of segment: %d, processed %d/%d\n",
rdata->segment_r,
slsch_harq->processedSegments,
rdata->nbSegments);
if (decodeSuccess) {
memcpy(slsch_harq->b + rdata->offset, slsch_harq->c[r], rdata->Kr_bytes - (slsch_harq->F >> 3) - ((slsch_harq->C > 1) ? 3 : 0));
} else {
LOG_D(NR_PHY, "ULSCH %d in error\n", rdata->ulsch_id);
}
//int dumpsig=0;
// if all segments are done
if (rdata->nbSegments == slsch_harq->processedSegments) {
sl_nr_rx_indication_t sl_rx_indication;
nr_sidelink_indication_t sl_indication;
slsch_status_t slsch_status;
if (!check_abort(&slsch_harq->abort_decode) && !UE->pssch_vars[rdata->ulsch_id].DTX) {
LOG_D(NR_PHY,
"[UE] SLSCH: Setting ACK for SFN/SF %d.%d (pid %d, ndi %d, status %d, round %d, TBS %d, Max interation "
"(all seg) %d)\n",
slsch->frame,
slsch->slot,
rdata->harq_pid,
slsch_pdu->ndi,
slsch->active,
slsch_harq->round,
slsch_harq->TBS,
rdata->decodeIterations);
slsch->active = false;
slsch_harq->round = 0;
LOG_D(NR_PHY, "%4d.%2d SLSCH received ok \n", proc->frame_rx, proc->nr_slot_rx);
slsch_status.rdata = rdata;
slsch_status.rxok = true;
//dumpsig=1;
} else {
LOG_E(NR_PHY,
"[UE] SLSCH %d in error: Setting NAK for SFN/SF %d/%d (pid %d, ndi %d, status %d, round %d, RV %d, prb_start %d, prb_size %d, "
"TBS %d) r %d\n",
rdata->ulsch_id,
slsch->frame,
slsch->slot,
rdata->harq_pid,
slsch_pdu->ndi,
slsch->active,
slsch_harq->round,
slsch_harq->ulsch_pdu.pusch_data.rv_index,
slsch_harq->ulsch_pdu.rb_start,
slsch_harq->ulsch_pdu.rb_size,
slsch_harq->TBS,
r);
slsch->handled = 1;
LOG_D(NR_PHY, "%4d.%2d SLSCH %d in error\n", proc->frame_rx, proc->nr_slot_rx, rdata->ulsch_id);
slsch_status.rdata = rdata;
slsch_status.rxok = false;
// dumpsig=1;
}
slsch->last_iteration_cnt = rdata->decodeIterations;
sl_rx_indication.sfn = proc->frame_rx;
sl_rx_indication.slot = proc->nr_slot_rx;
sl_rx_indication.rx_indication_body[0].rx_slsch_pdu.ack_nack_rcvd = calloc(num_acks, sizeof(uint8_t));
memcpy((void*)sl_rx_indication.rx_indication_body[0].rx_slsch_pdu.ack_nack_rcvd, (void*)ack_nack_rcvd,
num_acks * sizeof(uint8_t));
sl_rx_indication.rx_indication_body[0].rx_slsch_pdu.num_acks_rcvd = num_acks;
uint8_t pdu_type = phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_PSFCH ? SL_NR_RX_PDU_TYPE_SLSCH_PSFCH : SL_NR_RX_PDU_TYPE_SLSCH;
nr_fill_sl_rx_indication(&sl_rx_indication, pdu_type, UE, 1, proc, (void*)&slsch_status, 0);
nr_fill_sl_indication(&sl_indication,&sl_rx_indication,NULL,proc,UE,phy_data);
if (UE->if_inst && UE->if_inst->sl_indication)
UE->if_inst->sl_indication(&sl_indication);
/*
if (ulsch_harq->ulsch_pdu.mcs_index == 0 && dumpsig==1) {
int off = ((ulsch_harq->ulsch_pdu.rb_size&1) == 1)? 4:0;
LOG_M("rxsigF0.m","rxsF0",&gNB->common_vars.rxdataF[0][(ulsch_harq->slot&3)*gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot],gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot,1,1);
LOG_M("rxsigF0_ext.m","rxsF0_ext",
&gNB->pusch_vars[0].rxdataF_ext[0][ulsch_harq->ulsch_pdu.start_symbol_index*NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("chestF0.m","chF0",
&gNB->pusch_vars[0].ul_ch_estimates[0][ulsch_harq->ulsch_pdu.start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1);
LOG_M("chestF0_ext.m","chF0_ext",
&gNB->pusch_vars[0]->ul_ch_estimates_ext[0][(ulsch_harq->ulsch_pdu.start_symbol_index+1)*(off+(NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size))], (ulsch_harq->ulsch_pdu.nr_of_symbols-1)*(off+(NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("rxsigF0_comp.m","rxsF0_comp",
&gNB->pusch_vars[0].rxdataF_comp[0][ulsch_harq->ulsch_pdu.start_symbol_index*(off+(NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size))],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("rxsigF0_llr.m","rxsF0_llr",
&gNB->pusch_vars[0].llr[0],(ulsch_harq->ulsch_pdu.nr_of_symbols-1)*NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size *
ulsch_harq->ulsch_pdu.qam_mod_order,1,0); if (gNB->frame_parms.nb_antennas_rx > 1) {
LOG_M("rxsigF1_ext.m","rxsF0_ext",
&gNB->pusch_vars[0].rxdataF_ext[1][ulsch_harq->ulsch_pdu.start_symbol_index*NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("chestF1.m","chF1",
&gNB->pusch_vars[0].ul_ch_estimates[1][ulsch_harq->ulsch_pdu.start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1);
LOG_M("chestF1_ext.m","chF1_ext",
&gNB->pusch_vars[0].ul_ch_estimates_ext[1][(ulsch_harq->ulsch_pdu.start_symbol_index+1)*(off+(NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size))], (ulsch_harq->ulsch_pdu.nr_of_symbols-1)*(off+(NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("rxsigF1_comp.m","rxsF1_comp",
&gNB->pusch_vars[0].rxdataF_comp[1][ulsch_harq->ulsch_pdu.start_symbol_index*(off+(NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size))],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size)),1,1);
}
exit(-1);
}
*/
slsch->last_iteration_cnt = rdata->decodeIterations;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,0);
}
}
static int nr_ue_psbch_procedures(PHY_VARS_NR_UE *ue,
NR_DL_FRAME_PARMS *fp,
UE_nr_rxtx_proc_t *proc,
int estimateSz,
struct complex16 dl_ch_estimates[][estimateSz],
nr_phy_data_t *phy_data,
c16_t rxdataF[][fp->samples_per_slot_wCP])
{
int ret = 0;
DevAssert(ue);
int frame_rx = proc->frame_rx;
int nr_slot_rx = proc->nr_slot_rx;
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
uint16_t rx_slss_id = sl_phy_params->sl_config.sl_sync_source.rx_slss_id;
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PSBCH_PROCEDURES, VCD_FUNCTION_IN);
LOG_D(PHY,"[UE %d] Frame %d Slot %d, Trying PSBCH (SLSS ID %d)\n",
ue->Mod_id,frame_rx,nr_slot_rx,
sl_phy_params->sl_config.sl_sync_source.rx_slss_id);
uint8_t decoded_pdu[4] = {0};
ret = nr_rx_psbch(ue,
proc,
estimateSz,
dl_ch_estimates,
fp,
decoded_pdu,
rxdataF,
sl_phy_params->sl_config.sl_sync_source.rx_slss_id);
nr_sidelink_indication_t sl_indication;
sl_nr_rx_indication_t rx_ind = {0};
uint16_t number_pdus = 1;
uint8_t *result = NULL;
if (ret) sl_phy_params->psbch.rx_errors ++;
else {
result = decoded_pdu;
sl_phy_params->psbch.rx_ok ++;
}
nr_fill_sl_indication(&sl_indication, &rx_ind, NULL, proc, ue, phy_data);
nr_fill_sl_rx_indication(&rx_ind, SL_NR_RX_PDU_TYPE_SSB, ue, number_pdus, proc, (void *)result, rx_slss_id);
if (ue->if_inst && ue->if_inst->sl_indication)
ue->if_inst->sl_indication(&sl_indication);
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PSBCH_PROCEDURES, VCD_FUNCTION_OUT);
return ret;
}
void psbch_pscch_pssch_processing(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
nr_phy_data_t *phy_data) {
int frame_rx = proc->frame_rx;
int nr_slot_rx = proc->nr_slot_rx;
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
NR_DL_FRAME_PARMS *fp = &sl_phy_params->sl_frame_params;
bool is_csi_rs_slot = false;
int8_t *ack_nack_rcvd = NULL;
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX_SL, VCD_FUNCTION_IN);
start_meas(&sl_phy_params->phy_proc_sl_rx);
LOG_D(PHY," ****** Sidelink RX-Chain for Frame.Slot %d.%d ****** \n",
frame_rx%1024, nr_slot_rx);
const uint32_t rxdataF_sz = fp->samples_per_slot_wCP;
__attribute__ ((aligned(32))) c16_t rxdataF[fp->nb_antennas_rx][rxdataF_sz];
if ((frame_rx&127) == 0) {
LOG_I(NR_PHY,"============================================\n");
LOG_I(NR_PHY,"%s[UE%d] %d:%d PSBCH Stats: TX %u, RX ok %u, RX not ok %u\n",KGRN,
ue->Mod_id, frame_rx, nr_slot_rx,
sl_phy_params->psbch.num_psbch_tx,
sl_phy_params->psbch.rx_ok,
sl_phy_params->psbch.rx_errors);
LOG_I(NR_PHY,"%s[UE%d] %d:%d PSCCH Stats: TX %u, RX ok %u\n",KGRN,
ue->Mod_id, frame_rx, nr_slot_rx,
sl_phy_params->pscch.num_pscch_tx,
sl_phy_params->pscch.rx_ok);
LOG_I(NR_PHY,"%s[UE%d] %d:%d PSSCH/SCI2 Stats: TX %u, RX ok %u, RX not ok %u\n",KGRN,
ue->Mod_id, frame_rx, nr_slot_rx,
sl_phy_params->pssch.num_pssch_sci2_tx,
sl_phy_params->pssch.rx_sci2_ok,
sl_phy_params->pssch.rx_sci2_errors);
LOG_I(NR_PHY,"%s[UE%d] %d:%d PSSCH Stats: TX %u, RX ok %u, RX not ok (%u/%u/%u/%u)\n",KGRN,
ue->Mod_id, frame_rx, nr_slot_rx,
sl_phy_params->pssch.num_pssch_tx,
sl_phy_params->pssch.rx_ok,
sl_phy_params->pssch.rx_errors[0],
sl_phy_params->pssch.rx_errors[1],
sl_phy_params->pssch.rx_errors[2],
sl_phy_params->pssch.rx_errors[3]);
LOG_I(NR_PHY, "%s[UE%d] %d:%d PSFCH Stats: TX %u\n", KGRN,
ue->Mod_id, frame_rx, nr_slot_rx,
sl_phy_params->psfch.num_psfch_tx
);
LOG_I(NR_PHY,"============================================\n");
}
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSBCH){
const int estimateSz = fp->symbols_per_slot * fp->ofdm_symbol_size;
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PSBCH, VCD_FUNCTION_IN);
LOG_D(PHY," ----- PSBCH RX TTI: frame.slot %d.%d ------ \n",
frame_rx%1024, nr_slot_rx);
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates[fp->nb_antennas_rx][estimateSz];
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_time[fp->nb_antennas_rx][fp->ofdm_symbol_size];
// 0 for Normal Cyclic Prefix and 1 for EXT CyclicPrefix
const int numsym = (fp->Ncp) ? SL_NR_NUM_SYMBOLS_SSB_EXT_CP
: SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP;
for (int sym=0; sym<numsym;) {
nr_slot_fep(ue,
fp,
proc,
sym,
rxdataF,
link_type_sl);
start_meas(&sl_phy_params->channel_estimation_stats);
nr_pbch_channel_estimation(ue,
fp,
estimateSz,
dl_ch_estimates,
dl_ch_estimates_time,
proc,
sym,
sym,
0,
0,
rxdataF,
true,
sl_phy_params->sl_config.sl_sync_source.rx_slss_id);
stop_meas(&sl_phy_params->channel_estimation_stats);
//PSBCH present in symbols 0, 5-12 for normal cp
sym = (sym == 0) ? 5 : sym + 1;
}
nr_sl_psbch_rsrp_measurements(sl_phy_params,fp, rxdataF,false);
LOG_D(PHY," ------ Decode SL-MIB: frame.slot %d.%d ------ \n",
frame_rx%1024, nr_slot_rx);
const int psbchSuccess = nr_ue_psbch_procedures(ue, fp, proc, estimateSz,
dl_ch_estimates, phy_data, rxdataF);
if (ue->no_timing_correction==0 && psbchSuccess == 0) {
LOG_D(PHY,"start adjust sync slot = %d no timing %d\n", nr_slot_rx, ue->no_timing_correction);
nr_adjust_synch_ue(fp,
ue,
proc->gNB_id,
fp->ofdm_symbol_size,
dl_ch_estimates_time,
frame_rx,
nr_slot_rx,
0,
16384);
}
ue->apply_timing_offset = true;
LOG_D(PHY, "Doing N0 measurements in %s\n", __FUNCTION__);
// nr_ue_rrc_measurements(ue, proc, rxdataF);
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PSBCH, VCD_FUNCTION_OUT);
}
else if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSCCH){
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &phy_data->phy_pdcch_config.pdcch_config[0];
LOG_D(NR_PHY,"pscch_numsym = %d\n",phy_data->nr_sl_pscch_pdu.pscch_numsym);
LOG_D(NR_PHY,"pscch_startrb = %d\n",phy_data->nr_sl_pscch_pdu.pscch_startrb);
LOG_D(NR_PHY,"pscch_numrbs = %d\n",phy_data->nr_sl_pscch_pdu.pscch_numrbs);
LOG_D(NR_PHY,"pscch_dmrs_scrambling_id = %d\n",phy_data->nr_sl_pscch_pdu.pscch_dmrs_scrambling_id);
LOG_D(NR_PHY,"pscch_num_subch= %d\n",phy_data->nr_sl_pscch_pdu.num_subch);
LOG_D(NR_PHY,"pscch_subchannel_size = %d\n",phy_data->nr_sl_pscch_pdu.subchannel_size);
LOG_D(NR_PHY,"pscch_l_subch = %d\n",phy_data->nr_sl_pscch_pdu.l_subch);
LOG_D(NR_PHY,"pscch_pssch_numsym = %d\n",phy_data->nr_sl_pscch_pdu.pssch_numsym);
LOG_D(NR_PHY,"sense_pscch = %d\n",phy_data->nr_sl_pscch_pdu.sense_pscch);
rel15->rnti = 0;
rel15->BWPSize = phy_data->nr_sl_pscch_pdu.num_subch * phy_data->nr_sl_pscch_pdu.subchannel_size;
rel15->BWPStart = phy_data->nr_sl_pscch_pdu.pscch_startrb;
rel15->SubcarrierSpacing = fp->subcarrier_spacing;
rel15->coreset.frequency_domain_resource[0] = phy_data->nr_sl_pscch_pdu.pscch_startrb;
rel15->coreset.frequency_domain_resource[1] = phy_data->nr_sl_pscch_pdu.pscch_numrbs;
rel15->coreset.CoreSetType = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG;
rel15->coreset.StartSymbolIndex = 1;
rel15->coreset.RegBundleSize = 0;
rel15->coreset.duration = phy_data->nr_sl_pscch_pdu.pscch_numsym;
rel15->coreset.pdcch_dmrs_scrambling_id = phy_data->nr_sl_pscch_pdu.pscch_dmrs_scrambling_id;
rel15->coreset.scrambling_rnti = 1010;
rel15->coreset.tci_present_in_dci = 0;
rel15->number_of_candidates = phy_data->nr_sl_pscch_pdu.l_subch;
rel15->num_dci_options = 1;
rel15->dci_length_options[0] = phy_data->nr_sl_pscch_pdu.sci_1a_length;
// L now provides the number of PRBs used by PSCCH instead of the number of CCEs
rel15->L[0] = phy_data->nr_sl_pscch_pdu.pscch_numrbs * phy_data->nr_sl_pscch_pdu.pscch_numsym;
// This provides the offset of the candidate of PSCCH in RBs instead of CCEs
rel15->CCE[0] = 0;
// Hold the channel estimates in frequency domain.
int32_t pscch_est_size = ((((fp->symbols_per_slot*(fp->ofdm_symbol_size+LTE_CE_FILTER_LENGTH))+15)/16)*16);
__attribute__ ((aligned(16))) int32_t pscch_dl_ch_estimates[4*fp->nb_antennas_rx][pscch_est_size];
//
int16_t rsrp_dBm = 0;
for (int sym=0; sym<rel15->coreset.duration;sym++) {
nr_slot_fep(ue,
fp,
proc,
1+sym,
rxdataF,
link_type_sl);
nr_pdcch_channel_estimation(ue,
proc,
1,
1+sym,
&rel15->coreset,
fp->first_carrier_offset,
rel15->BWPStart,
pscch_est_size,
pscch_dl_ch_estimates,
rxdataF,
&rsrp_dBm);
}
nr_ue_pdcch_procedures(ue, proc, 1, pscch_est_size, pscch_dl_ch_estimates, phy_data, 0, rxdataF, &rsrp_dBm);
LOG_D(NR_PHY,"returned from nr_ue_pdcch_procedures\n");
}
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SCI) {
LOG_D(NR_PHY,"sci2_len = %d\n",phy_data->nr_sl_pssch_sci_pdu.sci2_len);
LOG_D(NR_PHY,"sci2_beta_offset = %d\n",phy_data->nr_sl_pssch_sci_pdu.sci2_beta_offset);
LOG_D(NR_PHY,"sci2_alpha_times_100= %d\n",phy_data->nr_sl_pssch_sci_pdu.sci2_alpha_times_100);
LOG_D(NR_PHY,"pssch_targetCodeRate = %d\n",phy_data->nr_sl_pssch_sci_pdu.targetCodeRate);
LOG_D(NR_PHY,"pssch_num_layers = %d\n",phy_data->nr_sl_pssch_sci_pdu.num_layers);
LOG_D(NR_PHY,"dmrs_symbol_position = %d\n",phy_data->nr_sl_pssch_sci_pdu.dmrs_symbol_position);
int num_dmrs = 0;
for (int s = 0; s < NR_NUMBER_OF_SYMBOLS_PER_SLOT; s++)
num_dmrs += (phy_data->nr_sl_pssch_sci_pdu.dmrs_symbol_position >> s) & 1;
LOG_D(NR_PHY,"num_dmrs = %d\n",num_dmrs);
LOG_D(NR_PHY,"Nid = %x\n",phy_data->nr_sl_pssch_sci_pdu.Nid);
LOG_D(NR_PHY,"startrb = %d\n",phy_data->nr_sl_pssch_sci_pdu.startrb);
LOG_D(NR_PHY,"pscch_numsym = %d\n",phy_data->nr_sl_pssch_sci_pdu.pscch_numsym);
LOG_D(NR_PHY,"pscch_numrbs = %d\n",phy_data->nr_sl_pssch_sci_pdu.pscch_numrbs);
LOG_D(NR_PHY,"num_subch= %d\n",phy_data->nr_sl_pssch_sci_pdu.num_subch);
LOG_D(NR_PHY,"subchannel_size = %d\n",phy_data->nr_sl_pssch_sci_pdu.subchannel_size);
LOG_D(NR_PHY,"l_subch = %d\n",phy_data->nr_sl_pssch_sci_pdu.l_subch);
LOG_D(NR_PHY,"pssch_numsym = %d\n",phy_data->nr_sl_pssch_sci_pdu.pssch_numsym);
LOG_D(NR_PHY,"sense_pssch = %d\n",phy_data->nr_sl_pssch_sci_pdu.sense_pssch);
ue->slsch->harq_process->pssch_pdu = &phy_data->nr_sl_pssch_sci_pdu;
// compute number of REs containing SCI2
int sci2_re = get_NREsci2_2(phy_data->nr_sl_pssch_sci_pdu.sci2_alpha_times_100,
phy_data->nr_sl_pssch_sci_pdu.sci2_len,
phy_data->nr_sl_pssch_sci_pdu.sci2_beta_offset,
phy_data->nr_sl_pssch_sci_pdu.pssch_numsym,
phy_data->nr_sl_pssch_sci_pdu.pscch_numsym,
phy_data->nr_sl_pssch_sci_pdu.pscch_numrbs,
phy_data->nr_sl_pssch_sci_pdu.l_subch,
phy_data->nr_sl_pssch_sci_pdu.subchannel_size,
phy_data->nr_sl_pssch_sci_pdu.targetCodeRate,
0);
LOG_D(NR_PHY,"Starting slot FEP for SLSCH (symbol %d to %d) pscch_numsym %d pssch_numsym %d REs with SCI2 %d\n",
1 + phy_data->nr_sl_pssch_sci_pdu.pscch_numsym, phy_data->nr_sl_pssch_sci_pdu.pssch_numsym,
phy_data->nr_sl_pssch_sci_pdu.pscch_numsym, phy_data->nr_sl_pssch_sci_pdu.pssch_numsym, sci2_re);
for (int sym=1+phy_data->nr_sl_pssch_sci_pdu.pscch_numsym; sym<=phy_data->nr_sl_pssch_sci_pdu.pssch_numsym;sym++) {
nr_slot_fep(ue,
fp,
proc,
sym,
rxdataF,
link_type_sl);
}
nr_rx_pusch(NULL,
ue,
proc,
phy_data,
rxdataF_sz,
rxdataF,
0,
frame_rx,
nr_slot_rx,
0,
&is_csi_rs_slot);
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_PSFCH) {
ack_nack_rcvd = calloc(phy_data->num_psfch_pdus, sizeof(ack_nack_rcvd));
LOG_D(NR_PHY, "num_psfch_pdus: %d\n", phy_data->num_psfch_pdus);
for (int k = 0; k < phy_data->num_psfch_pdus; k++) {
sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu = &phy_data->psfch_pdu_list[k];
LOG_D(NR_PHY, "%s start_symbol_index %d, sl_bwp_start %d, sequence_hop_flag %d, \
second_hop_prb %d, prb %d, nr_of_symbols %d, initial_cyclic_shift %d, hopping_id %d, \
group_hop_flag %d, freq_hop_flag %d, bit_len_harq %d\n",
__FUNCTION__,
psfch_pdu->start_symbol_index, psfch_pdu->sl_bwp_start,
psfch_pdu->sequence_hop_flag, psfch_pdu->second_hop_prb, psfch_pdu->prb,
psfch_pdu->nr_of_symbols, psfch_pdu->initial_cyclic_shift, psfch_pdu->hopping_id,
psfch_pdu->group_hop_flag, psfch_pdu->freq_hop_flag, psfch_pdu->bit_len_harq);
nr_slot_fep(ue,
fp,
proc,
psfch_pdu->start_symbol_index,
rxdataF,
link_type_sl);
ack_nack_rcvd[k] = nr_ue_decode_psfch0(ue,
frame_rx,
nr_slot_rx,
rxdataF,
psfch_pdu);
}
free(phy_data->psfch_pdu_list);
phy_data->psfch_pdu_list = NULL;
}
NR_gNB_PUSCH *pssch_vars = &ue->pssch_vars[0];
pssch_vars->ulsch_power_tot = 0;
pssch_vars->ulsch_noise_power_tot = 0;
for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++) {
pssch_vars->ulsch_power[aarx] /= num_dmrs;
pssch_vars->ulsch_power_tot += pssch_vars->ulsch_power[aarx];
pssch_vars->ulsch_noise_power[aarx] /= num_dmrs;
pssch_vars->ulsch_noise_power_tot += pssch_vars->ulsch_noise_power[aarx];
}
if (dB_fixed_x10(pssch_vars->ulsch_power_tot) < dB_fixed_x10(pssch_vars->ulsch_noise_power_tot) + ue->pssch_thres) {
LOG_D(NR_PHY,
"PSSCH not detected in %d.%d (%d,%d,%d)\n",
frame_rx,
nr_slot_rx,
dB_fixed_x10(pssch_vars->ulsch_power_tot),
dB_fixed_x10(pssch_vars->ulsch_noise_power_tot),
ue->pssch_thres);
pssch_vars->ulsch_power_tot = pssch_vars->ulsch_noise_power_tot;
pssch_vars->DTX = 1;
//if (stats)
// stats->ulsch_stats.DTX++;
// nr_fill_indication(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid, 1, 1);
//pssch_DTX++;
// continue;
} else {
pssch_vars->DTX = 0;
int totalDecode = nr_slsch_procedures(ue, frame_rx, nr_slot_rx, 0, proc, phy_data, is_csi_rs_slot, ack_nack_rcvd, phy_data->num_psfch_pdus);
LOG_D(NR_PHY,
"Total %d decoded PSSCH detected in %d.%d (%d,%d,%d)\n",
totalDecode,
frame_rx,
nr_slot_rx,
dB_fixed_x10(pssch_vars->ulsch_power_tot),
dB_fixed_x10(pssch_vars->ulsch_noise_power_tot),
ue->pssch_thres);
}
}
LOG_D(PHY,"****** end Sidelink RX-Chain for AbsSubframe %d.%d ******\n",
frame_rx, nr_slot_rx);
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_SL, VCD_FUNCTION_OUT);
stop_meas(&sl_phy_params->phy_proc_sl_tx);
return;
}
int phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
nr_phy_data_tx_t *phy_data)
{
int slot_tx = proc->nr_slot_tx;
int frame_tx = proc->frame_tx;
int tx_action = 0;
const char *sl_tx_actions[] = {"PSBCH", "PSCCH_PSSCH", "PSCCH_PSSCH_PSFCH", "PSCCH_PSSCH_CSI_RS"};
if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS) {
LOG_D(NR_PHY, "Generating %s (%d.%d)\n", sl_tx_actions[phy_data->sl_tx_action - SL_NR_CONFIG_TYPE_TX_PSBCH], frame_tx, slot_tx);
}
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
NR_DL_FRAME_PARMS *fp = &sl_phy_params->sl_frame_params;
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_SL,VCD_FUNCTION_IN);
const int samplesF_per_slot = NR_SYMBOLS_PER_SLOT * fp->ofdm_symbol_size;
c16_t txdataF_buf[fp->nb_antennas_tx * samplesF_per_slot] __attribute__((aligned(32)));
memset(txdataF_buf, 0, sizeof(txdataF_buf));
c16_t *txdataF[fp->nb_antennas_tx]; /* workaround to be compatible with current txdataF usage in all tx procedures. */
for(int i=0; i< fp->nb_antennas_tx; ++i)
txdataF[i] = &txdataF_buf[i * samplesF_per_slot];
LOG_D(PHY,"****** start Sidelink TX-Chain for AbsSubframe %d.%d ******\n",
frame_tx, slot_tx);
start_meas(&sl_phy_params->phy_proc_sl_tx);
if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSBCH) {
sl_nr_tx_config_psbch_pdu_t *psbch_vars = &phy_data->psbch_vars;
nr_tx_psbch(ue, frame_tx, slot_tx, psbch_vars, txdataF);
sl_phy_params->psbch.num_psbch_tx ++;
tx_action = 1;
}
else if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH ||
phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS ||
phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH) {
if (phy_data->sl_tx_action >= SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH && phy_data->sl_tx_action <= SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS)
LOG_D(NR_PHY, "(%d.%d) Sending %s\n", frame_tx, slot_tx, sl_tx_actions[phy_data->sl_tx_action - SL_NR_CONFIG_TYPE_TX_PSBCH]);
phy_data->pscch_Nid = nr_generate_sci1(ue, txdataF[0], fp, AMP, slot_tx, &phy_data->nr_sl_pssch_pscch_pdu) &0xFFFF;
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)&phy_data->nr_sl_pssch_pscch_pdu.nr_sl_csi_rs_pdu;
csi_params->scramb_id = phy_data->pscch_Nid % (1 << 10);
for (uint8_t harq_pid = 0; harq_pid < NR_MAX_ULSCH_HARQ_PROCESSES; harq_pid++) {
if (ue->sl_harq_processes[harq_pid].status == ACTIVE) {
nr_ue_ulsch_procedures(ue, harq_pid, frame_tx, slot_tx, 0, phy_data, txdataF);
}
}
sl_phy_params->pscch.num_pscch_tx ++;
sl_phy_params->pssch.num_pssch_sci2_tx ++;
sl_phy_params->pssch.num_pssch_tx ++;
if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS) {
uint16_t beta_csirs = get_softmodem_params()->sl_mode ? (uint16_t)(AMP * (ceil(sqrt(phy_data->nr_sl_pssch_pscch_pdu.num_layers / fp->nb_antennas_tx)))) & 0xFFFF : AMP;
LOG_D(NR_PHY, "Tx beta_csirs: %d, scramb_id %i (%d.%d)\n", beta_csirs, csi_params->scramb_id, frame_tx, slot_tx);
nr_generate_csi_rs(fp,
(int32_t **)txdataF,
beta_csirs,
ue->nr_csi_info,
csi_params,
slot_tx,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
}
if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH) {
for (int k = 0; k < phy_data->nr_sl_pssch_pscch_pdu.num_psfch_pdus; k++) {
nr_generate_psfch0(ue,
txdataF,
fp,
AMP,
slot_tx,
&phy_data->nr_sl_pssch_pscch_pdu.psfch_pdu_list[k]);
}
sl_phy_params->psfch.num_psfch_tx ++;
free(phy_data->nr_sl_pssch_pscch_pdu.psfch_pdu_list);
phy_data->nr_sl_pssch_pscch_pdu.psfch_pdu_list = NULL;
}
tx_action = 1;
}
if (tx_action) {
LOG_D(PHY, "Sending SL data \n");
nr_ue_pusch_common_procedures(ue,
proc->nr_slot_tx,
fp,
fp->nb_antennas_tx,
txdataF, link_type_sl);
}
LOG_D(PHY,"****** end Sidelink TX-Chain for AbsSubframe %d.%d ******\n",
frame_tx, slot_tx);
return tx_action;
}

View File

@@ -45,8 +45,9 @@
#include <linux/if.h>
#include <linux/if_tun.h>
#include "common/openairinterface5g_limits.h"
#include "pdcp.h"
#include <executables/nr-uesoftmodem.h>
char nl_rx_buf[NL_MAX_PAYLOAD];
@@ -65,7 +66,24 @@ struct msghdr nas_msg_rx;
#define GRAAL_NETLINK_ID 31
static int tun_alloc(char *dev) {
//Jin add for TAP
typedef enum {
OAI_TUNTAP_TUN = 0,
OAI_TUNTAP_TAP = 1
} oai_tuntap_mode_t;
static oai_tuntap_mode_t oai_get_tuntap_mode(void)
{
// Default: TUN (keeps your current behaviour)
const char *s = getenv("OAI_TUNTAP_MODE"); // set to "tap" to enable TAP
if (s && !strcasecmp(s, "tap"))
return OAI_TUNTAP_TAP;
return OAI_TUNTAP_TUN;
}
//Jin TAP end
//static int tun_alloc(char *dev) { //Jin origin
static int tun_alloc(char *dev, oai_tuntap_mode_t mode) { //Jin replace TAP
struct ifreq ifr;
int fd, err;
@@ -80,7 +98,8 @@ static int tun_alloc(char *dev) {
*
* IFF_NO_PI - Do not provide packet information
*/
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
//ifr.ifr_flags = IFF_TUN | IFF_NO_PI; //Jin origin
ifr.ifr_flags = ((mode == OAI_TUNTAP_TAP) ? IFF_TAP : IFF_TUN) | IFF_NO_PI; //Jin replace TAP
if( *dev )
strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)-1);
@@ -105,14 +124,19 @@ int netlink_init_mbms_tun(char *ifprefix, int id) {//for UE, id = 1, 2, ...,
else {
sprintf(ifname, "oaitun_%.3s1", ifprefix); // added "1": for historical reasons
}
nas_sock_mbms_fd = tun_alloc(ifname);
// nas_sock_mbms_fd = tun_alloc(ifname); //Jin origin
oai_tuntap_mode_t mode = oai_get_tuntap_mode(); //Jin TAP
nas_sock_mbms_fd = tun_alloc(ifname, mode); //Jin add TAP
if (nas_sock_mbms_fd == -1) {
printf("[NETLINK] Error opening mbms socket %s (%d:%s)\n",ifname,errno, strerror(errno));
exit(1);
}
printf("[NETLINK]Opened socket %s with fd %d\n",ifname,nas_sock_mbms_fd);
//printf("[NETLINK]Opened socket %s with fd %d\n",ifname,nas_sock_mbms_fd); //Jin origin
printf("[Jin TAP TAP NETLINK]%s Opened socket %s with fd %d\n", //Jin have a look at TAP
(mode == OAI_TUNTAP_TAP) ? "TAP" : "TUN",
ifname, nas_sock_mbms_fd);
ret = fcntl(nas_sock_mbms_fd,F_SETFL,O_NONBLOCK);
if (ret == -1) {
@@ -135,24 +159,33 @@ int netlink_init_mbms_tun(char *ifprefix, int id) {//for UE, id = 1, 2, ...,
int netlink_init_tun(char *ifprefix, int num_if, int id) {//for UE, id = 1, 2, ...,
int ret;
char ifname[64];
oai_tuntap_mode_t mode = oai_get_tuntap_mode(); //Jin add TAP
int begx = (id == 0) ? 0 : id - 1;
int endx = (id == 0) ? num_if : id;
int index;
for (int i = begx; i < endx; i++) {
sprintf(ifname, "oaitun_%.3s%d",ifprefix,i+1);
nas_sock_fd[i] = tun_alloc(ifname);
sprintf(ifname, "oaitun_%.3s%d", ifprefix, i+1);
//index = get_softmodem_params()->sl_mode ? 0 : i; //Jin origin
index = i; //Jin replace so TAP has different endpoints for multiple UES
//nas_sock_fd[index] = tun_alloc(ifname); //Jin origin
oai_tuntap_mode_t mode = oai_get_tuntap_mode(); //Jin add TAP
nas_sock_fd[index] = tun_alloc(ifname, mode); //Jin add TAP
if (nas_sock_fd[i] == -1) {
LOG_E(PDCP, "TUN: Error opening socket %s (%d:%s)\n",ifname,errno, strerror(errno));
if (nas_sock_fd[index] == -1) {
LOG_E(PDCP, "TUN: Error opening socket %s (%d:%s)\n", ifname, errno, strerror(errno));
exit(1);
}
LOG_I(PDCP, "TUN: Opened socket %s with fd nas_sock_fd[%d]=%d\n",
ifname, i, nas_sock_fd[i]);
ret = fcntl(nas_sock_fd[i],F_SETFL,O_NONBLOCK);
ifname, index, nas_sock_fd[index]);
LOG_D(PDCP, "JIN LOG TAP !!!!!!!!!! %s: Opened socket %s with fd nas_sock_fd[%d]=%d\n",
(mode == OAI_TUNTAP_TAP) ? "TAP" : "TUN",
ifname, index, nas_sock_fd[index]);
ret = fcntl(nas_sock_fd[index], F_SETFL, O_NONBLOCK);
if (ret == -1) {
LOG_E(PDCP, "TUN: Error fcntl (%d:%s)\n",errno, strerror(errno));
LOG_E(PDCP, "TUN: Error fcntl (%d:%s)\n", errno, strerror(errno));
if (LINK_ENB_PDCP_TO_IP_DRIVER) {
exit(1);
@@ -224,4 +257,4 @@ void netlink_cleanup(void)
{
free(nas_nlh_tx);
nas_nlh_tx = NULL;
}
}

View File

@@ -846,7 +846,7 @@ int main(int argc, char **argv)
// compute the scramblingID_pdcch and the gold pdcch
UE->scramblingID_pdcch = frame_parms->Nid_cell;
nr_gold_pdcch(UE, frame_parms->Nid_cell);
nr_gold_pdcch(&UE->frame_parms, UE->nr_gold_pdcch[0],frame_parms->Nid_cell);
// compute the scrambling IDs for PDSCH DMRS
for (int i = 0; i < 2; i++) {
@@ -854,7 +854,7 @@ int main(int argc, char **argv)
nr_gold_pdsch(UE, i, UE->scramblingID_dlsch[i]);
}
nr_l2_init_ue(NULL);
nr_l2_init_ue(NULL, NULL);
UE_mac = get_mac_inst(0);
ue_init_config_request(UE_mac, mu);

View File

@@ -49,3 +49,12 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id,
const channel_t channel,
const uint8_t* pduP,
const sdu_size_t pdu_len) { return 0; }
int8_t nr_mac_rrc_sl_mib_ind(const module_id_t module_id,
const int CC_id,
const uint8_t gNB_index,
const frame_t frame,
const int slot,
const int channel,
const uint8_t* pduP,
const sdu_size_t pdu_len,
const uint16_t rx_slss_id) {return 1;}

View File

@@ -116,7 +116,8 @@ int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
nr_phy_data_t *phy_data,
int n_ss,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
int *rsrp_dBm) {
return 0;
}
@@ -797,12 +798,13 @@ int main(int argc, char **argv)
proc.gNB_id = 0;
for (int i=UE->symbol_offset+1; i<UE->symbol_offset+4; i++) {
nr_slot_fep(UE,
frame_parms,
&proc,
i%frame_parms->symbols_per_slot,
rxdataF);
rxdataF, link_type_dl);
nr_pbch_channel_estimation(UE,estimateSz, dl_ch_estimates, dl_ch_estimates_time, &proc,
i%frame_parms->symbols_per_slot,i-(UE->symbol_offset+1),ssb_index%8,n_hf,rxdataF);
nr_pbch_channel_estimation(UE,&UE->frame_parms, estimateSz, dl_ch_estimates, dl_ch_estimates_time, &proc,
i%frame_parms->symbols_per_slot,i-(UE->symbol_offset+1),ssb_index%8,n_hf,rxdataF,false,frame_parms->Nid_cell);
}
fapiPbch_t result;

View File

@@ -0,0 +1,657 @@
#include <string.h>
#include <math.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include "common/config/config_userapi.h"
#include "common/ran_context.h"
#include "PHY/types.h"
#include "PHY/defs_nr_common.h"
#include "PHY/defs_nr_UE.h"
#include "PHY/defs_gNB.h"
#include "PHY/phy_vars.h"
#include "NR_MasterInformationBlockSidelink.h"
#include "PHY/INIT/phy_init.h"
#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h"
#include "openair1/SIMULATION/TOOLS/sim.h"
#include "common/utils/nr/nr_common.h"
#include "openair2/RRC/NR/nr_rrc_extern.h"
#include "openair2/RRC/LTE/rrc_vars.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "PHY/INIT/nr_phy_init.h"
#include "SIMULATION/RF/rf.h"
#include "common/utils/load_module_shlib.h"
#include "PHY/MODULATION/nr_modulation.h"
#include "NR_SL-SSB-TimeAllocation-r16.h"
void exit_function(const char* file, const char* function, const int line, const char* s, const int assert) {
const char * msg= s==NULL ? "no comment": s;
printf("Exiting at: %s:%d %s(), %s\n", file, line, function, msg);
exit(-1);
}
int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) { return 1; }
// to solve link errors
double cpuf;
//void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {}
void get_num_re_dmrs(nfapi_nr_ue_pusch_pdu_t *pusch_pdu,
uint8_t *nb_dmrs_re_per_rb,
uint16_t *number_dmrs_symbols){}
uint64_t downlink_frequency[1][1];
int32_t uplink_frequency_offset[1][1];
THREAD_STRUCT thread_struct;
instance_t DUuniqInstance=0;
instance_t CUuniqInstance=0;
openair0_config_t openair0_cfg[1];
RAN_CONTEXT_t RC;
int oai_exit = 0;
char *uecap_file;
void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index)
{
return;
}
int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP,
const int CC_id,
const uint8_t gNB_id,
const frame_t frameP,
const rb_id_t Srb_id,
uint8_t *buffer_pP)
{
return 0;
}
nr_bler_struct nr_bler_data[NR_NUM_MCS];
void get_nrUE_params(void) { return;}
uint8_t check_if_ue_is_sl_syncsource() {return 0;}
void nr_rrc_mac_config_req_sl_mib(module_id_t module_id,
NR_SL_SSB_TimeAllocation_r16_t *ssb_ta,
uint16_t rx_slss_id,
uint8_t *sl_mib) {}
//////////////////////////////////////////////////////////////////////////
static void prepare_mib_bits(uint8_t *buf, uint32_t frame_tx, uint32_t slot_tx) {
NR_MasterInformationBlockSidelink_t *sl_mib;
asn_enc_rval_t enc_rval;
void *buffer = (void *)buf;
sl_mib = CALLOC(1, sizeof(NR_MasterInformationBlockSidelink_t));
sl_mib->inCoverage_r16 = 0;//TRUE;
// allocate buffer for 7 bits slotnumber
sl_mib->slotIndex_r16.size = 1;
sl_mib->slotIndex_r16.buf = CALLOC(1, sl_mib->slotIndex_r16.size);
sl_mib->slotIndex_r16.bits_unused = sl_mib->slotIndex_r16.size*8 - 7;
sl_mib->slotIndex_r16.buf[0] = slot_tx << sl_mib->slotIndex_r16.bits_unused;
sl_mib->directFrameNumber_r16.size = 2;
sl_mib->directFrameNumber_r16.buf = CALLOC(1, sl_mib->directFrameNumber_r16.size);
sl_mib->directFrameNumber_r16.bits_unused = sl_mib->directFrameNumber_r16.size*8 - 10;
sl_mib->directFrameNumber_r16.buf[0] = frame_tx >> (8 - sl_mib->directFrameNumber_r16.bits_unused);
sl_mib->directFrameNumber_r16.buf[1] = frame_tx << sl_mib->directFrameNumber_r16.bits_unused;
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_MasterInformationBlockSidelink,
NULL,
(void *)sl_mib,
buffer,
100);
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
asn_DEF_NR_MasterInformationBlockSidelink.op->free_struct(&asn_DEF_NR_MasterInformationBlockSidelink, sl_mib, ASFM_FREE_EVERYTHING);
}
static int test_rx_mib(uint8_t *decoded_output, uint16_t frame, uint16_t slot) {
uint32_t sl_mib = *(uint32_t *)decoded_output;
uint32_t fn = 0, sl = 0;
fn = (((sl_mib & 0x0700) >> 1) | ((sl_mib & 0xFE0000) >> 17));
sl = (((sl_mib & 0x010000) >> 10) | ((sl_mib & 0xFC000000) >> 26));
printf("decoded output:%x, TX %d:%d, timing decoded from sl-MIB %d:%d\n",
*(uint32_t *)decoded_output, frame, slot, fn, sl);
if (frame == fn && slot == sl)
return 0;
return -1;
}
//////////////////////////////////////////////////////////////////////////
static void configure_NR_UE(PHY_VARS_NR_UE *UE, int mu, int N_RB) {
fapi_nr_config_request_t config;
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
config.ssb_config.scs_common = mu;
config.cell_config.frame_duplex_type = TDD;
config.carrier_config.dl_grid_size[mu] = N_RB;
config.carrier_config.ul_grid_size[mu] = N_RB;
config.carrier_config.dl_frequency = 0;
config.carrier_config.uplink_frequency = 0;
int band;
if (mu == 1) band = 78;
if (mu == 0) band = 34;
nr_init_frame_parms_ue(fp, &config, band);
fp->ofdm_offset_divisor = 8;
nr_dump_frame_parms(fp);
if (init_nr_ue_signal(UE, 1) != 0) {
printf("Error at UE NR initialisation\n");
exit(-1);
}
}
static void sl_init_frame_parameters(PHY_VARS_NR_UE *UE) {
NR_DL_FRAME_PARMS *nr_fp = &UE->frame_parms;
NR_DL_FRAME_PARMS *sl_fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
memcpy(sl_fp, nr_fp, sizeof(NR_DL_FRAME_PARMS));
sl_fp->ofdm_offset_divisor = 8; // What is this used for?
sl_fp->att_tx = 1;
sl_fp->att_rx = 1;
// band47 //UL freq will be set to Sidelink freq
sl_fp->ul_CarrierFreq = 5880000000;
sl_fp->ssb_start_subcarrier = UE->SL_UE_PHY_PARAMS.sl_config.sl_bwp_config.sl_ssb_offset_point_a;
sl_fp->Nid_cell = UE->SL_UE_PHY_PARAMS.sl_config.sl_sync_source.rx_slss_id;
#ifdef DEBUG_INIT
LOG_I(PHY, "Dumping Sidelink Frame Parameters\n");
nr_dump_frame_parms(sl_fp);
#endif
}
static void configure_SL_UE(PHY_VARS_NR_UE *UE, int mu, int N_RB, int ssb_offset, int slss_id) {
sl_nr_phy_config_request_t *config = &UE->SL_UE_PHY_PARAMS.sl_config;
NR_DL_FRAME_PARMS *fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
config->sl_bwp_config.sl_scs = mu;
config->sl_bwp_config.sl_ssb_offset_point_a = ssb_offset;
config->sl_carrier_config.sl_bandwidth = N_RB;
config->sl_carrier_config.sl_grid_size = 106;
config->sl_sync_source.rx_slss_id = slss_id;
sl_init_frame_parameters(UE);
sl_ue_phy_init(UE);
init_symbol_rotation(fp);
init_timeshift_rotation(fp);
LOG_I(PHY, "Dumping Sidelink Frame Parameters\n");
nr_dump_frame_parms(fp);
}
static int freq_domain_loopback(PHY_VARS_NR_UE *UE_tx, PHY_VARS_NR_UE *UE_rx,
int frame, int slot,
nr_phy_data_tx_t *phy_data) {
sl_nr_ue_phy_params_t *sl_ue1 = &UE_tx->SL_UE_PHY_PARAMS;
sl_nr_ue_phy_params_t *sl_ue2 = &UE_rx->SL_UE_PHY_PARAMS;
printf("\nPSBCH SIM -F: %d:%d slss id TX UE:%d, RX UE:%d\n",
frame, slot,phy_data->psbch_vars.tx_slss_id,
sl_ue2->sl_config.sl_sync_source.rx_slss_id);
NR_DL_FRAME_PARMS *fp = &sl_ue1->sl_frame_params;
const int samplesF_per_slot = NR_SYMBOLS_PER_SLOT * fp->ofdm_symbol_size;
c16_t txdataF_buf[fp->nb_antennas_tx * samplesF_per_slot] __attribute__((aligned(32)));
memset(txdataF_buf, 0, sizeof(txdataF_buf));
c16_t *txdataF[fp->nb_antennas_tx]; /* workaround to be compatible with current txdataF usage in all tx procedures. */
for(int i=0; i< fp->nb_antennas_tx; ++i)
txdataF[i] = &txdataF_buf[i * samplesF_per_slot];
nr_tx_psbch(UE_tx,frame, slot, &phy_data->psbch_vars, txdataF);
int estimateSz = sl_ue2->sl_frame_params.samples_per_slot_wCP;
__attribute__ ((aligned(32))) struct complex16 rxdataF[1][estimateSz];
for (int i=0; i<sl_ue1->sl_frame_params.samples_per_slot_wCP; i++) {
struct complex16 *txdataF_ptr = (struct complex16 *)&txdataF[0][i];
struct complex16 *rxdataF_ptr = (struct complex16 *)&rxdataF[0][i];
rxdataF_ptr->r = txdataF_ptr->r;
rxdataF_ptr->i = txdataF_ptr->i;
//printf("r,i TXDATAF[%d]- %d:%d, RXDATAF[%d]- %d:%d\n",
// i, txdataF_ptr->r, txdataF_ptr->i, i, txdataF_ptr->r, txdataF_ptr->i);
}
uint8_t err_status = 0;
UE_nr_rxtx_proc_t proc;
proc.frame_rx = frame;
proc.nr_slot_rx = slot;
struct complex16 dl_ch_estimates[1][estimateSz];
uint8_t decoded_output[4] = {0};
LOG_I(PHY,"DEBUG: HIJACKING DL CHANNEL ESTIMATES.\n");
for (int s=0; s<14; s++) {
for (int j=0; j<sl_ue2->sl_frame_params.ofdm_symbol_size; j++) {
struct complex16 *dlch = (struct complex16 *)(&dl_ch_estimates[0][s*sl_ue2->sl_frame_params.ofdm_symbol_size]);
dlch[j].r = 128;
dlch[j].i = 0;
}
}
err_status = nr_rx_psbch(UE_rx,
&proc,
estimateSz,
dl_ch_estimates,
&sl_ue2->sl_frame_params,
decoded_output,
rxdataF,
sl_ue2->sl_config.sl_sync_source.rx_slss_id);
int error_payload = 0;
error_payload = test_rx_mib(decoded_output, frame, slot);
if (err_status == 0 || error_payload == 0) {
LOG_I(PHY,"---------PSBCH -F TEST OK.\n");
return 0;
}
LOG_E(PHY, "--------PSBCH -F TEST NOK. FAIL.\n");
return -1;
}
PHY_VARS_NR_UE *UE_TX; // for tx
PHY_VARS_NR_UE *UE_RX; // for rx
double cpuf;
int main(int argc, char **argv) {
char c;
int test_freqdomain_loopback = 0,test_slss_search = 0;
int frame = 5, slot = 10, frame_tx = 0, slot_tx = 0;
int loglvl = OAILOG_INFO;
uint16_t slss_id = 336, ssb_offset = 0;
double snr1 = 2.0, snr0 = 2.0, SNR;
double sigma2 = 0.0, sigma2_dB = 0.0;
double cfo=0, ip =0.0;
SCM_t channel_model=AWGN;//Rayleigh1_anticorr;
int N_RB_DL=106,mu=1;
uint16_t errors = 0, n_trials = 1;
int frame_length_complex_samples;
//int frame_length_complex_samples_no_prefix;
NR_DL_FRAME_PARMS *frame_parms;
int seed = 0;
cpuf = get_cpu_freq_GHz();
if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0 ) {
exit_fun("SIDELINK PSBCH SIM Error, configuration module init failed\n");
}
randominit(0);
while ((c = getopt(argc, argv, "c:hn:o:s:FIL:N:R:S:T:")) != -1) {
printf("SIDELINK PSBCH SIM: handling optarg %c\n",c);
switch (c) {
case 'c':
cfo = atof(optarg);
printf("Setting CFO to %f Hz\n",cfo);
break;
case 'g':
switch((char)*optarg) {
case 'A':
channel_model=SCM_A;
break;
case 'B':
channel_model=SCM_B;
break;
case 'C':
channel_model=SCM_C;
break;
case 'D':
channel_model=SCM_D;
break;
case 'E':
channel_model=EPA;
break;
case 'F':
channel_model=EVA;
break;
case 'G':
channel_model=ETU;
break;
default:
printf("Unsupported channel model! Exiting.\n");
exit(-1);
}
break;
case 'n':
n_trials = atoi(optarg);
break;
case 'o':
ssb_offset = atoi(optarg);
printf("SIDELINK PSBCH SIM: ssb offset from pointA:%d\n",ssb_offset);
break;
case 's':
slss_id = atoi(optarg);
printf("SIDELINK PSBCH SIM: slss_id from arg:%d\n",slss_id);
AssertFatal(slss_id >= 0 && slss_id <= 671,"SLSS ID not within Range 0-671\n");
break;
case 'F':
test_freqdomain_loopback = 1;
break;
case 'I':
test_slss_search = 1;
printf("SIDELINK PSBCH SIM: SLSS search will be tested\n");
break;
case 'L':
loglvl = atoi(optarg);
break;
case 'N':
snr0 = atoi(optarg);
snr1 = snr0;
printf("Setting SNR0 to %f. Test uses this SNR as target SNR\n",snr0);
break;
case 'R':
N_RB_DL = atoi(optarg);
printf("SIDELINK PSBCH SIM: N_RB_DL:%d\n",N_RB_DL);
break;
case 'S':
snr1 = atof(optarg);
printf("Setting SNR1 to %f. Test will run until this SNR as target SNR\n",snr1);
AssertFatal(snr1 <= snr0, "Test runs SNR down, set snr1 to a lower value than %f\n", snr0);
break;
case 'T':
frame = atoi(argv[2]);
slot = atoi(argv[3]);
break;
case 'h':
default :
printf("\n\nSIDELINK PSBCH SIM OPTIONS LIST - hus:FL:T:\n");
printf("-h: HELP\n");
printf("-c Carrier frequency offset in Hz\n");
printf("-n Number of trials\n");
printf("-o ssb offset from PointA - indicates ssb_start subcarrier\n");
printf("-s: set Sidelink sync id slss_id. ex -s 100\n");
printf("-F: Run PSBCH frequency domain loopback test of the samples\n");
printf("-I: Sidelink SLSS search will be tested.\n");
printf("-L: Set Log Level.\n");
printf("-N: Test with Noise. target SNR0 eg -N 10\n");
printf("-R N_RB_DL\n");
printf("-S Ending SNR, runs from SNR0 to SNR1\n");
printf("-T: Frame,Slot to be sent in sl-MIB eg -T 4 2\n");
return 1;
}
}
randominit(seed);
logInit();
set_glog(loglvl);
T_stdout = 1;
double fs=0, eps;
double scs = 30000;
double bw = 100e6;
switch (mu) {
case 1:
scs = 30000;
if (N_RB_DL == 217) {
fs = 122.88e6;
bw = 80e6;
}
else if (N_RB_DL == 245) {
fs = 122.88e6;
bw = 90e6;
}
else if (N_RB_DL == 273) {
fs = 122.88e6;
bw = 100e6;
}
else if (N_RB_DL == 106) {
fs = 61.44e6;
bw = 40e6;
}
else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL);
break;
case 3:
scs = 120000;
if (N_RB_DL == 66) {
fs = 122.88e6;
bw = 100e6;
}
else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL);
break;
}
// cfo with respect to sub-carrier spacing
eps = cfo/scs;
// computation of integer and fractional FO to compare with estimation results
int IFO;
if(eps!=0.0){
printf("Introducing a CFO of %lf relative to SCS of %d kHz\n",eps,(int)(scs/1000));
if (eps>0)
IFO=(int)(eps+0.5);
else
IFO=(int)(eps-0.5);
printf("FFO = %lf; IFO = %d\n",eps-IFO,IFO);
}
channel_desc_t *UE2UE;
int n_tx = 1, n_rx = 1;
UE2UE = new_channel_desc_scm(n_tx,
n_rx,
channel_model,
fs,
0,
bw,
300e-9,
0.0,
CORR_LEVEL_LOW,
0,
0,
0,
0);
if (UE2UE==NULL) {
printf("Problem generating channel model. Exiting.\n");
exit(-1);
}
/*****configure UE *************************/
UE_TX = calloc(1, sizeof(PHY_VARS_NR_UE));
UE_RX = calloc(1, sizeof(PHY_VARS_NR_UE));
LOG_I(PHY, "Configure UE-TX and sidelink UE-TX.\n");
configure_NR_UE(UE_TX, mu, N_RB_DL);
configure_SL_UE(UE_TX, mu, N_RB_DL,ssb_offset, 0xFFFF);
LOG_I(PHY, "Configure UE-RX and sidelink UE-RX.\n");
configure_NR_UE(UE_RX, mu, N_RB_DL);
UE_RX->is_synchronized = (test_slss_search) ? 0 : 1;
configure_SL_UE(UE_RX, mu, N_RB_DL,ssb_offset, slss_id);
/*****************************************/
sl_nr_ue_phy_params_t *sl_uetx = &UE_TX->SL_UE_PHY_PARAMS;
sl_nr_ue_phy_params_t *sl_uerx = &UE_RX->SL_UE_PHY_PARAMS;
frame_parms = &sl_uetx->sl_frame_params;
frame_tx = frame % 1024;
slot_tx = slot % frame_parms->slots_per_frame;
frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
//frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP;
double **s_re,**s_im,**r_re,**r_im;
s_re = malloc(2*sizeof(double*));
s_im = malloc(2*sizeof(double*));
r_re = malloc(2*sizeof(double*));
r_im = malloc(2*sizeof(double*));
s_re[0] = malloc16_clear(frame_length_complex_samples*sizeof(double));
s_im[0] = malloc16_clear(frame_length_complex_samples*sizeof(double));
r_re[0] = malloc16_clear(frame_length_complex_samples*sizeof(double));
r_im[0] = malloc16_clear(frame_length_complex_samples*sizeof(double));
if(eps!=0.0)
UE_RX->UE_fo_compensation = 1; // if a frequency offset is set then perform fo estimation and compensation
UE_nr_rxtx_proc_t proc;
proc.frame_tx = frame;
proc.nr_slot_tx = slot;
nr_phy_data_tx_t phy_data_tx;
phy_data_tx.psbch_vars.tx_slss_id = slss_id;
uint8_t sl_mib[4] = {0};
prepare_mib_bits(sl_mib,frame, slot);
memcpy(phy_data_tx.psbch_vars.psbch_payload,sl_mib, 4);
phy_data_tx.sl_tx_action = SL_NR_CONFIG_TYPE_TX_PSBCH;
proc.frame_rx = frame;
proc.nr_slot_rx = slot;
nr_phy_data_t phy_data_rx;
phy_data_rx.sl_rx_action = SL_NR_CONFIG_TYPE_RX_PSBCH;
if (test_freqdomain_loopback) {
errors += freq_domain_loopback(UE_TX, UE_RX, frame_tx, slot_tx, &phy_data_tx);
}
printf("\nSidelink TX UE - Frame.Slot %d.%d SLSS id:%d\n",
frame, slot,phy_data_tx.psbch_vars.tx_slss_id);
printf("Sidelink RX UE - Frame.Slot %d.%d SLSS id:%d\n",
proc.frame_rx, proc.nr_slot_rx,
sl_uerx->sl_config.sl_sync_source.rx_slss_id);
phy_procedures_nrUE_SL_TX(UE_TX, &proc, &phy_data_tx);
for (SNR=snr0; SNR>=snr1; SNR-=1) {
for (int trial=0; trial<n_trials; trial++) {
for (int i=0; i<frame_length_complex_samples; i++) {
for (int aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
struct complex16 *txdata_ptr = (struct complex16 *)&UE_TX->common_vars.txData[aa][i];
r_re[aa][i] = (double)txdata_ptr->r;
r_im[aa][i] = (double)txdata_ptr->i;
}
}
LOG_M("txData0.m","txd0", UE_TX->common_vars.txData[0],frame_parms->samples_per_frame,1,1);
//AWGN
sigma2_dB = 20*log10((double)AMP/4)-SNR;
sigma2 = pow(10,sigma2_dB/10);
//printf("sigma2 %f (%f dB), tx_lev %f (%f dB)\n",sigma2,sigma2_dB,txlev,10*log10((double)txlev));
if(eps!=0.0) {
rf_rx(r_re, // real part of txdata
r_im, // imag part of txdata
NULL, // interference real part
NULL, // interference imag part
0, // interference power
frame_parms->nb_antennas_rx, // number of rx antennas
frame_length_complex_samples, // number of samples in frame
1.0e9/fs, //sampling time (ns)
cfo, // frequency offset in Hz
0.0, // drift (not implemented)
0.0, // noise figure (not implemented)
0.0, // rx gain in dB ?
200, // 3rd order non-linearity in dB ?
&ip, // initial phase
30.0e3, // phase noise cutoff in kHz
-500.0, // phase noise amplitude in dBc
0.0, // IQ imbalance (dB),
0.0); // IQ phase imbalance (rad)
}
for (int i=0; i<frame_length_complex_samples; i++) {
for (int aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
UE_RX->common_vars.rxdata[aa][i].r = (short)(r_re[aa][i] + sqrt(sigma2 / 2) * gaussdouble(0.0, 1.0));
UE_RX->common_vars.rxdata[aa][i].i = (short)(r_im[aa][i] + sqrt(sigma2 / 2) * gaussdouble(0.0, 1.0));
}
}
if (UE_RX->is_synchronized == 0) {
int ret = -1;
UE_nr_rxtx_proc_t proc={0};
//Should not have SLSS id configured. Search should find SLSS id from TX UE
UE_RX->SL_UE_PHY_PARAMS.sl_config.sl_sync_source.rx_slss_id = 0xFFFF;
ret = sl_nr_slss_search(UE_RX, &proc, 1);
printf("Sidelink SLSS search returns %d\n",ret);
if (ret!=0) sl_uerx->psbch.rx_errors = 1;
else {
AssertFatal(UE_RX->SL_UE_PHY_PARAMS.sync_params.N_sl_id == slss_id,
"DETECTED INCORRECT SLSS ID in SEARCH.CHECK id:%d\n", UE_RX->SL_UE_PHY_PARAMS.sync_params.N_sl_id);
sl_uerx->psbch.rx_ok = 1;
}
} else psbch_pscch_processing(UE_RX,&proc,&phy_data_rx);
} //noise trials
printf("Runs:%d SNR %f: SLSS Search:%d crc ERRORs = %d, OK = %d\n",
n_trials, SNR, !UE_RX->is_synchronized,
sl_uerx->psbch.rx_errors, sl_uerx->psbch.rx_ok);
errors += sl_uerx->psbch.rx_errors;
sl_uerx->psbch.rx_errors = 0;
sl_uerx->psbch.rx_ok = 0;
} // NSR
if (errors == 0)
LOG_I(PHY,"PSBCH test OK\n");
else
LOG_E(PHY,"PSBCH test NOT OK\n");
free_channel_desc_scm(UE2UE);
free(s_re[0]);
free(s_im[0]);
free(r_re[0]);
free(r_im[0]);
free(s_re);
free(s_im);
free(r_re);
free(r_im);
term_nr_ue_signal(UE_TX, 1);
term_nr_ue_signal(UE_RX, 1);
free(UE_TX);
free(UE_RX);
logTerm();
loader_reset();
return errors;
}

View File

@@ -593,7 +593,7 @@ int main(int argc, char **argv)
rel15_ul->qam_mod_order,
rel15_ul->nrOfLayers);
int nbDecode = nr_ulsch_decoding(gNB, UE_id, channel_output_fixed, frame_parms, rel15_ul, frame, subframe, harq_pid, G);
int nbDecode = nr_ulsch_decoding(gNB, NULL, UE_id, channel_output_fixed, frame_parms, rel15_ul, frame, subframe, harq_pid, G, NULL, NULL, NULL, -1);
int nb_ok = 0;
if (nbDecode > 0)
while (nbDecode > 0) {

View File

@@ -726,7 +726,7 @@ int main(int argc, char **argv)
NR_UE_RRC_INST_t rrcue = {0};
rrcue.mib = mib->message.choice.mib;
rrcue.scell_group_config = secondaryCellGroup;
nr_l2_init_ue(&rrcue);
nr_l2_init_ue(&rrcue, NULL);
NR_UE_MAC_INST_t* UE_mac = get_mac_inst(0);

View File

@@ -20,7 +20,6 @@
*/
#include <math.h>
#include <cblas.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

View File

@@ -20,7 +20,6 @@
*/
#include <math.h>
#include <cblas.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -527,15 +526,13 @@ double get_normalization_ch_factor(channel_desc_t *desc)
bzero(acorr, desc->nb_tx * desc->nb_rx * sizeof(struct complexd));
for (int aatx = 0; aatx < desc->nb_tx; aatx++) {
for (int aarx = 0; aarx < desc->nb_rx; aarx++) {
cblas_zaxpy(desc->nb_tx * desc->nb_rx,
(void *)&anew[aarx + (aatx * desc->nb_rx)],
(void *)desc->R_sqrt[aarx + (aatx * desc->nb_rx)],
1,
(void *)acorr,
1);
for (int inside = 0; inside < desc->nb_tx * desc->nb_rx; inside++) {
const cd_t tmp = cdMul(anew[aarx + aatx * desc->nb_rx], desc->R_sqrt[aarx + aatx * desc->nb_rx][inside]);
csum(acorr[inside], tmp, acorr[inside]);
}
} // for (int aarx = 0; aarx < desc->nb_rx; aarx++)
} // for (int aatx = 0; aatx < desc->nb_tx; aatx++)
cblas_zcopy(desc->nb_tx * desc->nb_rx, (void *)acorr, 1, (void *)a[l], 1);
memcpy(a[l], acorr, desc->nb_tx * desc->nb_rx * sizeof(*acorr));
} // for (int l = 0; l < (int)desc->nb_taps; l++)
for (int aarx = 0; aarx < desc->nb_rx; aarx++) {
@@ -1759,7 +1756,7 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
acorr[aarx+(aatx*desc->nb_rx)].i = desc->ch[aarx+(aatx*desc->nb_rx)][0].i;
}
}
cblas_zcopy(desc->nb_tx*desc->nb_rx, (void *) acorr, 1, (void *) desc->a[0], 1);
memcpy(desc->a[0], acorr, desc->nb_tx * desc->nb_rx * sizeof(*acorr));
stop_meas(&desc->random_channel);
desc->first_run = 0;
return 0;
@@ -1810,16 +1807,17 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
if (desc->modelid >= TDL_A && desc->modelid <= TDL_E) {
for (aatx = 0; aatx < desc->nb_tx; aatx++) {
for (aarx=0; aarx<desc->nb_rx; aarx++) {
cblas_zaxpy(desc->nb_tx*desc->nb_rx,
(void *) &anew[aarx+(aatx*desc->nb_rx)],
(void *) desc->R_sqrt[aarx+(aatx*desc->nb_rx)],
1,
(void *) acorr,
1);
for (int inside = 0; inside < desc->nb_tx * desc->nb_rx; inside++) {
const cd_t tmp = cdMul(anew[aarx + aatx * desc->nb_rx], desc->R_sqrt[aarx + aatx * desc->nb_rx][inside]);
csum(acorr[inside], tmp, acorr[inside]);
}
}
}
} else {
cblas_zaxpy(desc->nb_tx*desc->nb_rx, (void *) desc->R_sqrt[i/3], (void *) anew, 1, (void *) acorr, 1);
for (int inside = 0; inside < desc->nb_tx * desc->nb_rx; inside++) {
const cd_t tmp = cdMul(desc->R_sqrt[i / 3][0], anew[inside]);
csum(acorr[inside], tmp, acorr[inside]);
}
}
/*
@@ -1844,7 +1842,7 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
*/
if (desc->first_run==1) {
cblas_zcopy(desc->nb_tx*desc->nb_rx, (void *) acorr, 1, (void *) desc->a[i], 1);
memcpy(desc->a[i], acorr, desc->nb_tx * desc->nb_rx * sizeof(*acorr));
} else {
// a = alpha*acorr+beta*a
// a = beta*a
@@ -1853,8 +1851,11 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
alpha.i = 0;
beta.r = sqrt(desc->forgetting_factor);
beta.i = 0;
cblas_zscal(desc->nb_tx*desc->nb_rx, (void *) &beta, (void *) desc->a[i], 1);
cblas_zaxpy(desc->nb_tx*desc->nb_rx, (void *) &alpha, (void *) acorr, 1, (void *) desc->a[i], 1);
for (int inside = 0; inside < desc->nb_tx * desc->nb_rx; inside++) {
desc->a[i][inside] = cdMul(beta, desc->a[i][inside]);
const cd_t tmp = cdMul(alpha, acorr[inside]);
csum(desc->a[i][inside], tmp, desc->a[i][inside]);
}
// desc->a[i][aarx+(aatx*desc->nb_rx)].x = (sqrt(desc->forgetting_factor)*desc->a[i][aarx+(aatx*desc->nb_rx)].x) + sqrt(1-desc->forgetting_factor)*anew.x;
// desc->a[i][aarx+(aatx*desc->nb_rx)].y = (sqrt(desc->forgetting_factor)*desc->a[i][aarx+(aatx*desc->nb_rx)].y) + sqrt(1-desc->forgetting_factor)*anew.y;
}

View File

@@ -153,7 +153,12 @@ typedef enum ip_traffic_type_e {
TRAFFIC_IPV4_TYPE_BROADCAST = 7,
TRAFFIC_IPV4_TYPE_UNKNOWN = 8,
TRAFFIC_PC5S_SIGNALLING = 9,
TRAFFIC_PC5S_SESSION_INIT = 10
TRAFFIC_PC5S_SESSION_INIT = 10,
// MC ADDED: New types for non-IP packets, for each type cast
TRAFFIC_NONIP_TYPE_UNKOWN = 11,
TRAFFIC_NONIP_TYPE_UNICAST = 12,
TRAFFIC_NONIP_TYPE_MULTICAST = 13,
TRAFFIC_NONIP_TYPE_BROADCAST = 14
} ip_traffic_type_t;
//-----------------------------------------------------------------------------

Some files were not shown because too many files have changed in this diff Show More