Compare commits

...

128 Commits

Author SHA1 Message Date
beraoudabdelkhalek
54a039b350 Fix config files 2025-03-10 10:35:36 +01:00
Karim Boutiba
6fdfdc2dfc add loggin 2025-02-26 15:06:19 +00:00
Karim Boutiba
02226bf919 checkpoint for me to test 2024-05-30 14:31:47 +02:00
matilde.costa
9588e10de0 Added non-ip types to ip_traffic_type_t 2024-05-17 14:58:54 +02: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
118 changed files with 11716 additions and 1315 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,19 @@ 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_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 +1093,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 +1135,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 +1367,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 +1381,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
@@ -2225,6 +2244,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

View File

@@ -315,7 +315,7 @@ function main() {
-P | --phy_simulators)
SIMUS_PHY=1
# TODO: fix: dlsim_tm4 pucchsim prachsim pdcchsim pbchsim mbmssim
TARGET_LIST="$TARGET_LIST dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim"
TARGET_LIST="$TARGET_LIST dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim nr_psbchsim"
echo_info "Will compile dlsim, ulsim, ..."
shift;;
-s | --check)
@@ -523,7 +523,7 @@ function main() {
echo_info "Doxygen generation log is located here: $doxygen_log"
echo_info "Generating Doxygen files....please wait"
(
cmake --build . --target doc
cmake3 --build . --target doc
) >& $doxygen_log
fi

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

@@ -232,6 +232,42 @@ 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 == 2) {
*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 {
*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);
}
}
int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB) {
int tmp = locationAndBandwidth/N_RB;
int tmp2 = locationAndBandwidth%N_RB;
@@ -351,7 +387,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 +769,62 @@ 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);
LOG_D(NR_PHY,"R10240 %d\n",R10240);
uint32_t tmp = (uint32_t)ceil((Osci2 + 24)*beta_offset_sci2/(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);
return min(tmp,(int)ceil(tmp2));
}
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) {
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 = target_coderate;
LOG_D(NR_PHY,"R10240 = %d\n",R10240);
uint32_t tmp = (uint32_t)ceil((Osci2 + 24)*beta_offset_sci2/(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);
return min(tmp,(int)ceil(tmp2));
}

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())

View File

@@ -744,7 +744,7 @@ static radio_tx_gpio_flag_t get_gpio_flags(RU_t *ru, int slot)
int beam = beam_ids[slot * fp->symbols_per_slot];
if (prev_beam != beam) {
flags_gpio = beam | TX_GPIO_CHANGE; // enable change of gpio
LOG_I(HW, "slot %d, beam %d\n", slot, ru->common.beam_id[0][slot * fp->symbols_per_slot]);
LOG_D(HW, "slot %d, beam %d\n", slot, ru->common.beam_id[0][slot * fp->symbols_per_slot]);
}
}
break;

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);
@@ -314,7 +315,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 +377,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 +495,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 +548,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 +568,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 +606,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 +620,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 +705,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 +756,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 +777,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 +826,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 +853,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 +884,14 @@ 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;
sl_nr_phy_config_request_t *sl_cfg = NULL;
int is_sidelink = (UE->sl_mode == 2) ? 1 : 0;
if (is_sidelink) {
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
sl_cfg = &UE->SL_UE_PHY_PARAMS.sl_config;
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 +910,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 +921,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 +935,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 +955,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 +981,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 +1010,30 @@ 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) {
curMsg.proc.rx_slot_type = sl_nr_ue_slot_select(sl_cfg, curMsg.proc.frame_rx, curMsg.proc.nr_slot_rx, TDD);
curMsg.proc.tx_slot_type = sl_nr_ue_slot_select(sl_cfg, curMsg.proc.frame_tx, curMsg.proc.nr_slot_tx, TDD);
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 +1046,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 +1059,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;
@@ -973,6 +1121,9 @@ void init_NR_UE(int nb_inst,
AssertFatal((mac_inst = nr_l2_init_ue(rrc_inst)) != 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

@@ -312,13 +312,15 @@ 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;
@@ -344,15 +346,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;
@@ -479,12 +480,13 @@ int main( int argc, char **argv ) {
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) {
init_pdcp(0);
}
else {
init_pdcp(mode_offset + ue_id_g);
}
}*/
init_pdcp(0);
}
PHY_vars_UE_g = malloc(sizeof(PHY_VARS_NR_UE **));
@@ -522,7 +524,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 +534,25 @@ int main( int argc, char **argv ) {
*mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]);
}
UE[CC_id]->sl_mode = get_softmodem_params()->sl_mode;
init_nr_ue_vars(UE[CC_id], 0, abstraction_flag);
if (UE[CC_id]->sl_mode) {
AssertFatal(UE[CC_id]->sl_mode == 2, "Only Sidelink mode 2 supported. Mode 1 not yet supported\n");
nr_UE_configure_Sidelink(0, get_nrUE_params()->sync_ref);
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);
sl_ue_phy_init(UE[CC_id]);
}
}
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

@@ -12,6 +12,7 @@
#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"
/***************************************************************************************************************************************/
/* 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 */
@@ -61,6 +62,7 @@
{"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}, \
}
// clang-format on
@@ -82,6 +84,7 @@ typedef struct {
int threequarter_fs;
int N_RB_DL;
int ssb_start_subcarrier;
uint32_t sync_ref;
} nrUE_params_t;
extern uint64_t get_nrUE_optmask(void);
extern uint64_t set_nrUE_optmask(uint64_t bitmask);

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

@@ -5,11 +5,30 @@
#define SL_NR_RX_CONFIG_LIST_NUM 1
#define SL_NR_TX_CONFIG_LIST_NUM 1
#define SL_NR_RX_IND_MAX_PDU 1
#define SL_NR_RX_IND_MAX_PDU 2
#define SL_NR_SCI_IND_MAX_PDU 2
#define SL_NR_MAX_PSCCH_SCI_LENGTH_IN_BYTES 8
#define SL_NR_MAX_PSSCH_SCI_LENGTH_IN_BYTES 8
#define SL_NR_MAX_SCI_LENGTH_IN_BYTES 8
typedef struct sl_nr_tti_csi_rs_pdu {
uint8_t subcarrier_spacing; // subcarrierSpacing [3GPP TS 38.211, sec 4.2], Value:0->4
uint8_t cyclic_prefix; // Cyclic prefix type [3GPP TS 38.211, sec 4.2], 0: Normal; 1: Extended
uint16_t start_rb; // PRB where this CSI resource starts related to common resource block #0 (CRB#0). Only multiples of 4 are allowed. [3GPP TS 38.331, sec 6.3.2 parameter CSIFrequencyOccupation], Value: 0 ->274
uint16_t nr_of_rbs; // Number of PRBs across which this CSI resource spans. Only multiples of 4 are allowed. [3GPP TS 38.331, sec 6.3.2 parameter CSI-FrequencyOccupation], Value: 24 -> 276
uint8_t csi_type; // CSI Type [3GPP TS 38.211, sec 7.4.1.5], Value: 0:TRS; 1:CSI-RS NZP; 2:CSI-RS ZP
uint8_t row; // Row entry into the CSI Resource location table. [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 1-18
uint16_t freq_domain; // Bitmap defining the frequencyDomainAllocation [3GPP TS 38.211, sec 7.4.1.5.3] [3GPP TS 38.331 CSIResourceMapping], Value: Up to the 12 LSBs, actual size is determined by the Row parameter
uint8_t symb_l0; // The time domain location l0 and firstOFDMSymbolInTimeDomain [3GPP TS 38.211, sec 7.4.1.5.3], Value: 0->13
uint8_t symb_l1; // The time domain location l1 and firstOFDMSymbolInTimeDomain2 [3GPP TS 38.211, sec 7.4.1.5.3], Value: 2->12
uint8_t cdm_type; // The cdm-Type field [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 0: noCDM; 1: fd-CDM2; 2: cdm4-FD2-TD2; 3: cdm8-FD2-TD4
uint8_t freq_density; // The density field, p and comb offset (for dot5). [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 0: dot5 (even RB); 1: dot5 (odd RB); 2: one; 3: three
uint16_t scramb_id; // ScramblingID of the CSI-RS [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->1023
uint8_t power_control_offset; // Ratio of PDSCH EPRE to NZP CSI-RSEPRE [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->23 representing -8 to 15 dB in 1dB steps; 255: L1 is configured with ProfileSSS
uint8_t power_control_offset_ss; // Ratio of NZP CSI-RS EPRE to SSB/PBCH block EPRE [3GPP TS 38.214, sec 5.2.2.3.1], Values: 0: -3dB; 1: 0dB; 2: 3dB; 3: 6dB; 255: L1 is configured with ProfileSSS
uint8_t measurement_bitmap; // bit 0 RSRP, bit 1 RI, bit 2 LI, bit 3 PMI, bit 4 CQI, bit 5 i1
} sl_nr_tti_csi_rs_pdu_t;
typedef enum sl_sci_format_type_enum {
SL_SCI_INVALID_FORMAT,
SL_SCI_FORMAT_1A_ON_PSCCH,
@@ -29,6 +48,7 @@ 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_CSI_RS,
SL_NR_CONFIG_TYPE_RX_MAXIMUM
} sl_nr_rx_config_type_enum_t;
@@ -36,7 +56,9 @@ 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_PSCCH_PSSCH_PSFCH_CSI_RS,
SL_NR_CONFIG_TYPE_TX_MAXIMUM
} sl_nr_tx_config_type_enum_t;
@@ -68,7 +90,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
@@ -197,6 +219,7 @@ 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_rx_config_request_pdu_t;
// MAC commands PHY to perform an action on RX RESOURCE POOL or RX PSBCH using this RX CONFIG
@@ -208,6 +231,21 @@ typedef struct {
sl_nr_rx_config_request_pdu_t sl_rx_config_list[SL_NR_RX_CONFIG_LIST_NUM];
} sl_nr_rx_config_request_t;
typedef struct sl_nr_tx_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_config_psfch_pdu_t;
//MAC commands PHY to transmit Data on PSCCH, PSSCH.
typedef struct sl_nr_tx_config_pscch_pssch_pdu {
@@ -243,6 +281,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 +306,20 @@ 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_config_psfch_pdu_t psfch_pdu;
//....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 +398,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 +410,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,6 +429,8 @@ 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;

View File

@@ -56,7 +56,7 @@ At runtime, to successfully use hardware acceleration via OpenCL, you need to in
[HW] Device 0 is available
[HW] Device 0, type 2 = 0x00000002: cpu
[HW] Device 0, number of Compute Units: 8
[HW] Device 0, max Work Items dimension: 3
] Device 0, max Work Items dimension: 3
[HW] Device 0, max Work Items size for dimension: 0 8192
[HW] Device 0, max Work Items size for dimension: 1 8192
[HW] Device 0, max Work Items size for dimension: 2 8192

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) {
@@ -634,7 +653,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 +706,365 @@ 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 Ptx=sl_fp->nb_antennas_tx;
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,16 @@ 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, uint8_t sci1_symb, uint16_t sci1_rb, uint16_t sci2_re, uint8_t Qm, uint8_t Nl) {
uint32_t G_SL;
G_SL = ((NR_NB_SC_PER_RB*nb_symb_sch)-(nb_re_dmrs*length_dmrs))*nb_rb*Qm*Nl;
if (sci1_dmrs_overlap > 0) G_SL += (nb_re_dmrs*sci1_rb*Qm*Nl); // return the dmrs that are not transmitted due to SCI1
G_SL -= (sci1_symb*sci1_rb*NR_NB_SC_PER_RB*Qm*Nl); // REs taken by SCI1
G_SL -= (sci2_re*Qm*Nl); // REs taken by SCI2
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,18 @@ 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);
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, uint8_t sci1_symb, uint16_t sci1_rb, uint16_t sci2_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;
@@ -140,7 +145,8 @@ double nr_cyclic_shift_hopping(uint32_t n_id,
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 l = get_softmodem_params()->sl_mode ? 0 : 32;
int minShift = (14*8*nr_slot_tx) + 8*(lnormal+lprime);
int tmpShift =0;
#ifdef DEBUG_NR_PUCCH_TX
printf("\t\t [nr_cyclic_shift_hopping] calculating alpha (cyclic shift) using c_init=%u -> \n",c_init);

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,9 @@ 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);
/*! \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"
@@ -47,6 +48,8 @@
#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
@@ -169,6 +172,7 @@ 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);
@@ -251,16 +255,23 @@ static void nr_processULSegment(void *arg)
//stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats);
}
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)
{
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 +279,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 +393,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 +475,16 @@ 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_I(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,
"[%s %d] ULSCH: 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->frame,
ulsch->slot,
harq_pid,
@@ -492,13 +502,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 +529,25 @@ 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 num_seg_ok = 0;
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);
delNotifiedFIFO_elt(req);
nbDecode--;
}
}
}
return harq_process->C;
}

View File

@@ -3,11 +3,15 @@
#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"
//#define DEBUG_CH_COMP
//#define DEBUG_RB_EXT
@@ -16,8 +20,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 +307,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 +330,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 +347,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 +422,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 +447,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 +650,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 +1108,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 +1952,246 @@ 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;
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];
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) {
if (ue->csirs_vars[0]->active == 1) {
LOG_D(NR_PHY, "%d.%d CSI-RS Received\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 +2202,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 +2212,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 +2231,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 +2295,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 +2314,106 @@ 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)],
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; // need to get this from the inner receiver
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; // need to get from inner rx
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++) {
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 * rel15_ul->qam_mod_order],
rel15_ul->rb_size,
&pusch_vars->llr_layers[aatx][rxdataF_ext_offset * qam_mod_order],
rb_size,
pusch_vars->ul_valid_re_per_slot[symbol],
symbol,
rel15_ul->qam_mod_order);
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");

View File

@@ -1691,7 +1691,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

@@ -608,7 +608,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 +729,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 +751,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 +828,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 +875,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 +907,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 +925,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 +940,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 +952,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 +971,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 +986,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 +1001,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,20 +1018,26 @@ 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,
@@ -1029,12 +1061,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 +1088,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++) {

View File

@@ -52,6 +52,7 @@ 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,
@@ -68,15 +69,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 +145,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,13 +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 DEBUG_CSI_PRINTS // To enable CSI SNR debug logs
extern short nr_qpsk_mod_table[8];
//#define NR_CSIRS_DEBUG
//#define NR_CSIIM_DEBUG
@@ -180,6 +182,87 @@ bool is_csi_rs_in_symbol(const fapi_nr_dl_config_csirs_pdu_rel15_t csirs_config_
return ret;
}
int32_t sl_csi_rs_snr_estimation(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
const NR_DL_FRAME_PARMS *frame_parms,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
{
//FIXME: This function needs to be updated for two ports
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)&ue->csirs_vars[0]->csirs_config_pdu;
csi_rs_params_t table_params;
get_csi_rs_params_from_table(csi_params, &table_params);
const int16_t *fl;
switch (table_params.kprime) {
case 0:
fl = filt8_l0;
break;
case 1:
fl = filt8_l1;
break;
default:
LOG_I(PHY, "%s: ERROR!! Invalid k_prime=%d, symbol %d\n",__FUNCTION__, table_params.kprime, csi_params->symb_l0);
return(-1);
break;
}
// Pilots generation and modulation
uint32_t **nr_gold_csi_rs = ue->nr_csi_info->nr_gold_csi_rs[proc->nr_slot_rx];
int nrRECSI_RS = get_nRECSI_RS(csi_params->freq_density, csi_params->nr_of_rbs);
int16_t mod_csi[nrRECSI_RS << 1];
for (int m = 0; m < nrRECSI_RS; m++) {
uint8_t idx = (((nr_gold_csi_rs[csi_params->symb_l0][(m<<1)>>5])>>((m<<1)&0x1f))&3);
mod_csi[m<<1] = nr_qpsk_mod_table[idx<<1];
mod_csi[(m<<1)+1] = nr_qpsk_mod_table[(idx<<1) + 1];
}
port_freq_indices_t *port_freq_indices = (port_freq_indices_t *)malloc(table_params.ports*sizeof(port_freq_indices));
int32_t snr = 0;
int16_t ch[2] = {0}, noiseFig[2] = {0};
for (uint8_t rxAnt = 0; rxAnt < frame_parms->nb_antennas_rx; rxAnt++) {
snr = 0;
int16_t *pil = (int16_t *)&mod_csi[0];
for (uint8_t rb = csi_params->start_rb; rb < csi_params->start_rb + csi_params->nr_of_rbs; rb++) {
// calculate RE offset
get_csi_rs_freq_ind_sl(frame_parms, rb, csi_params, &table_params, port_freq_indices);
// Channel estimation and interpolation
int16_t *rxF = (int16_t *)&rxdataF[rxAnt][csi_params->symb_l0 * frame_parms->ofdm_symbol_size + port_freq_indices[rxAnt].k];
//Start pilot
c16_t ch_tmp_buf[ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32)));
memset(ch_tmp_buf, 0, sizeof(ch_tmp_buf));
ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15);
ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15);
multadd_real_vector_complex_scalar(fl, ch, (int16_t *)ch_tmp_buf, 8);
//SNR estimation
noiseFig[0] = rxF[0] - (int16_t)(((int32_t)ch[0]*pil[0] - (int32_t)ch[1]*pil[1])>>15);
noiseFig[1] = rxF[1] - (int16_t)(((int32_t)ch[1]*pil[0] + (int32_t)ch[0]*pil[1])>>15);
snr += 10 * log10(squaredMod(*(c16_t*)rxF) - squaredMod(*(c16_t*)noiseFig)) - 10 * log10(squaredMod(*(c16_t*)noiseFig));
#ifdef DEBUG_CSI_PRINTS
LOG_I(NR_PHY, "[Rx %d] symbol %d, carrier %d, SNR %+2d dB: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, %+d) \n",
rxAnt,
csi_params->symb_l0,
port_freq_indices[rxAnt].k,
snr/((rb-csi_params->start_rb)+1),
rxF[0],
rxF[1],
&rxF[0],
ch[0],
ch[1],
pil[0],
pil[1]);
#endif
pil += 2;
} // iterate over all rbs
snr = snr / nrRECSI_RS;
#ifdef DEBUG_CSI_PRINTS
LOG_I(NR_PHY, "[Rx %d] symbol %d Avg SNR %+2d dB, Number of pilots %d\n", rxAnt, csi_params->symb_l0, snr, nrRECSI_RS);
#endif
}
free(port_freq_indices);
port_freq_indices = NULL;
return snr;
}
int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
@@ -205,7 +288,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,9 +313,9 @@ int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue,
((int32_t)(rx_csi_rs_signal[k].i)*rx_csi_rs_signal[k].i));
meas_count++;
LOG_D(NR_PHY, "RX CSI-RS symbol_offset %li k %i symbol_offset+k=%li\n", symbol_offset, k, symbol_offset+k);
#ifdef NR_CSIRS_DEBUG
int dataF_offset = proc->nr_slot_rx*ue->frame_parms.samples_per_slot_wCP;
int dataF_offset = 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",
@@ -270,7 +353,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];
@@ -302,7 +385,7 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
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 +401,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;
}
@@ -386,7 +469,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;
}
@@ -634,7 +717,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;
@@ -837,12 +920,12 @@ 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) {
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);
@@ -887,9 +970,15 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t
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 +1053,31 @@ 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);
if (get_softmodem_params()->sl_mode != 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);
// 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) {
uint32_t snr = sl_csi_rs_snr_estimation(ue,
proc,
frame_parms,
rxdataF);
nr_csi_rs_cqi_estimation(snr, &cqi);
} else
nr_csi_rs_cqi_estimation(precoded_sinr_dB, &cqi);
}
}
switch (csirs_config_pdu->measurement_bitmap) {
@@ -991,7 +1089,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,8 +877,9 @@ 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,
void *ind,
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15) {
//int gNB_id = 0;
@@ -869,6 +887,11 @@ uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
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 +902,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 +920,66 @@ 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; // need to get this from the inner receiver
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 = 0; // need to get from inner rx
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 +988,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;
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,69 @@
/*
* 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_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;
nr_generate_pucch0(ue, txdataF, frame_parms, amp, nr_slot_tx, &pucch_pdu);
}

View File

@@ -211,6 +211,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 +253,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 +265,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,12 +364,13 @@ 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,
void *ind,
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15);
@@ -410,6 +413,36 @@ 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_config_psfch_pdu_t *psfch_pdu);
/**@}*/
#endif

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

@@ -43,6 +43,7 @@
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) {
@@ -54,43 +55,42 @@ 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;
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 +145,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 +217,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;
@@ -238,17 +238,17 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
G,
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 +256,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,41 +174,57 @@ 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 ||
phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH_CSI_RS)
is_csi_rs_slot = true;
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;
LOG_D(NR_PHY, "Tx start_rb %i, cdm_type %i, csi_type %i, freq_density %i, nr_of_rbs %i, row %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);
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;
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 = &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->symb_l0 != 0)
AssertFatal(i != csi_params->symb_l0, "CSI-RS MUST not be sent in DMRS symbol\n");
}
}
if (csi_params->symb_l0 != 0)
AssertFatal(csi_params->symb_l0 > pscch_pssch_pdu->pscch_numsym, "CSI-RS MUST not be sent in PSCCH symbol\n");
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;
harq_process_ul_ue->num_of_mod_symbols = N_RE_prime*nb_rb;
@@ -164,18 +232,56 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
/////////////////////////ULSCH coding/////////////////////////
///////////
unsigned int G = nr_get_G(nb_rb, number_of_symbols,
nb_dmrs_re_per_rb, number_dmrs_symbols, mod_order, Nl);
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,
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;
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,pscch_pssch_pdu->pscch_numsym,pscch_pssch_pdu->pscch_numrbs,sci2_re,mod_order,Nl);
G -= (is_csi_rs_slot ? csi_params->nr_of_rbs/csi_params->freq_density*mod_order*Nl : 0);
LOG_D(NR_PHY, "%d.%d, is_csi_rs_slot %d, G %i, number_of_symbols %i, mod_order %i, freq_density %i, nr_of_rbs %i\n", frame, slot, is_csi_rs_slot, G, number_of_symbols, mod_order, csi_params->freq_density, csi_params->nr_of_rbs);
// 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->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 +291,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 +323,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 +369,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 +393,11 @@ 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 +416,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 +446,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 +491,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 +506,39 @@ 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 = csi_params->start_rb;
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;
}
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 +555,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 +584,25 @@ 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 +611,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 +626,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 +641,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 +673,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 +700,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 +729,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 +752,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];
@@ -591,15 +784,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

@@ -645,7 +645,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"
@@ -309,7 +314,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 +367,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 +440,6 @@ 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];
//Paging parameters
uint32_t IMSImod1024;
uint32_t PF;
@@ -649,6 +653,23 @@ 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;
} PHY_VARS_NR_UE;
typedef struct {
@@ -670,11 +691,25 @@ 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;
} 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)

View File

@@ -0,0 +1,222 @@
/*
* 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;
} 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,7 @@ SystemInformationBlockType1_nr_t;
#define NR_DOWNLINK_SLOT (0x01)
#define NR_UPLINK_SLOT (0x02)
#define NR_MIXED_SLOT (0x03)
#define NR_SIDELINK_SLOT NR_UPLINK_SLOT
#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 */

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);
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,
@@ -137,6 +137,11 @@ int is_pbch_in_slot(fapi_nr_config_request_t *config, int frame, int slot, NR_DL
int is_ssb_in_slot(fapi_nr_config_request_t *config, int frame, int slot, NR_DL_FRAME_PARMS *fp);
bool is_csi_rs_in_symbol(fapi_nr_dl_config_csirs_pdu_rel15_t csirs_config_pdu, int symbol);
int32_t sl_csi_rs_snr_estimation(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
const NR_DL_FRAME_PARMS *frame_parms,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
/*! \brief This function prepares the dl indication to pass to the MAC
@param
@param
@@ -181,6 +186,7 @@ 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,
@@ -191,5 +197,34 @@ 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 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);
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,133 @@ 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_SLSCH_ON_PSSCH_CSI_RS"};
const char *sl_tx_action[] = {"TX_PSBCH", "TX_PSCCH_PSSCH", "TX_PSCCH_PSSCH_PSFCH", "TX_PSCCH_PSSCH_CSI_RS", "TX_PSCCH_PSSCH_PSFCH_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_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, "Recvd %s\n", 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;
}
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:
case SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH_CSI_RS:
phy_data_tx->sl_tx_action = sl_tx_config->tx_config_list[0].pdu_type;
phy_data_tx->nr_sl_pssch_pscch_pdu = sl_tx_config->tx_config_list[0].tx_pscch_pssch_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_PSFCH || phy_data_tx->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH_CSI_RS) {
phy_data_tx->nr_sl_pssch_pscch_pdu.psfch_pdu = sl_tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu.psfch_pdu;
}
if (phy_data_tx->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS || phy_data_tx->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH_CSI_RS) {
phy_data_tx->nr_sl_pssch_pscch_pdu.nr_sl_csi_rs_pdu = sl_tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu.nr_sl_csi_rs_pdu;
}
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 - 6],
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

@@ -99,3 +99,66 @@ int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_frame, int nr_slot)
}
}
}
/*
* This function determines if the mixed slot is a Sidelink slot
*/
uint8_t sl_determine_if_sidelink_slot(uint8_t sl_startsym, uint8_t sl_lensym, uint8_t num_ulsym) {
uint8_t ul_startsym = NR_NUMBER_OF_SYMBOLS_PER_SLOT - num_ulsym;
if ((sl_startsym >= ul_startsym) && (sl_lensym <= NR_NUMBER_OF_SYMBOLS_PER_SLOT)) {
LOG_D(MAC,"MIXED SLOT is a SIDELINK SLOT. Sidelink Symbols: %d-%d, Uplink Symbols: %d-%d\n",
sl_startsym,sl_lensym-1,
ul_startsym, ul_startsym+num_ulsym-1);
return NR_SIDELINK_SLOT;
}
else {
LOG_D(MAC,"MIXED SLOT is NOT SIDELINK SLOT. Sidelink Symbols: %d-%d, Uplink Symbols: %d-%d\n",
sl_startsym,sl_lensym-1,
ul_startsym, ul_startsym+num_ulsym-1);
return 0;
}
}
/*
* This function determines if the Slot is a SIDELINK SLOT
* Every Uplink Slot is a Sidelink slot
* Mixed Slot is a sidelink slot if the uplink symbols in Mixed slot
* overlaps with Sidelink start symbol and number of symbols.
*/
int sl_nr_ue_slot_select(sl_nr_phy_config_request_t *cfg,
int nr_frame, int nr_slot,
uint8_t frame_duplex_type)
{
int mu = cfg->sl_bwp_config.sl_scs, ul_sym = 0, slot_type = 0;
//All PC5 bands are TDD bands , hence handling only TDD in this function.
AssertFatal(frame_duplex_type == TDD, "No Sidelink operation defined for FDD in 3GPP rel16\n");
if (cfg->tdd_table.max_tdd_periodicity_list == NULL) { // this happens before receiving TDD configuration
return 0;
}
int slot = (nr_frame%2 == 0) ? nr_slot : ((1<<mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME) + nr_slot;
for(int symbol_count=0; symbol_count<NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) {
if (cfg->tdd_table.max_tdd_periodicity_list[slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 1) {
ul_sym++;
}
}
if(ul_sym == NR_NUMBER_OF_SYMBOLS_PER_SLOT) {
slot_type = NR_SIDELINK_SLOT;
} else if (ul_sym){
slot_type = sl_determine_if_sidelink_slot(cfg->sl_bwp_config.sl_start_symbol,
cfg->sl_bwp_config.sl_num_symbols,
ul_sym);
}
return slot_type;
}

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,6 +422,7 @@ 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,
@@ -432,7 +433,10 @@ int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
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 +448,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 +459,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);
#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 +468,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 +893,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 +910,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 +962,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 +1003,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,6 +1022,7 @@ 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,
@@ -1006,7 +1034,7 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
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);
}
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 +1067,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 +1146,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 +1157,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,790 @@
/*
* 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: {
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;
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) {
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;
uint8_t nr_of_rbs;
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);
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,
pssch_pdu->pscch_numsym,
pssch_pdu->pscch_numrbs,
sci2_re,
pssch_pdu->mod_order,
pssch_pdu->num_layers);
G -= is_csi_rs_slot ? nr_of_rbs/freq_density*pssch_pdu->mod_order*pssch_pdu->num_layers : 0;
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,"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",
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;
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);
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)
{
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, "SLSCH received ok \n");
slsch_status.rdata = rdata;
slsch_status.rxok = true;
//dumpsig=1;
} else {
LOG_D(NR_PHY,
"[UE] SLSCH: 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",
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, "SLSCH %d in error\n",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;
nr_fill_sl_rx_indication(&sl_rx_indication,SL_NR_RX_PDU_TYPE_SLSCH,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;
//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 && nr_slot_rx==19) {
LOG_I(NR_PHY,"============================================\n");
LOG_I(NR_PHY,"%s[UE%d] %d:%d PSBCH Stats: TX %d, RX ok %d, RX not ok %d\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 %d, RX ok %d\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 %d, RX ok %d, RX not ok %d\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 %d, RX ok %d, RX not ok (%d/%d/%d/%d)\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 %d\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];
//
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);
}
nr_ue_pdcch_procedures(ue, proc, 1, pscch_est_size, pscch_dl_ch_estimates, phy_data, 0, rxdataF);
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);
LOG_D(NR_PHY,"Starting slot FEP for SLSCH (symbol %d to %d) pscch_numsym %d pssch_numsym %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);
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);
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 {
LOG_D(NR_PHY,
"PSSCH 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->DTX = 0;
int totalDecode = nr_slsch_procedures(ue, frame_rx, nr_slot_rx, 0, proc, phy_data, is_csi_rs_slot);
}
}
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", "PSCCH_PSSCH_PSFCH_CSI_RS"};
if (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_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 ||
phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH_CSI_RS) {
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_PSFCH_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);
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);
nr_ue_ulsch_procedures(ue,0,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 ||
phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH_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 ||
phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH_CSI_RS) {
nr_generate_psfch0(ue,
txdataF,
fp,
AMP,
slot_tx,
&phy_data->nr_sl_pssch_pscch_pdu.psfch_pdu);
sl_phy_params->psfch.num_psfch_tx ++;
}
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

@@ -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++) {

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

@@ -797,12 +797,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

@@ -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;
//-----------------------------------------------------------------------------

View File

@@ -94,6 +94,54 @@ uint32_t nr_compute_tbs(uint16_t Qm,
return nr_tbs;
}
uint32_t nr_compute_tbs_sl(uint16_t Qm,
uint16_t R,
uint16_t nb_re,
uint8_t Nl)
{
LOG_D(NR_MAC, "In %s: nb_re %d, Nl %d\n", __FUNCTION__, nb_re,Nl);
// Intermediate number of information bits
// Rx1024 is tabulated as 10 times the actual code rate
const uint32_t R_5 = R/5; // R can be fractional so we can't divide by 10
// So we ned to right shift by 11 (10 for x1024 and 1 additional as above)
const uint32_t Ninfo = ((nb_re * R_5 * Qm * Nl)>>11);
uint32_t nr_tbs=0;
uint32_t Np_info, C, n;
if (Ninfo <=3824) {
n = max(3, floor(log2(Ninfo)) - 6);
Np_info = max(24, (Ninfo>>n)<<n);
for (int i=0; i<INDEX_MAX_TBS_TABLE; i++) {
if (Tbstable_nr[i] >= Np_info){
nr_tbs = Tbstable_nr[i];
break;
}
}
} else {
n = log2(Ninfo-24)-5;
Np_info = max(3840, (ROUNDIDIV((Ninfo-24),(1<<n)))<<n);
if (R <= 2560) {
C = CEILIDIV((Np_info+24),3816);
nr_tbs = (C<<3)*CEILIDIV((Np_info+24),(C<<3)) - 24;
} else {
if (Np_info > 8424){
C = CEILIDIV((Np_info+24),8424);
nr_tbs = (C<<3)*CEILIDIV((Np_info+24),(C<<3)) - 24;
} else {
nr_tbs = ((CEILIDIV((Np_info+24),8))<<3) - 24;
}
}
}
LOG_D(NR_MAC, "In %s: Ninfo %u nb_re %d Qm %d, R %d, tbs %d bits\n", __FUNCTION__, Ninfo, nb_re, Qm, R, nr_tbs);
return nr_tbs;
}
//tbslbrm calculation according to 5.4.2.1 of 38.212

View File

@@ -38,6 +38,8 @@
#include <string.h>
#include <stdbool.h>
#include "common/utils/nr/nr_common.h"
#include "common/utils/collection/linear_alloc.h"
#include "NR_CellGroupConfig.h"
#define NR_SHORT_BSR_TABLE_SIZE 32
@@ -112,9 +114,17 @@ typedef struct {
uint8_t R: 2; // octet 1 [7:6]
} __attribute__ ((__packed__)) NR_MAC_SUBHEADER_FIXED;
// 38321 section 6.1.6 Figure 6.1.6-1
typedef struct {
uint8_t V: 4; // octet 1 [7:4]
uint8_t R: 4; // octet 1 [3:0]
uint16_t SRC: 16; // octet 2, octet 3
uint8_t DST: 8; // octet 4
}__attribute__ ((__packed__)) NR_SLSCH_MAC_SUBHEADER_FIXED;
static inline int get_mac_len(uint8_t* pdu, int pdu_len, uint16_t *mac_ce_len, uint16_t *mac_subheader_len) {
if ( pdu_len < (int)sizeof(NR_MAC_SUBHEADER_SHORT))
return false;
return false;
NR_MAC_SUBHEADER_SHORT *s = (NR_MAC_SUBHEADER_SHORT*) pdu;
NR_MAC_SUBHEADER_LONG *l = (NR_MAC_SUBHEADER_LONG*) pdu;
if (s->F && pdu_len < (int)sizeof(NR_MAC_SUBHEADER_LONG))
@@ -128,7 +138,18 @@ static inline int get_mac_len(uint8_t* pdu, int pdu_len, uint16_t *mac_ce_len, u
}
return true;
}
// SL BSR MAC CEs
// TS 38.321 ch. 6.1.3.33
// Short BSR for a specific logical channel group ID
typedef struct {
uint8_t destination_index: 5; // octet 1 MSB
uint8_t LcgID: 3; // octet 1 LSB
uint8_t Buffer_size: 8;
} __attribute__ ((__packed__)) NR_SL_BSR_SHORT;
typedef NR_SL_BSR_SHORT NR_SL_BSR_SHORT_TRUNCATED;
// BSR MAC CEs
// TS 38.321 ch. 6.1.3.1
// Short BSR for a specific logical channel group ID
@@ -404,6 +425,22 @@ typedef struct {
#define NR_MAX_NUM_LCID 32
#define NR_MAX_NUM_LCGID 8
#define SL_SCH_LCID_SCCH_PC5_NOT_PROT 0 // SCCH carrying PC5-S messages that are not protected
#define SL_SCH_LCID_SCCH_PC5_DSMC 1 // SCCH carrying PC5-S messages "Direct Security Mode Command" and "Direct Security Mode Complete"
#define SL_SCH_LCID_SCCH_PC5_PROT 2 // SCCH carrying other PC5-S messages that are protected
#define SL_SCH_LCID_SCCH_PC5_RRC 3 // SCCH carrying PC5-RRC messages
#define SL_SCH_LCID_4_19 4 // 419 Identity of the logical channel
#define SL_SCH_LCID_20_55 20 // 2055 Reserved
#define SL_SCH_LCID_SCCH_RRC_SL_RLC0 56 // SCCH carrying RRC messages delivered via SL-RLC0 as specified in TS 38.331 [5]
#define SL_SCH_LCID_SCCH_RRC_SL_RLC1 57 // SCCH carrying RRC message delivered via SL-RLC1 as specified in TS 38.331 [5]
#define SL_SCH_LCID_SCCH_SL_DISCOVERY 58 // SCCH for Sidelink Discovery Messages
#define SL_SCH_LCID_SL_INTER_UE_COORD_REQ 59 // Sidelink Inter-UE Coordination Request
#define SL_SCH_LCID_SL_INTER_UE_COORD_INFO 60 // Sidelink Inter-UE Coordination Information
#define SL_SCH_LCID_SL_DRX_CMD 61 // Sidelink DRX Command
#define SL_SCH_LCID_SL_CSI_REPORT 62 // Sidelink CSI Reporting
#define SL_SCH_LCID_SL_PADDING 63 // Padding
#define MAX_RLC_SDU_SUBHEADER_SIZE 3
//===========
@@ -534,6 +571,25 @@ typedef struct nr_csi_report {
int N2;
} nr_csi_report_t;
// 38321 sec. 6.1.3.35
typedef struct {
uint8_t RI: 1; // 7th bit
uint8_t CQI: 4; // 3-6 bits
uint8_t R: 3; // 0-2 bits
} __attribute__ ((__packed__)) nr_sl_csi_report_t;
// 38321 sec. 6.1.3.34
typedef struct {
uint8_t C1: 1; // 1st bit
uint8_t C2: 1; // 2nd bit
uint8_t C3: 1; // 3rd bit
uint8_t C4: 1; // 4th bit
uint8_t C5: 1; // 5th bit
uint8_t C6: 1; // 6th bit
uint8_t C7: 1; // 7th bit
uint8_t C8: 1; // 8th bit
} __attribute__ ((__packed__)) nr_sl_config_grant_t;
typedef enum {
NR_SRS_SRI_0 = 0,
NR_SRS_SRI_1,
@@ -619,5 +675,21 @@ typedef struct NR_tda_info {
long k2;
} NR_tda_info_t;
typedef struct NR_bler_stats {
frame_t last_frame;
float bler;
uint8_t mcs;
uint64_t rounds[8];
} NR_bler_stats_t;
/*! \brief NR_list_t is a "list" (of users, HARQ processes, slices, ...).
* * Especially useful in the scheduler and to keep "classes" of users. */
typedef struct {
int head;
int *next;
int tail;
int len;
} NR_list_t;
#endif /*__LAYER2_MAC_H__ */

View File

@@ -185,6 +185,12 @@ uint32_t nr_compute_tbs(uint16_t Qm,
uint8_t tb_scaling,
uint8_t Nl);
uint32_t nr_compute_tbs_sl(uint16_t Qm,
uint16_t R,
uint16_t nb_re,
uint8_t Nl);
/** \brief Computes Q based on I_MCS PDSCH and table_idx for downlink. Implements MCS Tables from 38.214. */
uint8_t nr_get_Qm_dl(uint8_t Imcs, uint8_t table_idx);
uint32_t nr_get_code_rate_dl(uint8_t Imcs, uint8_t table_idx);

View File

@@ -0,0 +1,696 @@
/*
* 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 "openair2/LAYER2/NR_MAC_UE/mac_defs.h"
#include "openair2/LAYER2/NR_MAC_UE/nr_ue_sci.h"
#include "NR_SidelinkPreconfigNR-r16.h"
#include "mac_proto.h"
#include "common/config/config_paramdesc.h"
#include <executables/nr-uesoftmodem.h>
#define SL_CONFIG_STRING_SL_PRECONFIGURATION "SIDELINK_PRECONFIGURATION"
/* Sidelink CSI-RS configuration parameters for MAC*/
#define SL_CONFIG_STRING_SL_CSI_RS_LIST "sl_csi_rs"
#define SL_CONFIG_STRING_SL_CSI_RS_SYMB_L0 "symb_l0"
#define SL_CONFIG_STRING_SL_CSI_RS_CSI_TYPE "csi_Type"
#define SL_CONFIG_STRING_SL_CSI_RS_SLOT_OFFSET "slot_Offset"
#define SL_CONFIG_STRING_SL_CSI_RS_SLOT_PERIODICITY "slot_Periodicity"
#define SL_CONFIG_STRING_SL_CSI_RS_POWER_CONTROL_OFFSET "sl_powerControlOffset"
#define SL_CONFIG_STRING_SL_CSI_RS_POWER_CONTROL_OFFSET_SS "sl_powerControlOffsetSS"
#define SL_CONFIG_STRING_SL_CSI_RS_SL_CSI_ACQUISITION "sl_CSI_Acquisition"
#define SL_CSI_RS_DESC(sl_csi_info) { \
{SL_CONFIG_STRING_SL_CSI_RS_SYMB_L0,NULL,0,.u8ptr=&sl_csi_info->symb_l0,.defuintval=1,TYPE_UINT8,0}, \
{SL_CONFIG_STRING_SL_CSI_RS_CSI_TYPE,NULL,0,.u8ptr=&sl_csi_info->csi_type,.defuintval=1,TYPE_UINT8,0}, \
{SL_CONFIG_STRING_SL_CSI_RS_POWER_CONTROL_OFFSET,NULL,0,.u8ptr=&sl_csi_info->power_control_offset,.defuintval=1,TYPE_UINT8,0}, \
{SL_CONFIG_STRING_SL_CSI_RS_POWER_CONTROL_OFFSET_SS,NULL,0,.u8ptr=&sl_csi_info->power_control_offset_ss,.defuintval=1,TYPE_UINT8,0}, \
{SL_CONFIG_STRING_SL_CSI_RS_SLOT_OFFSET,NULL,0,.u8ptr=&sl_csi_info->slot_offset,.defuintval=1,TYPE_UINT8,0}, \
{SL_CONFIG_STRING_SL_CSI_RS_SLOT_PERIODICITY,NULL,0,.u8ptr=&sl_csi_info->slot_periodicity,.defuintval=1,TYPE_UINT8,0}, \
{SL_CONFIG_STRING_SL_CSI_RS_SL_CSI_ACQUISITION,NULL,0,.u8ptr=&sl_csi_info->sl_csi_acquisition,.defuintval=1,TYPE_UINT8,0}}
typedef struct sl_csi_info {
uint8_t symb_l0;
uint8_t csi_type;
uint8_t slot_offset;
uint8_t slot_periodicity;
uint8_t power_control_offset;
uint8_t power_control_offset_ss;
uint8_t sl_csi_acquisition;
} sl_csi_info_t;
void sl_ue_mac_free(uint8_t module_id)
{
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
sl_nr_phy_config_request_t *sl_config =
&mac->SL_MAC_PARAMS->sl_phy_config.sl_config_req;
uint8_t syncsource = sl_config->sl_sync_source.sync_source;
//Allocated by MAC only in case of SYNC_REF_UE
//else it is freed as part of RRC pre-config structure
if (syncsource == SL_SYNC_SOURCE_SYNC_REF_UE &&
mac->SL_MAC_PARAMS->sl_TDD_config) {
ASN_STRUCT_FREE (asn_DEF_NR_TDD_UL_DL_Pattern, mac->SL_MAC_PARAMS->sl_TDD_config);
mac->SL_MAC_PARAMS->sl_TDD_config = NULL;
}
fapi_nr_max_tdd_periodicity_t *tdd_list =
sl_config->tdd_table.max_tdd_periodicity_list;
// @todo: maybe this should be done by phy
if (tdd_list) {
int mu = sl_config->sl_bwp_config.sl_scs;
int nb_slots_to_set = TDD_CONFIG_NB_FRAMES*(1<<mu)*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
for (int i=0; i<nb_slots_to_set; i++) {
free_and_zero(tdd_list[i].max_num_of_symbol_per_slot_list);
}
free_and_zero(sl_config->tdd_table.max_tdd_periodicity_list);
}
for (int i=0;i<SL_NR_MAC_NUM_RX_RESOURCE_POOLS;i++) {
free_and_zero(mac->SL_MAC_PARAMS->sl_RxPool[i]);
}
for (int i=0;i<SL_NR_MAC_NUM_TX_RESOURCE_POOLS;i++) {
free_and_zero(mac->SL_MAC_PARAMS->sl_TxPool[i]);
}
free_and_zero(mac->SL_MAC_PARAMS);
}
//Prepares the TDD config to be passed to PHY
static int sl_set_tdd_config_nr_ue(sl_nr_phy_config_request_t *cfg,
int mu,
int nrofDownlinkSlots, int nrofDownlinkSymbols,
int nrofUplinkSlots, int nrofUplinkSymbols)
{
int slot_number = 0;
int nb_periods_per_frame = get_nb_periods_per_frame(cfg->tdd_table.tdd_period);
int nb_slots_to_set = TDD_CONFIG_NB_FRAMES*(1<<mu)*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
int nb_slots_per_period = ((1<<mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME)/nb_periods_per_frame;
cfg->tdd_table.tdd_period_in_slots = nb_slots_per_period;
if ((nrofDownlinkSlots == 0) && (nrofDownlinkSymbols == 0)) {
nrofDownlinkSymbols = (nrofUplinkSymbols) ? 14 - nrofUplinkSymbols : 0;
nrofDownlinkSlots = nb_slots_per_period - nrofUplinkSlots;
if (nrofDownlinkSymbols) nrofDownlinkSlots -= 1;
}
LOG_I(NR_MAC,"Set Phy Sidelink TDD Config: scs:%d,dl:%d-%d, ul:%d-%d, nb_periods_per_frame:%d, nb_slots_per_period:%d\n",
mu, nrofDownlinkSlots, nrofDownlinkSymbols, nrofUplinkSlots, nrofUplinkSymbols, nb_periods_per_frame, nb_slots_per_period);
if ( (nrofDownlinkSymbols + nrofUplinkSymbols) == 0 )
AssertFatal(nb_slots_per_period == (nrofDownlinkSlots + nrofUplinkSlots),
"set_tdd_configuration_nr: given period is inconsistent with current tdd configuration, nrofDownlinkSlots %d, nrofUplinkSlots %d, nb_slots_per_period %d \n",
nrofDownlinkSlots,nrofUplinkSlots,nb_slots_per_period);
else {
AssertFatal(nrofDownlinkSymbols + nrofUplinkSymbols <= 14,"illegal symbol configuration DL %d, UL %d\n",nrofDownlinkSymbols,nrofUplinkSymbols);
AssertFatal(nb_slots_per_period == (nrofDownlinkSlots + nrofUplinkSlots + 1),
"set_tdd_configuration_nr: given period is inconsistent with current tdd configuration, nrofDownlinkSlots %d, nrofUplinkSlots %d, nrofMixed slots 1, nb_slots_per_period %d \n",
nrofDownlinkSlots,nrofUplinkSlots,nb_slots_per_period);
}
cfg->tdd_table.max_tdd_periodicity_list = (fapi_nr_max_tdd_periodicity_t *) malloc(nb_slots_to_set*sizeof(fapi_nr_max_tdd_periodicity_t));
for(int memory_alloc =0 ; memory_alloc<nb_slots_to_set; memory_alloc++)
cfg->tdd_table.max_tdd_periodicity_list[memory_alloc].max_num_of_symbol_per_slot_list = (fapi_nr_max_num_of_symbol_per_slot_t *) malloc(NR_NUMBER_OF_SYMBOLS_PER_SLOT*sizeof(
fapi_nr_max_num_of_symbol_per_slot_t));
while(slot_number != nb_slots_to_set) {
if(nrofDownlinkSlots != 0) {
for (int number_of_symbol = 0; number_of_symbol < nrofDownlinkSlots*NR_NUMBER_OF_SYMBOLS_PER_SLOT; number_of_symbol++) {
cfg->tdd_table.max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol%NR_NUMBER_OF_SYMBOLS_PER_SLOT].slot_config= 0;
if((number_of_symbol+1)%NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0)
slot_number++;
}
}
if (nrofDownlinkSymbols != 0 || nrofUplinkSymbols != 0) {
for(int number_of_symbol =0; number_of_symbol < nrofDownlinkSymbols; number_of_symbol++) {
cfg->tdd_table.max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol].slot_config= 0;
}
for(int number_of_symbol = nrofDownlinkSymbols; number_of_symbol < NR_NUMBER_OF_SYMBOLS_PER_SLOT-nrofUplinkSymbols; number_of_symbol++) {
cfg->tdd_table.max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol].slot_config= 2;
}
for(int number_of_symbol = NR_NUMBER_OF_SYMBOLS_PER_SLOT-nrofUplinkSymbols; number_of_symbol < NR_NUMBER_OF_SYMBOLS_PER_SLOT; number_of_symbol++) {
cfg->tdd_table.max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol].slot_config= 1;
}
slot_number++;
}
if(nrofUplinkSlots != 0) {
for (int number_of_symbol = 0; number_of_symbol < nrofUplinkSlots*NR_NUMBER_OF_SYMBOLS_PER_SLOT; number_of_symbol++) {
cfg->tdd_table.max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol%NR_NUMBER_OF_SYMBOLS_PER_SLOT].slot_config= 1;
if((number_of_symbol+1)%NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0)
slot_number++;
}
}
}
return (0);
}
//Prepares the PHY config to be sent to PHY. Prepares from the Valus from MAC context.
static void sl_prepare_phy_config(int module_id,
sl_nr_phy_config_request_t *phycfg,
NR_SL_FreqConfigCommon_r16_t *freqcfg,
uint8_t sync_source,
uint32_t sl_OffsetDFN,
NR_TDD_UL_DL_ConfigCommon_t *sl_TDD_config)
{
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
phycfg->sl_sync_source.sync_source = sync_source;
LOG_I(NR_MAC, "Sidelink CFG: sync source:%d\n", phycfg->sl_sync_source.sync_source);
uint32_t pointA_ARFCN = freqcfg->sl_AbsoluteFrequencyPointA_r16;
AssertFatal(pointA_ARFCN, "sl_AbsoluteFrequencyPointA_r16 cannot be 0\n");
int sl_band = 0;
if (pointA_ARFCN >= 790334 && pointA_ARFCN <= 795000)
sl_band = 47;
else if (pointA_ARFCN >= 514000 && pointA_ARFCN <= 524000)
sl_band = 38;
AssertFatal(sl_band, "not valid band for Sidelink operation\n");
uint32_t SSB_ARFCN = (freqcfg->sl_AbsoluteFrequencySSB_r16)
? *freqcfg->sl_AbsoluteFrequencySSB_r16 : 0;
AssertFatal(SSB_ARFCN, "sl_AbsoluteFrequencySSB cannot be 0\n");
LOG_I(NR_MAC, "SIDELINK CONFIGs: AbsFreqSSB:%d, AbsFreqPointA:%d, SL band:%d\n",
SSB_ARFCN,pointA_ARFCN, sl_band);
#define SL_VALUE_FREQSHIFT_7P5KHZ_DISABLED 0
phycfg->sl_carrier_config.sl_frequency_shift_7p5khz = SL_VALUE_FREQSHIFT_7P5KHZ_DISABLED;
phycfg->sl_carrier_config.sl_value_N = freqcfg->valueN_r16;
phycfg->sl_carrier_config.sl_num_tx_ant = 1;
phycfg->sl_carrier_config.sl_num_rx_ant = 1;
NR_SCS_SpecificCarrier_t *carriercfg =
freqcfg->sl_SCS_SpecificCarrierList_r16.list.array[0];
AssertFatal(carriercfg, "SCS_SpecificCarrier cannot be NULL");
int bw_index = get_supported_band_index(carriercfg->subcarrierSpacing,
sl_band,
carriercfg->carrierBandwidth);
phycfg->sl_carrier_config.sl_bandwidth = get_supported_bw_mhz(FR1, bw_index);
phycfg->sl_carrier_config.sl_frequency =
from_nrarfcn(sl_band,carriercfg->subcarrierSpacing,pointA_ARFCN)/1000; // freq in kHz
phycfg->sl_carrier_config.sl_grid_size = carriercfg->carrierBandwidth;
//For sidelink offset to carrier is 0. hence not used
//phycfg->sl_carrier_config.sl_k0 = carriercfg->offsetToCarrier;
NR_SL_BWP_Generic_r16_t *bwp_generic = NULL;
if (freqcfg->sl_BWP_List_r16 &&
freqcfg->sl_BWP_List_r16->list.array[0] &&
freqcfg->sl_BWP_List_r16->list.array[0]->sl_BWP_Generic_r16)
bwp_generic = freqcfg->sl_BWP_List_r16->list.array[0]->sl_BWP_Generic_r16;
AssertFatal(bwp_generic, "SL-BWP Generic cannot be NULL");
NR_BWP_t *sl_bwp = bwp_generic->sl_BWP_r16;
AssertFatal(sl_bwp, "SL-BWP cannot be NULL");
int locbw = bwp_generic->sl_BWP_r16->locationAndBandwidth;
phycfg->sl_bwp_config.sl_bwp_size = NRRIV2BW(locbw, MAX_BWP_SIZE);
phycfg->sl_bwp_config.sl_bwp_start = NRRIV2PRBOFFSET(locbw, MAX_BWP_SIZE);
phycfg->sl_bwp_config.sl_scs = sl_bwp->subcarrierSpacing;
int scs_scaling = 1<<(phycfg->sl_bwp_config.sl_scs);
if (pointA_ARFCN < 600000)
scs_scaling = scs_scaling*3;
if (pointA_ARFCN > 2016666)
scs_scaling = scs_scaling>>2;
//SSB arfcn points to middle RE of PSBCH 11 RBs
uint32_t diff = (SSB_ARFCN - 66*scs_scaling) - pointA_ARFCN;
//the RE offset from pointA where SSB starts
phycfg->sl_bwp_config.sl_ssb_offset_point_a = diff/scs_scaling;
#ifdef SL_DEBUG
printf("diff:%d, scaling:%d, pointa:%d, ssb:%d\n", diff, scs_scaling, pointA_ARFCN, SSB_ARFCN);
#endif
phycfg->sl_bwp_config.sl_dc_location = (bwp_generic->sl_TxDirectCurrentLocation_r16) ?
*bwp_generic->sl_TxDirectCurrentLocation_r16 : 0;
const uint8_t values[] = {7,8,9,10,11,12,13,14};
phycfg->sl_bwp_config.sl_num_symbols = (bwp_generic->sl_LengthSymbols_r16) ?
values[*bwp_generic->sl_LengthSymbols_r16] : 0;
phycfg->sl_bwp_config.sl_start_symbol = (bwp_generic->sl_StartSymbol_r16) ?
*bwp_generic->sl_StartSymbol_r16 : 0;
//0-EXTENDED, 1-NORMAL CP
phycfg->sl_bwp_config.sl_cyclic_prefix = (sl_bwp->cyclicPrefix) ? EXTENDED : NORMAL;
AssertFatal(phycfg->sl_bwp_config.sl_cyclic_prefix == NORMAL, "Only NORMAL-CP Supported. Ext CP not yet supported\n");
AssertFatal(phycfg->sl_bwp_config.sl_start_symbol >= 0 && phycfg->sl_bwp_config.sl_start_symbol <=7,
"Sidelink Start symbol should be in range 0-7\n");
AssertFatal(phycfg->sl_bwp_config.sl_num_symbols >= 7 && phycfg->sl_bwp_config.sl_num_symbols <=14,
"Num Sidelink symbols should be in range 7-14\n");
AssertFatal((phycfg->sl_bwp_config.sl_start_symbol + phycfg->sl_bwp_config.sl_num_symbols) <= 14,
"Incorrect configuration of Start and num SL symbols\n");
//Configure PHY with TDD config only if the sync source is known.
if (sync_source == SL_SYNC_SOURCE_LOCAL_TIMING ||
sync_source == SL_SYNC_SOURCE_GNSS) {
phycfg->config_mask = 0xF;//Total config is sent
phycfg->sl_sync_source.gnss_dfn_offset = sl_OffsetDFN;
// TDD Table Configuration
if (sl_TDD_config->pattern1.ext1 == NULL)
phycfg->tdd_table.tdd_period = sl_TDD_config->pattern1.dl_UL_TransmissionPeriodicity;
else {
if (sl_TDD_config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL)
phycfg->tdd_table.tdd_period += (1 + *sl_TDD_config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530);
}
int return_tdd = sl_set_tdd_config_nr_ue(phycfg,
sl_TDD_config->referenceSubcarrierSpacing,
sl_TDD_config->pattern1.nrofDownlinkSlots,
sl_TDD_config->pattern1.nrofDownlinkSymbols,
sl_TDD_config->pattern1.nrofUplinkSlots,
sl_TDD_config->pattern1.nrofUplinkSymbols);
if (return_tdd !=0)
LOG_E(PHY,"TDD configuration can not be done\n");
else {
LOG_I(NR_MAC, "SIDELINK CONFIGs: tdd config period:%d, mu:%ld, DLslots:%ld,ULslots:%ld Mixedslotsym DL:UL %ld:%ld\n",
phycfg->tdd_table.tdd_period, sl_TDD_config->referenceSubcarrierSpacing,
sl_TDD_config->pattern1.nrofDownlinkSlots, sl_TDD_config->pattern1.nrofUplinkSlots,
sl_TDD_config->pattern1.nrofDownlinkSymbols,sl_TDD_config->pattern1.nrofUplinkSymbols);
}
} else if (sync_source == SL_SYNC_SOURCE_NONE) {
//Only Carrier config, BWP config sent
phycfg->config_mask = 0x9;//partial config is sent
}
//#ifdef SL_DEBUG
char str[5][20] = {"NONE","GNBENB","GNSS","SYNC_REF_UE","LOCAL_TIMING"};
LOG_I(NR_MAC, "UE[%d] Function %s - Phy config preparation:\n",module_id, __FUNCTION__);
LOG_I(NR_MAC, "UE[%d] Sync source params: sync_source :%d-%s, gnss_dfn_offset:%d, rx_slss_id:%d\n",
module_id,phycfg->sl_sync_source.sync_source,
str[phycfg->sl_sync_source.sync_source],
phycfg->sl_sync_source.gnss_dfn_offset,
phycfg->sl_sync_source.rx_slss_id);
LOG_I(NR_MAC, "UE[%d] Carrier CFG Params: freq:%ld, bw:%d, gridsize:%d, rxant:%d, txant:%d, valueN:%d\n",
module_id,phycfg->sl_carrier_config.sl_frequency,
phycfg->sl_carrier_config.sl_bandwidth,
phycfg->sl_carrier_config.sl_grid_size,
phycfg->sl_carrier_config.sl_num_rx_ant,
phycfg->sl_carrier_config.sl_num_tx_ant,
phycfg->sl_carrier_config.sl_value_N);
LOG_I(NR_MAC, "UE[%d] SL-BWP Params: start:%d, size:%d, scs:%d, Ncp:%d, startsym:%d, numsym:%d,ssb_offset:%d,dcloc:%d\n",
module_id,phycfg->sl_bwp_config.sl_bwp_start,
phycfg->sl_bwp_config.sl_bwp_size,
phycfg->sl_bwp_config.sl_scs,
phycfg->sl_bwp_config.sl_cyclic_prefix,
phycfg->sl_bwp_config.sl_start_symbol,
phycfg->sl_bwp_config.sl_num_symbols,
phycfg->sl_bwp_config.sl_ssb_offset_point_a,
phycfg->sl_bwp_config.sl_dc_location);
//#endif
return;
}
// RRC calls this API when RRC is configured with Sidelink PRE-configuration I.E
int nr_rrc_mac_config_req_sl_preconfig(module_id_t module_id,
NR_SL_PreconfigurationNR_r16_t *sl_preconfiguration,
uint8_t sync_source,
int src_id)
{
LOG_I(NR_MAC,"[UE%d] SL RRC->MAC CONFIG RECEIVED. Syncsource:%d\n",
module_id, sync_source);
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
mac->src_id = src_id;
AssertFatal(sl_preconfiguration !=NULL,"SL-Preconfig Cannot be NULL");
AssertFatal(mac, "mac should have an instance");
mac->SL_MAC_PARAMS = CALLOC(1, sizeof(sl_nr_ue_mac_params_t));
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
NR_SidelinkPreconfigNR_r16_t *sl_preconfig = &sl_preconfiguration->sidelinkPreconfigNR_r16;
//Only one entry supported in rel16.
//Carrier freq config used for Sidelink
NR_SL_FreqConfigCommon_r16_t *freqcfg = (sl_preconfig->sl_PreconfigFreqInfoList_r16)
? sl_preconfig->sl_PreconfigFreqInfoList_r16->list.array[0]
: NULL;
AssertFatal(freqcfg !=NULL,"SL fcfg Cannot be NULL");
//MAx num of consecutive HARQ DTX before triggering RLF.
const uint8_t MaxNumConsecutiveDTX[] = {1,2,3,4,6,8,16,32};
sl_mac->sl_MaxNumConsecutiveDTX = (sl_preconfig->sl_MaxNumConsecutiveDTX_r16)
? MaxNumConsecutiveDTX[*sl_preconfig->sl_MaxNumConsecutiveDTX_r16]
: 0;
//priority of SL-SSB tx and rx
sl_mac->sl_SSB_PriorityNR = (sl_preconfig->sl_SSB_PriorityNR_r16)
? *sl_preconfig->sl_SSB_PriorityNR_r16 : 0;
//Used for DFN calculation in case Sync source = GNSS.
uint32_t sl_OffsetDFN = (sl_preconfig->sl_OffsetDFN_r16)
? *sl_preconfig->sl_OffsetDFN_r16 : 0;
NR_SL_BWP_ConfigCommon_r16_t *bwp = NULL;
if (freqcfg->sl_BWP_List_r16 &&
freqcfg->sl_BWP_List_r16->list.array[0])
bwp = freqcfg->sl_BWP_List_r16->list.array[0];
mac->sl_bwp = bwp;
AssertFatal(bwp!=NULL, "BWP config common cannot be NULL\n");
if (bwp->sl_BWP_PoolConfigCommon_r16) {
if (bwp->sl_BWP_PoolConfigCommon_r16->sl_RxPool_r16) {
for (int i=0;i<bwp->sl_BWP_PoolConfigCommon_r16->sl_RxPool_r16->list.count;i++) {
NR_SL_ResourcePool_r16_t *rxpool = bwp->sl_BWP_PoolConfigCommon_r16->sl_RxPool_r16->list.array[i];
if (rxpool) {
if (sl_mac->sl_RxPool[i] == NULL)
sl_mac->sl_RxPool[i] = malloc16_clear(sizeof(SL_ResourcePool_params_t));
mac->sl_rx_res_pool = rxpool;
sl_mac->sl_RxPool[i]->respool = rxpool;
uint16_t sci_1a_len = 0, num_subch = 0;
sci_1a_len = sl_determine_sci_1a_len(&num_subch,
sl_mac->sl_RxPool[i]->respool,
&sl_mac->sl_RxPool[i]->sci_1a);
sl_mac->sl_RxPool[i]->num_subch = num_subch;
sl_mac->sl_RxPool[i]->sci_1a_len = sci_1a_len;
LOG_I(NR_MAC,"Rxpool[%d] - num subchannels:%d, sci_1a_len:%d\n",i,
sl_mac->sl_RxPool[i]->num_subch,
sl_mac->sl_RxPool[i]->sci_1a_len);
}
}
}
if (bwp->sl_BWP_PoolConfigCommon_r16->sl_TxPoolSelectedNormal_r16) {
for (int i=0;i<bwp->sl_BWP_PoolConfigCommon_r16->sl_TxPoolSelectedNormal_r16->list.count;i++) {
NR_SL_ResourcePool_r16_t *txpool =
bwp->sl_BWP_PoolConfigCommon_r16->sl_TxPoolSelectedNormal_r16->list.array[0]->sl_ResourcePool_r16;
if (txpool) {
mac->sl_tx_res_pool = txpool;
if (sl_mac->sl_TxPool[i] == NULL)
sl_mac->sl_TxPool[i] = malloc16_clear(sizeof(SL_ResourcePool_params_t));
sl_mac->sl_TxPool[i]->respool = txpool;
uint16_t sci_1a_len = 0, num_subch = 0;
sci_1a_len = sl_determine_sci_1a_len(&num_subch,
sl_mac->sl_TxPool[i]->respool,
&sl_mac->sl_TxPool[i]->sci_1a);
sl_mac->sl_TxPool[i]->num_subch = num_subch;
sl_mac->sl_TxPool[i]->sci_1a_len = sci_1a_len;
LOG_I(NR_MAC,"Txpool[%d] - num subchannels:%d, sci_1a_len:%d\n",i,
sl_mac->sl_TxPool[i]->num_subch,
sl_mac->sl_TxPool[i]->sci_1a_len);
}
}
}
}
if (sync_source == SL_SYNC_SOURCE_GNSS ||
sync_source == SL_SYNC_SOURCE_LOCAL_TIMING) {
NR_TDD_UL_DL_ConfigCommon_t *tdd_uldl_config = NULL;
if (sl_preconfig->sl_PreconfigGeneral_r16 &&
sl_preconfig->sl_PreconfigGeneral_r16->sl_TDD_Configuration_r16)
tdd_uldl_config = sl_preconfig->sl_PreconfigGeneral_r16->sl_TDD_Configuration_r16;
AssertFatal((tdd_uldl_config!=NULL), "Sidelink MAC CFG: TDD Config cannot be NULL");
AssertFatal((tdd_uldl_config->pattern2 == NULL), "Sidelink MAC CFG: pattern2 not yet supported");
sl_mac->sl_TDD_config = sl_preconfig->sl_PreconfigGeneral_r16->sl_TDD_Configuration_r16;
//Sync source is identified, timing needs to be adjusted.
sl_mac->adjust_timing = 1;
}
//Do not copy TDD config yet as SYNC source is not yet found
if (sync_source == SL_SYNC_SOURCE_NONE) {
if (sl_mac->sl_TDD_config)
ASN_STRUCT_FREE(asn_DEF_NR_TDD_UL_DL_ConfigCommon, sl_mac->sl_TDD_config);
sl_mac->sl_TDD_config = NULL;
}
// Configuring CSI-RS parameters locally at MAC.
nr_sl_params_read_conf(module_id);
nr_sl_phy_config_t *sl_phy_cfg = &sl_mac->sl_phy_config;
sl_phy_cfg->Mod_id = module_id;
sl_phy_cfg->CC_id = 0;
sl_prepare_phy_config(module_id, &sl_phy_cfg->sl_config_req,
freqcfg, sync_source, sl_OffsetDFN, sl_mac->sl_TDD_config);
return 0;
}
//Copies the values of SSB time allocation from ASN format to MAC context
static void sl_mac_config_ssb_time_alloc(uint8_t module_id,
NR_SL_SSB_TimeAllocation_r16_t *sl_SSB_TimeAllocation_r16,
sl_ssb_timealloc_t *ssb_time_alloc)
{
const uint8_t values[] = {1,2,4,8,16,32,64};
ssb_time_alloc->sl_NumSSB_WithinPeriod =
(sl_SSB_TimeAllocation_r16->sl_NumSSB_WithinPeriod_r16 != NULL)
? values[*sl_SSB_TimeAllocation_r16->sl_NumSSB_WithinPeriod_r16] : 0;
ssb_time_alloc->sl_TimeOffsetSSB = (sl_SSB_TimeAllocation_r16->sl_TimeOffsetSSB_r16 != NULL)
? *sl_SSB_TimeAllocation_r16->sl_TimeOffsetSSB_r16 : 0;
ssb_time_alloc->sl_TimeInterval = (sl_SSB_TimeAllocation_r16->sl_TimeInterval_r16 != NULL)
? *sl_SSB_TimeAllocation_r16->sl_TimeInterval_r16 : 0;
}
//This API is called by RRC after it determines that UE needs to transmit SL-SSB
// SLSS id and SL-MIB is given to MAC by RRC
void nr_rrc_mac_transmit_slss_req(module_id_t module_id,
uint8_t *sl_mib_payload,
uint16_t tx_slss_id,
NR_SL_SSB_TimeAllocation_r16_t *ssb_ta)
{
sl_nr_ue_mac_params_t *sl_mac = get_mac_inst(module_id)->SL_MAC_PARAMS;
AssertFatal(sl_mac,"sidelink MAC cannot be NULL");
AssertFatal(tx_slss_id < 672,"SLSS id cannot be >= 672. id:%d", tx_slss_id);
AssertFatal(ssb_ta,"ssb_ta cannot be NULL");
sl_mac->tx_sl_bch.slss_id = tx_slss_id;
sl_mac->tx_sl_bch.status = 1;
memcpy(sl_mac->tx_sl_bch.sl_mib,sl_mib_payload, 4);
sl_mac->tx_sl_bch.num_ssb = 0;
sl_mac->tx_sl_bch.ssb_slot = 0;
sl_mac_config_ssb_time_alloc(module_id,
ssb_ta,
&sl_mac->tx_sl_bch.ssb_time_alloc);
LOG_I(NR_MAC,"[UE%d]SL RRC->MAC: TX SLSS REQ SLSS-id:%d, SL-MIB:%x, numssb:%d, offset:%d, interval:%d\n",
module_id, sl_mac->tx_sl_bch.slss_id,
*((uint32_t *)sl_mib_payload),
sl_mac->tx_sl_bch.ssb_time_alloc.sl_NumSSB_WithinPeriod,
sl_mac->tx_sl_bch.ssb_time_alloc.sl_TimeOffsetSSB,
sl_mac->tx_sl_bch.ssb_time_alloc.sl_TimeInterval);
uint8_t byte0 = 0;
uint8_t byte1 = 0;
sl_nr_bwp_config_t *cfg = &sl_mac->sl_phy_config.sl_config_req.sl_bwp_config;
sl_prepare_psbch_payload(sl_mac->sl_TDD_config, &byte0, &byte1,
cfg->sl_scs,cfg->sl_num_symbols,cfg->sl_start_symbol);
sl_mac->tx_sl_bch.sl_mib[0] = byte0;
sl_mac->tx_sl_bch.sl_mib[1] = byte1 | sl_mac->tx_sl_bch.sl_mib[1];
LOG_I(NR_MAC, "[UE%d]SL RRC->MAC: TX SLSS REQ - TDD CONFIG STUFFED INSIDE - SL-MIB :%x\n",
module_id, *((uint32_t *)sl_mac->tx_sl_bch.sl_mib));
}
//This API is called by RRC after it determines that UE needs to keep
// receiving SL-SSB from the sync ref UE
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)
{
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
AssertFatal(sl_mac,"Sidelink MAC instance cannot be NULL");
AssertFatal(ssb_ta,"ssb_ta cannot be NULL");
AssertFatal(rx_slss_id < 672,"SLSS id cannot be >= 672. id:%d", rx_slss_id);
AssertFatal(sl_mib,"sl_mib cannot be NULL");
sl_nr_phy_config_request_t *sl_config = &sl_mac->sl_phy_config.sl_config_req;
//Update configs if Sync source is not set else nothing to be done
if (sl_config->sl_sync_source.sync_source == SL_SYNC_SOURCE_NONE) {
//Set SYNC source as SYNC REF UE and send the remaining config to PHY
sl_config->config_mask = 0xF;//all configs done.
sl_config->sl_sync_source.sync_source = SL_SYNC_SOURCE_SYNC_REF_UE;
sl_config->sl_sync_source.rx_slss_id = rx_slss_id;
sl_mac->adjust_timing = 1;
sl_mac->rx_sl_bch.status = 1;
sl_mac->rx_sl_bch.slss_id = rx_slss_id;
sl_mac->rx_sl_bch.num_ssb = 0;
sl_mac->rx_sl_bch.ssb_slot = 0;
sl_mac_config_ssb_time_alloc(module_id,
ssb_ta,
&sl_mac->rx_sl_bch.ssb_time_alloc);
LOG_I(NR_MAC,"[UE%d]SL RRC->MAC: RX SLSS REQ SLSS-id:%d, SL-MIB:%x, numssb:%d, offset:%d, interval:%d\n",
module_id, sl_mac->rx_sl_bch.slss_id,
*((uint32_t *)sl_mib),
sl_mac->rx_sl_bch.ssb_time_alloc.sl_NumSSB_WithinPeriod,
sl_mac->rx_sl_bch.ssb_time_alloc.sl_TimeOffsetSSB,
sl_mac->rx_sl_bch.ssb_time_alloc.sl_TimeInterval);
if (sl_mac->sl_TDD_config == NULL)
sl_mac->sl_TDD_config = CALLOC(sizeof(NR_TDD_UL_DL_ConfigCommon_t), 1);
sl_nr_phy_config_request_t *cfg = &sl_mac->sl_phy_config.sl_config_req;
int ret = 1;
ret = sl_decode_sl_TDD_Config(sl_mac->sl_TDD_config,
sl_mib[0], sl_mib[1]&0xF0,
cfg->sl_bwp_config.sl_scs,
cfg->sl_bwp_config.sl_num_symbols,
cfg->sl_bwp_config.sl_start_symbol);
if (ret == 0) {
//sl_tdd_config bytes are all 1's - no TDD config present use all slots for sidelink.
//Spec not clear -- TBD...
sl_config->tdd_table.tdd_period = 7;// set it to frame period
sl_mac->sl_TDD_config->pattern1.nrofUplinkSlots =
NR_NUMBER_OF_SUBFRAMES_PER_FRAME*(1<<cfg->sl_bwp_config.sl_scs);
} else {
if (sl_mac->sl_TDD_config->pattern1.ext1 == NULL)
sl_config->tdd_table.tdd_period = sl_mac->sl_TDD_config->pattern1.dl_UL_TransmissionPeriodicity;
else {
if (sl_mac->sl_TDD_config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL)
sl_config->tdd_table.tdd_period += (1 + *sl_mac->sl_TDD_config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530);
}
}
uint8_t return_tdd = 0;
return_tdd = sl_set_tdd_config_nr_ue(cfg,
cfg->sl_bwp_config.sl_scs,
sl_mac->sl_TDD_config->pattern1.nrofDownlinkSlots,
sl_mac->sl_TDD_config->pattern1.nrofDownlinkSymbols,
sl_mac->sl_TDD_config->pattern1.nrofUplinkSlots,
sl_mac->sl_TDD_config->pattern1.nrofUplinkSymbols);
if (return_tdd !=0)
LOG_E(PHY,"TDD configuration can not be done\n");
LOG_I(MAC, "SIDELINK CONFIGs: tdd config period:%d, mu:%ld, DLslots:%ld,ULslots:%ld Mixedslotsym DL:UL %ld:%ld\n",
sl_config->tdd_table.tdd_period, sl_mac->sl_TDD_config->referenceSubcarrierSpacing,
sl_mac->sl_TDD_config->pattern1.nrofDownlinkSlots, sl_mac->sl_TDD_config->pattern1.nrofUplinkSlots,
sl_mac->sl_TDD_config->pattern1.nrofDownlinkSymbols,sl_mac->sl_TDD_config->pattern1.nrofUplinkSymbols);
DevAssert(mac->if_module != NULL && mac->if_module->sl_phy_config_request != NULL);
mac->if_module->sl_phy_config_request(&sl_mac->sl_phy_config);
}
}
void nr_sl_params_read_conf(module_id_t module_id) {
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
char aprefix[MAX_OPTNAME_SIZE*2 + 8];
sl_csi_info_t *sl_csi_rs_info = (sl_csi_info_t *)malloc(sizeof(sl_csi_info_t));
paramdef_t SL_CRI_RS_INFO[] = SL_CSI_RS_DESC(sl_csi_rs_info);
paramlist_def_t SL_CRI_RS_List = {SL_CONFIG_STRING_SL_CSI_RS_LIST, NULL, 0};
sprintf(aprefix, "%s.[%d]", SL_CONFIG_STRING_SL_PRECONFIGURATION, 0);
config_getlist(&SL_CRI_RS_List, NULL, 0, aprefix);
sprintf(aprefix, "%s.[%i].%s.[%i]", SL_CONFIG_STRING_SL_PRECONFIGURATION, 0, SL_CONFIG_STRING_SL_CSI_RS_LIST, 0);
config_get(SL_CRI_RS_INFO, sizeof(SL_CRI_RS_INFO)/sizeof(paramdef_t), aprefix);
sl_mac->csi_type = sl_csi_rs_info->csi_type;
sl_mac->symb_l0 = sl_csi_rs_info->symb_l0;
sl_mac->power_control_offset = sl_csi_rs_info->power_control_offset;
sl_mac->power_control_offset_ss = sl_csi_rs_info->power_control_offset_ss;
sl_mac->slot_offset = sl_csi_rs_info->slot_offset;
sl_mac->slot_periodicity = sl_csi_rs_info->slot_periodicity;
sl_mac->measurement_bitmap = 0b00011011;
sl_mac->sl_CSI_Acquisition = sl_csi_rs_info->sl_csi_acquisition;
// Based on 38211 Table 7.4.1.5.3-1, for density of 1 and ports 1 & 2 ENUMERATED {noCDM, fd-CDM2}
sl_mac->cdm_type = get_nrUE_params()->nb_antennas_tx == 1 ? 0 : 1;
sl_mac->row = get_nrUE_params()->nb_antennas_tx == 1 ? 2 : 3;
// Only 1 is supported (38211, 8.4.1.5.3) - means CSI-RS transmission in every resource block
sl_mac->freq_density = 1;
sl_mac->freq_domain = 0b000000000001; //bitmap size is dependent upon row size; for row 2 length is 12 bits else 6 bits;
int loc_bw = mac->sl_bwp->sl_BWP_Generic_r16->sl_BWP_r16->locationAndBandwidth;
uint16_t bwp_start = NRRIV2PRBOFFSET(loc_bw, MAX_BWP_SIZE);
// PRB where this CSI resource starts in relation to common resource block #0 (CRB#0) on the common resource block grid.
// Only multiples of 4 are allowed (0, 4, ...)
// INTEGER (0..maxNrofPhysicalResourceBlocks-1)
sl_mac->start_rb = (bwp_start % 4 == 0) ? bwp_start : ((bwp_start >> 2) << 2) + 4;
// Number of PRBs across which this CSI resource spans. The smallest configurable number is the minimum of 24 and the width of the associated BWP
// Only multiples of 4 are allowed.
// INTEGER (24..maxNrofPhysicalResourceBlocksPlus1)
uint16_t max_allowable_num_rbs = (NRRIV2BW(loc_bw, MAX_BWP_SIZE) >> 2) << 2;
sl_mac->nr_of_rbs = min(24, max_allowable_num_rbs);
LOG_D(NR_MAC, "loc_bw %i, start_rb %i, nr_of_rbs %i, max_allowable_num_rbs %i\n", loc_bw, sl_mac->start_rb, sl_mac->nr_of_rbs, max_allowable_num_rbs);
}

View File

@@ -41,13 +41,15 @@
/* IF */
#include "NR_IF_Module.h"
#include "fapi_nr_ue_interface.h"
#include "time_meas.h"
/* MAC */
#include "LAYER2/NR_MAC_COMMON/nr_mac.h"
#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h"
#include "LAYER2/MAC/mac.h"
#include "NR_MAC_COMMON/nr_mac_extern.h"
#include "mac_defs_sl.h"
#include "LAYER2/RLC/rlc.h"
/* RRC */
#include "NR_DRX-Config.h"
#include "NR_SchedulingRequestConfig.h"
@@ -62,6 +64,7 @@
#include "NR_ServingCellConfig.h"
#include "NR_MeasConfig.h"
#include "NR_ServingCellConfigCommonSIB.h"
#include "NR_SL-BWP-ConfigCommon-r16.h"
// ==========
@@ -419,6 +422,84 @@ typedef struct ssb_list_info {
uint8_t nb_tx_ssb;
} ssb_list_info_t;
typedef struct NR_sched_pssch {
int frame;
int slot;
int mu;
/// RB allocation within active uBWP
uint16_t rbSize;
uint16_t rbStart;
/// MCS
uint8_t mcs;
/// TBS-related info
uint16_t R;
uint8_t Qm;
uint32_t tb_size;
/// UL HARQ PID to use for this UE, or -1 for "any new"
int8_t sl_harq_pid;
uint8_t nrOfLayers;
//NR_pusch_dmrs_t dmrs_info;
} NR_sched_pssch_t;
typedef struct {
bool is_waiting;
bool is_active;
uint8_t ndi;
uint8_t round;
uint16_t feedback_slot;
uint16_t feedback_frame;
int8_t sl_harq_pid;
/// sched_pusch keeps information on MCS etc used for the initial transmission
NR_sched_pssch_t sched_pssch;
} NR_UE_sl_harq_t;
//
typedef struct {
/// Sched PSSCH: scheduling decisions, copied into HARQ and cleared every TTI
NR_sched_pssch_t sched_pssch;
//
NR_bler_stats_t sl_bler_stats;
/// per-LC status data
mac_rlc_status_resp_t rlc_status[NR_MAX_NUM_LCID];
//
/// information about every UL HARQ process
NR_UE_sl_harq_t sl_harq_processes[NR_MAX_HARQ_PROCESSES];
/// UL HARQ processes that are free
NR_list_t available_sl_harq;
/// UL HARQ processes that await feedback
NR_list_t feedback_sl_harq;
/// UL HARQ processes that await retransmission
NR_list_t retrans_sl_harq;
// NR_SLSCH
} NR_SL_UE_sched_ctrl_t;
#define MAX_SL_UE_CONNECTIONS 8
#define MAX_SL_CSI_REPORTCONFIG MAX_SL_UE_CONNECTIONS
typedef struct {
uint16_t dest_id;
uid_t uid; // unique ID of this UE
/// scheduling control info
nr_sl_csi_report_t csi_report_template[MAX_SL_CSI_REPORTCONFIG];
NR_SL_UE_sched_ctrl_t UE_sched_ctrl;
} NR_SL_UE_info_t;
typedef struct {
NR_SL_UE_info_t *list[MAX_SL_UE_CONNECTIONS+1];
uid_allocator_t ue_allocator;
} NR_SL_UEs_t;
/*!\brief Top level UE MAC structure */
typedef struct {
NR_UE_L2_STATE_t state;
@@ -455,6 +536,12 @@ typedef struct {
NR_SearchSpace_t *BWP_searchspaces[FAPI_NR_MAX_SS];
NR_SearchSpace_t *search_space_zero;
// sidelink
NR_SL_BWP_ConfigCommon_r16_t *sl_bwp;
NR_SL_ResourcePool_r16_t *sl_rx_res_pool;
NR_SL_ResourcePool_r16_t *sl_tx_res_pool;
nr_sl_csi_report_t *sl_csi_report;
bool phy_config_request_sent;
frame_type_t frame_type;
@@ -517,6 +604,7 @@ typedef struct {
NR_SSB_meas_t ssb_measurements;
dci_pdu_rel15_t def_dci_pdu_rel15[NR_MAX_SLOTS_PER_FRAME][8];
sl_nr_tx_config_psfch_pdu_t *sl_tx_config_psfch_pdu[NR_MAX_HARQ_PROCESSES];
// Defined for abstracted mode
nr_downlink_indication_t dl_info;
@@ -526,6 +614,19 @@ typedef struct {
pthread_mutex_t mutex_dl_info;
//SIDELINK MAC PARAMETERS
sl_nr_ue_mac_params_t *SL_MAC_PARAMS;
// SIDELINK Scheduling fields
NR_SL_UEs_t sl_info;
// current SCI pdu build from SCI1 and SCI2
nr_sci_pdu_t sci_pdu_rx;
nr_sci_pdu_t sci1_pdu;
nr_sci_pdu_t sci2_pdu;
uint8_t slsch_payload[16384];
time_stats_t rlc_data_req;
int src_id;
} NR_UE_MAC_INST_t;
/*@}*/

View File

@@ -0,0 +1,195 @@
/*
* 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
*/
#ifndef __MAC_DEFS_SL_H__
#define __MAC_DEFS_SL_H__
#include "sidelink_nr_ue_interface.h"
#include "NR_SL-ResourcePool-r16.h"
#include "NR_TDD-UL-DL-ConfigCommon.h"
#include "NR_MAC_COMMON/nr_mac.h"
#include "NR_UE_PHY_INTERFACE/NR_IF_Module.h"
#include "nr_ue_sci.h"
#define SL_NR_MAC_NUM_RX_RESOURCE_POOLS 1
#define SL_NR_MAC_NUM_TX_RESOURCE_POOLS 1
#define SL_NUM_BYTES_TIMERESOURCEBITMAP 20
//every 16 frames, SSB is repeated.
#define SL_NR_SSB_REPETITION_IN_FRAMES 16
#define SL_FRAME_NUMBER_CYCLE 1024
// Size of Fixed fields prio (3), sci_2ndstage(2),
// betaoffsetindicator(2), num dmrs ports (1), mcs (5bits)
#define SL_SCI_FORMAT_1A_LEN_IN_BITS_FIXED_FIELDS 13
#define sci_field_t dci_field_t
typedef struct sidelink_sci_format_1a_fields {
// Priority of this transmission
uint8_t priority; //3 bits
//Indicates the format to be used in 2nd stage i.e SCI format 2 sent on PSSCH
//00 - SCI FORMAT 2A, 01 - SCI FORMAT 2B, 10, 11 - Reserved
//Spec 38.212 Table 8.3.1.1-1
uint8_t sci_format_2nd_stage; //2 bits
//Num modulated symbols for stage 2 SCI - TBD:
// Spec 38.212 Table 8.3.1.1-2
uint8_t beta_offset_indicator; //2 bits
//determine the number of layers for data on PSSCH
// Spec 38.212 Table 8.3.1.1-3
uint8_t num_dmrs_ports; //1 bit
//Modulation and coding scheme to be used for data on PSSCH
uint8_t mcs; //5 bits
//Identifies the frequence resource (subchannels) to be used for PSSCH/PSCCH
//sl-MaxNumPerReserve is 2 - ceil(log2(N_subch*(N_subch+1)/2)) bits
//sl-MaxNumPerReserve is 3 - ceil(log2(N_subch*(N_subch+1)(2*N_subch+1)/6)) bits
sci_field_t frequency_resource_assignment; //variable
//Identifies the Time resource (slots) to be used for PSSCH/PSCCH
//sl-MaxNumPerReserve is 2 - 5 bits
//sl-MaxNumPerReserve is 3 - 9 bits
sci_field_t time_resource_assignment; //variable
//TBD:
//sl-MultiReserveResource is not configured - 0 bits
//sl-MultiReserveResource is configured - ceil(log2(number of entries in sl-ResourceReservePeriodList)) bits
sci_field_t resource_reservation_period; //variable
//Identifies the DMRS Pattern to be used on PSSCH
//ceil(log2(number of dmrs patterns in sl-PSSCH-DMRS-TimePatternList)) bits
sci_field_t dmrs_pattern; //variable
//Identifies the TABLE to be used to determine MCS on PSSCH
//1 table configured in sl-Additional-MCS-Table - 1 bit
//2 tables configured in sl-Additional-MCS-Table - 2 bits
//Not configured- 0 bits
sci_field_t additional_mcs_table_indicator; //variable
//Identifies the number of symbols for PSFCH
//sl-PSFCH-Period Not configured- 0 bits
//if sl-PSFCH-Period configured and value 2 or 4 - 1 bit
sci_field_t psfch_overhead_indication; //variable
//number of bits determined by sl-NumReservedbits
//Value encoded is 0
sci_field_t reserved_bits;
} sidelink_sci_format_1a_fields_t;
typedef struct SL_ResourcePool_params {
//This holds the structure from RRC
NR_SL_ResourcePool_r16_t *respool;
//NUM Subchannels in this resource pool
uint16_t num_subch;
//SCI-1A length is the same for this resource pool.
uint16_t sci_1a_len;
//SCI-1A configuration according to RESPOOL configured.
sidelink_sci_format_1a_fields_t sci_1a;
} SL_ResourcePool_params_t;
typedef struct sl_ssb_timealloc {
uint32_t sl_NumSSB_WithinPeriod;
uint32_t sl_TimeOffsetSSB;
uint32_t sl_TimeInterval;
} sl_ssb_timealloc_t;
typedef struct sl_bch_params {
//configured from RRC
//Parameters used to determine PSBCH slot
sl_ssb_timealloc_t ssb_time_alloc;
uint16_t slss_id;
bool status;
uint8_t sl_mib[4];
//Parameters incremented by MAC PSBCH scheduler
//after every SSB txn/reception
uint16_t num_ssb;
uint16_t ssb_slot;
} sl_bch_params_t;
typedef struct sl_nr_ue_mac_params {
//Holds the RX resource pool from RRC and its related parameters
SL_ResourcePool_params_t *sl_RxPool[SL_NR_MAC_NUM_RX_RESOURCE_POOLS];
//Holds the TX resource pool from RRC and its related parameters
SL_ResourcePool_params_t *sl_TxPool[SL_NR_MAC_NUM_TX_RESOURCE_POOLS];
//Holds either the TDD config from RRC
//or TDD config decoded from SL-MIB
NR_TDD_UL_DL_ConfigCommon_t *sl_TDD_config;
// CSI params configured locally
uint8_t symb_l0;
uint8_t csi_type;
uint8_t power_control_offset;
uint8_t power_control_offset_ss;
uint8_t slot_offset;
uint8_t slot_periodicity;
uint8_t freq_density;
uint8_t subcarrier_spacing;
uint8_t cyclic_prefix;
uint16_t start_rb;
uint16_t nr_of_rbs;
uint8_t row;
uint16_t freq_domain;
uint8_t cdm_type;
uint16_t scramb_id;
uint8_t measurement_bitmap;
//Configured from RRC
uint32_t sl_MaxNumConsecutiveDTX;
uint32_t sl_SSB_PriorityNR;
uint8_t sl_CSI_Acquisition;
//MAC prepares this and sends it to PHY
nr_sl_phy_config_t sl_phy_config;
//Holds Broadcast params incase UE sends Sidelink SSB
sl_bch_params_t tx_sl_bch;
//Holds Broadcast params incase UE receives SL-SSB
sl_bch_params_t rx_sl_bch;
//SSB RSRP in dBm
int16_t ssb_rsrp_dBm;
//Bitmap indicating which slots belong to sidelink
//Right now supports 30Khz and 15Khz
uint32_t sl_slot_bitmap;
//adjust timing after new timing from sync is acquired.
uint8_t adjust_timing;
//Sidelink slots per frame
uint16_t N_SL_SLOTS_perframe;
uint16_t decoded_DFN;
uint16_t decoded_slot;
} sl_nr_ue_mac_params_t;
#endif

View File

@@ -33,12 +33,20 @@
#ifndef __LAYER2_MAC_UE_PROTO_H__
#define __LAYER2_MAC_UE_PROTO_H__
#include <stdbool.h>
#include "mac_defs.h"
#include "RRC/NR_UE/rrc_defs.h"
#define NR_DL_MAX_DAI (4) /* TS 38.213 table 9.1.3-1 Value of counter DAI for DCI format 1_0 and 1_1 */
#define NR_DL_MAX_NB_CW (2) /* number of downlink code word */
// 38.213 Table 16.3-1 set of cyclic shift pairs
static const int16_t table_16_3_1[4][6] = {
{0},
{0, 3},
{0, 2, 4},
{0, 1, 2, 3, 4, 5}
};
/**\brief initialize the field in nr_mac instance
\param module_id module id */
void nr_ue_init_mac(module_id_t module_idP);
@@ -113,6 +121,8 @@ void nr_ue_dl_scheduler(nr_downlink_indication_t *dl_info);
@param fapi_nr_dl_config_request_t* pointer to dl_config,
@param fapi_nr_ul_config_request_t* pointer to ul_config,
@param fapi_nr_tx_request_t* pointer to tx_request;
@param sl_nr_rx_config_request_t* pointer to sl_rx_config,
@param sl_nr_tx_config_request_t* pointer to sl_tx_config,
@param module_id_t mod_id module ID
@param int cc_id CC ID
@param frame_t frame frame number
@@ -122,6 +132,8 @@ void fill_scheduled_response(nr_scheduled_response_t *scheduled_response,
fapi_nr_dl_config_request_t *dl_config,
fapi_nr_ul_config_request_t *ul_config,
fapi_nr_tx_request_t *tx_request,
sl_nr_rx_config_request_t *sl_rx_config,
sl_nr_tx_config_request_t *sl_tx_config,
module_id_t mod_id,
int cc_id,
frame_t frame,
@@ -430,5 +442,141 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
RAR_grant_t *rar_grant,
uint16_t rnti,
const nr_dci_format_t *dci_format);
int nr_rrc_mac_config_req_sl_preconfig(module_id_t module_id,
NR_SL_PreconfigurationNR_r16_t *sl_preconfiguration,
uint8_t sync_source,
int srcid);
uint8_t count_PSFCH_PRBs_bits(uint8_t* buf, size_t size);
void nr_rrc_mac_transmit_slss_req(module_id_t module_id,
uint8_t *sl_mib_payload,
uint16_t tx_slss_id,
NR_SL_SSB_TimeAllocation_r16_t *ssb_ta);
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);
void nr_sl_params_read_conf(module_id_t module_id);
void sl_prepare_psbch_payload(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config,
uint8_t *bits_0_to_7, uint8_t *bits_8_to_11,
uint8_t mu, uint8_t L, uint8_t Y);
uint8_t sl_decode_sl_TDD_Config(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config,
uint8_t bits_0_to_7, uint8_t bits_8_to_11,
uint8_t mu, uint8_t L, uint8_t Y);
uint8_t sl_determine_sci_1a_len(uint16_t *num_subchannels,
NR_SL_ResourcePool_r16_t *rpool,
sidelink_sci_format_1a_fields_t *sci_1a);
void nr_ue_process_mac_sl_pdu(int module_idP,
sl_nr_rx_indication_t *rx_ind,
int pdu_id);
/** \brief This function checks nr UE slot for Sidelink direction : Sidelink
* @param cfg : Sidelink config request
* @param nr_frame : frame number
* @param nr_slot : slot number
* @param frame duplex type : Frame type
@returns int : 0 or Sidelink slot type */
int sl_nr_ue_slot_select(sl_nr_phy_config_request_t *cfg,
int nr_frame, int nr_slot,
uint8_t frame_duplex_type);
int nr_ue_process_sci1_indication_pdu(NR_UE_MAC_INST_t *mac,module_id_t mod_id,frame_t frame, int slot, sl_nr_sci_indication_pdu_t *sci,void *phy_data);
void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind);
void 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 channel_t channel,
uint8_t* pduP,
const sdu_size_t pdu_len,
const uint16_t rx_slss_id);
bool nr_schedule_slsch(NR_UE_MAC_INST_t *mac, int frameP, int slotP, nr_sci_pdu_t *sci_pdu,
nr_sci_pdu_t *sci2_pdu,
uint8_t *slsch_pdu,
nr_sci_format_t format2,
uint16_t *slsch_pdu_length);
uint8_t nr_ue_sl_psbch_scheduler(nr_sidelink_indication_t *sl_ind,
sl_nr_ue_mac_params_t *sl_mac_params,
sl_nr_rx_config_request_t *rx_config,
sl_nr_tx_config_request_t *tx_config,
uint8_t *config_type);
void nr_ue_sl_pscch_rx_scheduler(nr_sidelink_indication_t *sl_ind,
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
const NR_SL_ResourcePool_r16_t *sl_res_pool,
sl_nr_rx_config_request_t *rx_config,
uint8_t *config_type);
void nr_ue_sl_csi_rs_scheduler(NR_UE_MAC_INST_t *mac,
uint8_t scs,
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
sl_nr_tx_config_request_t *tx_config,
sl_nr_rx_config_request_t *rx_config,
uint8_t *config_type);
void fill_csi_rs_pdu(sl_nr_ue_mac_params_t *sl_mac,
sl_nr_tti_csi_rs_pdu_t *csi_rs_pdu,
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
uint8_t scs);
void nr_ue_sl_psfch_scheduler(NR_UE_MAC_INST_t *mac,
long psfch_period,
nr_sidelink_indication_t *sl_ind,
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
const NR_SL_ResourcePool_r16_t *sl_res_pool,
sl_nr_tx_config_request_t *tx_config,
uint8_t *config_type,
bool is_csi_rs_sent);
void config_pscch_pdu_rx(sl_nr_rx_config_pscch_pdu_t *nr_sl_pscch_pdu,
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
const NR_SL_ResourcePool_r16_t *sl_res_pool);
int config_pssch_sci_pdu_rx(sl_nr_rx_config_pssch_sci_pdu_t *nr_sl_pssch_sci_pdu,
nr_sci_format_t sci2_format,
nr_sci_pdu_t *sci_pdu,
uint32_t pscch_Nid,
int pscch_subchannel_index,
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
const NR_SL_ResourcePool_r16_t *sl_res_pool);
int nr_ue_process_sci2_indication_pdu(NR_UE_MAC_INST_t *mac,
module_id_t mod_id,
int cc_id,
frame_t frame,
int slot,
sl_nr_sci_indication_pdu_t *sci,
void *phy_data);
void extract_pssch_sci_pdu(uint64_t *sci2_payload,
int len,
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
const NR_SL_ResourcePool_r16_t *sl_res_pool,
nr_sci_pdu_t *sci_pdu);
void fill_pssch_pscch_pdu(sl_nr_ue_mac_params_t *sl_mac_params,
sl_nr_tx_config_pscch_pssch_pdu_t *nr_sl_pssch_pscch_pdu,
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
const NR_SL_ResourcePool_r16_t *sl_res_pool,
nr_sci_pdu_t *sci_pdu,
nr_sci_pdu_t *sci2_pdu,
uint16_t slsch_pdu_length,
const nr_sci_format_t format1,
const nr_sci_format_t format2);
void fill_psfch_pdu(sl_nr_tx_config_psfch_pdu_t *mac_psfch_pdu,
sl_nr_tx_config_request_t *tx_config,
int num_psfch_symbols);
#endif
/** @}*/

View File

@@ -58,7 +58,7 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) {
int scs = get_softmodem_params()->sa ?
get_softmodem_params()->numerology :
rrc_inst ?
rrc_inst && rrc_inst->scell_group_config ?
*rrc_inst->scell_group_config->spCellConfig->reconfigurationWithSync->spCellConfigCommon->ssbSubcarrierSpacing :
- 1;
if (scs > -1)
@@ -94,6 +94,7 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) {
}
}
reset_meas(&nr_ue_mac_inst->rlc_data_req);
return (nr_ue_mac_inst);
}

View File

@@ -0,0 +1,109 @@
/*
* 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 nr_slsch_scheduler.c
* \brief Routines for UE SLSCH scheduling
* \author R. Knopp
* \date Aug. 2023
* \version 0.1
* \company EURECOM
* \email raymond.knopp@eurecom.fr
*/
#include <stdio.h>
#include <math.h>
#include <stdbool.h>
#include <common/utils/nr/nr_common.h>
#include "NR_MAC_COMMON/nr_mac.h"
#include "NR_MAC_COMMON/nr_mac_common.h"
#include "NR_MAC_UE/mac_proto.h"
#include "NR_MAC_UE/mac_extern.h"
#include "NR_MAC_UE/nr_ue_sci.h"
#include <executables/nr-uesoftmodem.h>
bool nr_schedule_slsch(NR_UE_MAC_INST_t *mac, int frameP,int slotP, nr_sci_pdu_t *sci_pdu,nr_sci_pdu_t *sci2_pdu,uint8_t *slsch_pdu,nr_sci_format_t format2, uint16_t *slsch_pdu_length_max) {
mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(0, mac->src_id, 0, frameP, slotP, ENB_FLAG_NO, MBMS_FLAG_NO, 4, 0, 0);
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
uint8_t mu = sl_mac->sl_phy_config.sl_config_req.sl_bwp_config.sl_scs;
uint8_t slots_per_frame = nr_slots_per_frame[mu];
uint8_t psfch_period = 0;
if (mac->sl_tx_res_pool->sl_PSFCH_Config_r16 && mac->sl_tx_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_Period_r16)
psfch_period = *mac->sl_tx_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_Period_r16;
*slsch_pdu_length_max = 0;
bool csi_acq = !mac->SL_MAC_PARAMS->sl_CSI_Acquisition;
bool csi_req_slot = !((slots_per_frame * frameP + slotP - sl_mac->slot_offset) % sl_mac->slot_periodicity);
if (rlc_status.bytes_in_buffer > 0 || mac->sci_pdu_rx.harq_feedback || (csi_acq && csi_req_slot)) {
LOG_I(NR_MAC, "%d.%d buffer %d\n",frameP, slotP, rlc_status.bytes_in_buffer );
// Fill SCI1A
sci_pdu->priority = 0;
sci_pdu->frequency_resource_assignment.val = 0;
sci_pdu->time_resource_assignment.val = 0;
sci_pdu->resource_reservation_period.val = 0;
sci_pdu->dmrs_pattern.val = 0;
sci_pdu->second_stage_sci_format = 0;
sci_pdu->number_of_dmrs_port = 0;
sci_pdu->mcs = 9;
sci_pdu->additional_mcs.val = 0;
sci_pdu->psfch_overhead.val = 0;
sci_pdu->reserved.val = 0;
sci_pdu->conflict_information_receiver.val = 0;
sci_pdu->beta_offset_indicator = 0;
// Fill SCI2A
sci2_pdu->harq_pid = 0;
sci2_pdu->ndi = (1 - sci2_pdu->ndi) & 1;
sci2_pdu->rv_index = 0;
sci2_pdu->source_id = get_softmodem_params()->node_number;
sci2_pdu->dest_id = 0xabcd;
sci2_pdu->harq_feedback = psfch_period ? 1 : 0;
sci2_pdu->cast_type = 1;
if (format2 == NR_SL_SCI_FORMAT_2C || format2 == NR_SL_SCI_FORMAT_2A) {
sci2_pdu->csi_req = (csi_acq && csi_req_slot) ? 1 : 0;
LOG_D(NR_MAC, "Setting sci2_pdu->csi_req %d (%d.%d)\n", sci2_pdu->csi_req, frameP, slotP);
}
if (format2 == NR_SL_SCI_FORMAT_2B)
sci2_pdu->zone_id = 0;
// Fill in for R17: communication_range
sci2_pdu->communication_range.val = 0;
if (format2 == NR_SL_SCI_FORMAT_2C) {
sci2_pdu->providing_req_ind = 0;
// Fill in for R17 : resource combinations
sci2_pdu->resource_combinations.val = 0;
sci2_pdu->first_resource_location = 0;
// Fill in for R17 : reference_slot_location
sci2_pdu->reference_slot_location.val = 0;
sci2_pdu->resource_set_type = 0;
// Fill in for R17 : lowest_subchannel_indices
sci2_pdu->lowest_subchannel_indices.val = 0;
}
// Set SLSCH
*slsch_pdu_length_max = rlc_status.bytes_in_buffer;
return true;
}
return false;
}

View File

@@ -0,0 +1,832 @@
/*
* 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 "mac_defs.h"
#include "mac_proto.h"
#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h"
#include "executables/softmodem-common.h"
#define SL_DEBUG
static const int sequence_cyclic_shift_harq_ack_or_ack_or_only_nack[2]
/* Sequence cyclic shift */ = { 0, 6 };
typedef struct prbs_set {
uint16_t **start_prb;
uint16_t **end_prb;
} prbs_set_t;
typedef struct psfch_params {
uint16_t m0;
prbs_set_t *prbs_sets;
} psfch_params_t;
void print_prb_set_allocation(psfch_params_t *psfch_params, uint8_t psfch_period, uint8_t num_subchannels) {
LOG_D(NR_PHY, "PSSCH Slot mod PSFCH period | Subchannel | Start PRB | End PRB\n");
for (int i = 0; i < psfch_period; i++) {
for (int j = 0; j < num_subchannels; j++) {
LOG_D(NR_PHY, "\t\t %d \t\t|\t%d\t|\t%d\t| \t %d\n", i, j, psfch_params->prbs_sets->start_prb[i][j], psfch_params->prbs_sets->end_prb[i][j]);
}
}
}
uint8_t sl_process_TDD_UL_DL_config_patterns(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config,
uint8_t mu,
double *slot_period_P,
uint8_t *w)
{
uint8_t return_value = 255;
*w = 0;
int pattern1_dlul_period = TDD_UL_DL_Config->pattern1.dl_UL_TransmissionPeriodicity;
#ifdef SL_DEBUG
printf("INPUT VALUES: function: %s\n", __func__);
printf("pattern1 periodicity:%d\n", pattern1_dlul_period);
if (TDD_UL_DL_Config->pattern1.ext1 != NULL && TDD_UL_DL_Config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL )
printf("pattern1 periodicity_v1530:%ld\n", *TDD_UL_DL_Config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530);
if (TDD_UL_DL_Config->pattern2 != NULL) {
printf("mu:%d, pattern2 periodicity:%d\n", mu, pattern1_dlul_period);
if (TDD_UL_DL_Config->pattern2->ext1 != NULL && TDD_UL_DL_Config->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL )
printf("pattern2 periodicity_v1530:%ld\n", *TDD_UL_DL_Config->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530);
}
#endif
return_value = pattern1_dlul_period;
switch (pattern1_dlul_period) {
case 0:
*slot_period_P = 0.5;
break;
case 1:
*slot_period_P = 0.625;
break;
case 2:
*slot_period_P = 1.0;
break;
case 3:
*slot_period_P = 1.25;
break;
case 4:
*slot_period_P = 2.0;
break;
case 5:
*slot_period_P = 2.5;
break;
case 6:
*slot_period_P = 5.0;
return_value = 7;
break;
case 7:
*slot_period_P = 10.0;
return_value = 8;
break;
default:
AssertFatal(1==0,"Incorrect value of dl_UL_TransmissionPeriodicity\n");
break;
}
if (TDD_UL_DL_Config->pattern1.ext1 != NULL &&
TDD_UL_DL_Config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL ) {
if (*TDD_UL_DL_Config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 == 1) {
*slot_period_P = 4.0;
return_value = 6;
} else {
*slot_period_P = 3.0;
return_value = 255;
}
}
if (TDD_UL_DL_Config->pattern2 != NULL) {
return_value = 255;
*w = 1;
if ((*slot_period_P == 4.0 ) && (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 1)) {
return_value = 13;
*w = (mu == 3)? 2: 1;
} else if ((*slot_period_P == 3.0 ) && (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 4)) {
return_value = 12;
*w = (mu == 3)? 2: 1;
} else if ((*slot_period_P == 3.0 ) && (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 2)) {
return_value = 8;
*w = (mu == 3)? 2: 1;
} else {
switch (pattern1_dlul_period) {
case 7:
if (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 7) {
return_value = 15;
*w = 1<<mu;
}
break;
case 6:
if (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 6) {
return_value = 14;
*w = (mu==0)?1:1<<(mu-1);
}
break;
case 5:
if (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 5) {
return_value = 11;
*w = (mu == 3)? 2: 1;
}
break;
case 4:
if (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 0) {
return_value = 5;
}
else if (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 4) {
return_value = 7;
}
else if (TDD_UL_DL_Config->pattern2->ext1 != NULL && *TDD_UL_DL_Config->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530 == 0) {
return_value = 10;
*w = (mu == 3)? 2: 1;
}
break;
case 3:
if (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 3) {
return_value = 4;
}
break;
case 2:
if (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 2) {
return_value = 2;
}
else if (TDD_UL_DL_Config->pattern2->ext1 != NULL && *TDD_UL_DL_Config->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530 == 0) {
return_value = 6;
*w = (mu == 3)? 2: 1;
}
else if (TDD_UL_DL_Config->pattern2->ext1 != NULL && *TDD_UL_DL_Config->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530 == 1) {
return_value = 9;
*w = (mu == 3)? 2: 1;
}
break;
case 1:
if (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 1) {
return_value = 1;
}
break;
case 0:
if (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 0) {
return_value = 0;
}
else if (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 4) {
return_value = 3;
}
break;
default:
AssertFatal(1==0,"Incorrect value of dl_UL_TransmissionPeriodicity");
}
}
}
#ifdef SL_DEBUG
printf("OUTPUT VALUES: function %s\n",__func__);
printf("return_value:%d, *w:%d, slot_period_P:%f\n", return_value, *w, *slot_period_P);
#endif
return return_value;
}
/*
This procedures prepares the psbch payload of tdd configuration according
to section 16.1 in 38.213
*/
void sl_prepare_psbch_payload(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config,
uint8_t *bits_0_to_7, uint8_t *bits_8_to_11,
uint8_t mu, uint8_t L, uint8_t Y)
{
uint8_t w = 0, a1_to_a4 = 0;
uint8_t mu_ref = 0, diff = 0;
uint8_t u_slots = 0, u_sym = 0, I1 = 0;
uint8_t u_sl_slots = 0, u_sl_slots_2 = 0;
double slot_period_P = 0.0;
*bits_0_to_7 = 0xFF; // If TDD_UL_DL_Config = NULL all 12 bits are set to 1
*bits_8_to_11 = 0xF0;
if (TDD_UL_DL_Config != NULL) {
mu_ref = TDD_UL_DL_Config->referenceSubcarrierSpacing;
diff = 1 << (mu-mu_ref);
u_slots = TDD_UL_DL_Config->pattern1.nrofUplinkSlots;
u_sym = TDD_UL_DL_Config->pattern1.nrofUplinkSymbols;
I1 = ((u_sym * diff) % L >= (L-Y)) ? 1 : 0;
#ifdef SL_DEBUG
printf("INPUT VALUES: function %s\n", __func__);
printf("numerology:%d, number of symbols:%d, sl-startSymbol:%d\n", mu, L, Y);
printf("mu_ref:%d, u_slots:%d, u_sym:%d\n", mu_ref, u_slots, u_sym);
if (TDD_UL_DL_Config->pattern2 != NULL)
printf("u_slots_2:%ld, u_sym_2:%ld\n", TDD_UL_DL_Config->pattern2->nrofUplinkSlots,
TDD_UL_DL_Config->pattern2->nrofUplinkSymbols);
#endif
u_sl_slots = (u_slots * diff) + floor((u_sym*diff)/L) + I1;
a1_to_a4 = sl_process_TDD_UL_DL_config_patterns(TDD_UL_DL_Config, mu, &slot_period_P, &w);
AssertFatal(a1_to_a4 != 255,"Incorrect return value, wrong configuration.\n");
#ifdef SL_DEBUG
printf("I1:%d, a1_to_a2:%d, u_sl_slots:%d\n", I1, a1_to_a4, u_sl_slots);
#endif
if (TDD_UL_DL_Config->pattern2 != NULL) {
uint8_t u_slots_2 = TDD_UL_DL_Config->pattern2->nrofUplinkSlots;
uint8_t u_sym_2 = TDD_UL_DL_Config->pattern2->nrofUplinkSymbols;
uint8_t I2 = ((u_sym_2 * diff) % L >= (L-Y)) ? 1 : 0;
uint16_t val = floor(((u_slots_2 * diff) + floor((u_sym_2*diff)/L) + I2)/w);
u_sl_slots_2 = val * ceil((slot_period_P*(1<<mu)+1)/w) + floor(u_sl_slots/w);
*bits_0_to_7 = 0x80 | (a1_to_a4 << 3) | ((u_sl_slots_2 & 0x70) >> 4);
*bits_8_to_11 = (u_sl_slots_2 & 0x0F) << 4;
#ifdef SL_DEBUG
printf("I2:%d, val:%d, u_sl_slots_2:%d\n", I2, val, u_sl_slots_2);
#endif
} else {
*bits_0_to_7 = 0x00 | (a1_to_a4 << 3) | ((u_sl_slots & 0x70) >> 4);
*bits_8_to_11 = (u_sl_slots & 0x0F) << 4;
}
}
#ifdef SL_DEBUG
printf("OUTPUT VALUES: function %s\n", __func__);
printf("12 bits payload buf[0]:%x, buf[1]:%x\n", *bits_0_to_7, *bits_8_to_11);
#endif
}
/*
This procedures prepares the psbch payload of tdd configuration according
to section 16.1 in 38.213
*/
uint8_t sl_decode_sl_TDD_Config(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config,
uint8_t bits_0_to_7, uint8_t bits_8_to_11,
uint8_t mu, uint8_t L, uint8_t Y)
{
AssertFatal(TDD_UL_DL_Config, "TDD_UL_DL_Config cannot be null");
uint16_t num_SL_slots = 0, mixed_slot_numsym = 0;
TDD_UL_DL_Config->pattern1.nrofDownlinkSlots = 0;
TDD_UL_DL_Config->pattern1.nrofDownlinkSymbols = 0;
TDD_UL_DL_Config->pattern1.nrofUplinkSlots = 0;
TDD_UL_DL_Config->pattern1.nrofUplinkSymbols = 0;
TDD_UL_DL_Config->referenceSubcarrierSpacing = mu;
TDD_UL_DL_Config->pattern1.ext1 = NULL;
LOG_D(MAC, "bits_0_to_7:%x, bits_8_to_11:%x, mu:%d, L:%d, Y:%d\n",
bits_0_to_7, bits_8_to_11,mu, L, Y);
//If all bits are 1 - indicates that no TDD config was present.
if ((bits_0_to_7 == 0xFF) && ((bits_8_to_11 & 0xF0) == 0xF0)) {
//If no TDD config present - use all slots for Sidelink.
//Spec not clear -- TBD....
return 0;
}
//Bit A0 if 1 indicates pattern2 as present.
if (bits_0_to_7 & 0x80) {
//Pattern1 and Pattern2 Present.
TDD_UL_DL_Config->pattern2 = malloc16_clear(sizeof(*TDD_UL_DL_Config->pattern2));
AssertFatal(1==0,"Decoding Pattern2 - NOT YET IMPLEMENTED\n");
} else {
//Only Pattern1 Present. bits a1..a4 identify the periodicity.
uint8_t val = (bits_0_to_7 & 0x78) >> 3;
if (val >= 7)
TDD_UL_DL_Config->pattern1.dl_UL_TransmissionPeriodicity = val-1;
if (val == 6) {
if (TDD_UL_DL_Config->pattern1.ext1 == NULL)
TDD_UL_DL_Config->pattern1.ext1 = calloc(1, sizeof(*TDD_UL_DL_Config->pattern1.ext1));
if (TDD_UL_DL_Config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 == NULL)
TDD_UL_DL_Config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 = calloc(1, sizeof(long));
*TDD_UL_DL_Config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 = 1;
}
//a5,a6..a11 bits from the 7th to 1st LSB of num SL slots
num_SL_slots = ((bits_0_to_7 & 0x07) << 4 ) | ((bits_8_to_11 & 0xF0) >> 4);
TDD_UL_DL_Config->pattern1.nrofUplinkSlots = num_SL_slots;
TDD_UL_DL_Config->pattern1.nrofUplinkSymbols = mixed_slot_numsym;
LOG_D(MAC, "SIDELINK: EXtracted TDD config from 12 bits - Sidelink Slots:%ld, Mixed_slot_symbols:%ld,dl_UL_TransmissionPeriodicity:%ld\n",
TDD_UL_DL_Config->pattern1.nrofUplinkSlots, TDD_UL_DL_Config->pattern1.nrofUplinkSymbols,
TDD_UL_DL_Config->pattern1.dl_UL_TransmissionPeriodicity);
}
return 1;
}
/*Function used to prepare Sidelink MIB*/
uint32_t sl_prepare_MIB(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config,
uint8_t incoverage, uint8_t mu,
uint8_t start_symbol, uint8_t L) {
uint8_t sl_mib_payload[4] = {0,0,0,0};
//int mu = UE->sl_frame_params.numerology_index, start_symbol = UE->start_symbol;
uint8_t byte0, byte1;
//int L = (UE->sl_frame_params.Ncp == 0) ? 14 : 12;
uint32_t sl_mib=0;
sl_prepare_psbch_payload(TDD_UL_DL_Config, &byte0, &byte1, mu, L, start_symbol);
sl_mib_payload[0] = byte0;
sl_mib_payload[1] = byte1;
AssertFatal(incoverage <= 1, "Invalid value for incoverage paramter for SL-MIB. Accepted values 0 or 1\n");
sl_mib_payload[1] |= (incoverage << 3);
sl_mib = sl_mib_payload[1]<<8 | sl_mib_payload[0];
#ifdef SL_DEBUG
printf("SIDELINK PSBCH SIM: NUM SYMBOLS:%d, mu:%d, start_symbol:%d incoverage:%d \n",
L, mu, start_symbol, incoverage);
printf("SIDELINK PSBCH PAYLOAD: psbch_a:%x, sl_mib_payload:%x %x %x %x\n",
sl_mib, sl_mib_payload[0],sl_mib_payload[1], sl_mib_payload[2], sl_mib_payload[3]);
#endif
return sl_mib;
}
uint16_t sl_get_subchannel_size(NR_SL_ResourcePool_r16_t *rpool)
{
uint16_t subch_size = 0;
const uint8_t subchsizes[8] = {10, 12, 15, 20, 25, 50, 75, 100};
subch_size = (rpool->sl_SubchannelSize_r16)
? subchsizes[*rpool->sl_SubchannelSize_r16] : 0;
AssertFatal(subch_size,"Subch Size cannot be 0.Resource Pool Configuration Error\n");
return subch_size;
}
uint16_t sl_get_num_subch(NR_SL_ResourcePool_r16_t *rpool)
{
uint16_t num_subch = 0;
uint16_t subch_size = sl_get_subchannel_size(rpool);
uint16_t num_rbs = (rpool->sl_RB_Number_r16) ? *rpool->sl_RB_Number_r16 : 0;
AssertFatal(num_rbs,"NumRbs in rpool cannot be 0.Resource Pool Configuration Error\n");
num_subch = num_rbs/subch_size;
LOG_I(NR_MAC, "Subch_size:%d, numRBS:%d, num_subch:%d\n",
subch_size,num_rbs,num_subch);
return (num_subch);
}
//This function determines SCI 1A Len in bits based on the configuration in the resource pool.
uint8_t sl_determine_sci_1a_len(uint16_t *num_subchannels,
NR_SL_ResourcePool_r16_t *rpool,
sidelink_sci_format_1a_fields_t *sci_1a)
{
uint8_t num_bits = 0;
//Size of Fixed fields prio (3), sci_2ndstage(2),
//betaoffsetindicator(2), num dmrs ports (1), mcs (5bits)
uint8_t sci_1a_len = SL_SCI_FORMAT_1A_LEN_IN_BITS_FIXED_FIELDS;
*num_subchannels = sl_get_num_subch(rpool);
uint16_t n_subch = *num_subchannels;
LOG_D(NR_MAC,"Determine SCI-1A len - Num Subch:%d, sci 1A len fixed fields:%d\n",
*num_subchannels, sci_1a_len);
NR_SL_UE_SelectedConfigRP_r16_t *selectedconfigRP = rpool->sl_UE_SelectedConfigRP_r16;
const uint8_t maxnum_values[] = {2,3};
uint8_t sl_MaxNumPerReserve = (selectedconfigRP &&
selectedconfigRP->sl_MaxNumPerReserve_r16)
? maxnum_values[*selectedconfigRP->sl_MaxNumPerReserve_r16]
: 0;
//Determine bits for Freq and Time Resource assignment
if (sl_MaxNumPerReserve == 3) {
num_bits = ceil(log2(n_subch * (n_subch + 1) * (2*n_subch + 1)/6));
sci_1a_len += num_bits;
sci_1a->frequency_resource_assignment.nbits = num_bits;
sci_1a_len += 9;
sci_1a->time_resource_assignment.nbits = 9;
} else {
num_bits = ceil(log2((n_subch * (n_subch + 1)) >> 1));
sci_1a_len += num_bits;
sci_1a->frequency_resource_assignment.nbits = num_bits;
sci_1a_len += 5;
sci_1a->time_resource_assignment.nbits = 5;
}
LOG_D(NR_MAC,"sci 1A - sl_MaxNumPerReserve:%d, sci 1a len:%d, FRA nbits:%d, TRA nbits:%d\n",
sl_MaxNumPerReserve,sci_1a_len,
sci_1a->frequency_resource_assignment.nbits,
sci_1a->time_resource_assignment.nbits);
//Determine bits for res reservation period
uint8_t n_rsvperiod = (selectedconfigRP &&
selectedconfigRP->sl_ResourceReservePeriodList_r16)
? selectedconfigRP->sl_ResourceReservePeriodList_r16->list.count : 0;
#define SL_IE_ENABLED 0
if (selectedconfigRP &&
selectedconfigRP->sl_MultiReserveResource_r16 == SL_IE_ENABLED) {
num_bits = ceil(log2(n_rsvperiod));
sci_1a_len += num_bits;
sci_1a->resource_reservation_period.nbits = num_bits;
} else
sci_1a->resource_reservation_period.nbits = 0;
LOG_D(NR_MAC,"sci 1A - n_rsvperiod:%d, sci 1a len:%d, res reserve period.nbits:%d\n",
n_rsvperiod, sci_1a_len,
sci_1a->resource_reservation_period.nbits);
uint8_t n_dmrspatterns = 0;
if (rpool->sl_PSSCH_Config_r16 &&
rpool->sl_PSSCH_Config_r16->present == NR_SetupRelease_SL_PSSCH_Config_r16_PR_setup) {
NR_SL_PSSCH_Config_r16_t *pssch_cfg = rpool->sl_PSSCH_Config_r16->choice.setup;
//Determine bits for DMRS PATTERNS
n_dmrspatterns = (pssch_cfg && pssch_cfg->sl_PSSCH_DMRS_TimePatternList_r16)
? pssch_cfg->sl_PSSCH_DMRS_TimePatternList_r16->list.count : 0;
}
AssertFatal((n_dmrspatterns>=1) && (n_dmrspatterns <=3),
"Number of DMRS Patterns should be 1or2or3. Resource Pool Configuration Error.\n");
if (n_dmrspatterns) {
num_bits = ceil(log2(n_dmrspatterns));
sci_1a_len += num_bits;
sci_1a->dmrs_pattern.nbits = num_bits;
}
LOG_D(NR_MAC,"sci 1A - n_dmrspatterns:%d, sci 1a len:%d, dmrs_pattern.nbits:%d\n",
n_dmrspatterns, sci_1a_len, sci_1a->dmrs_pattern.nbits);
//Determine bits for Additional MCS table
if (rpool->sl_Additional_MCS_Table_r16) {
int numbits = (*rpool->sl_Additional_MCS_Table_r16 > 1) ? 2 : 1;
sci_1a_len += numbits;
sci_1a->additional_mcs_table_indicator.nbits = numbits;
AssertFatal(*rpool->sl_Additional_MCS_Table_r16<=2, "additional table value cannot be > 2. Resource Pool Configuration Error.\n");
}
LOG_D(NR_MAC,"sci 1A - additional_table:%ld, sci 1a len:%d, additional table nbits:%d\n",
rpool->sl_Additional_MCS_Table_r16 ? *rpool->sl_Additional_MCS_Table_r16 : 0,
sci_1a_len,
sci_1a->additional_mcs_table_indicator.nbits);
uint8_t psfch_period = 0;
if (rpool->sl_PSFCH_Config_r16 &&
rpool->sl_PSFCH_Config_r16->present == NR_SetupRelease_SL_PSFCH_Config_r16_PR_setup) {
NR_SL_PSFCH_Config_r16_t *psfch_config = rpool->sl_PSFCH_Config_r16->choice.setup;
//Determine bits for PSFCH overhead indication
const uint8_t psfch_periods[] = {0,1,2,4};
psfch_period = (psfch_config->sl_PSFCH_Period_r16)
? psfch_periods[*psfch_config->sl_PSFCH_Period_r16] : 0;
}
if ((psfch_period == 2) || (psfch_period == 4)) {
sci_1a_len += 1;
sci_1a->psfch_overhead_indication.nbits = 1;
} else
sci_1a->psfch_overhead_indication.nbits = 0;
LOG_D(NR_MAC,"sci 1A - psfch_period:%d, sci 1a len:%d, psfch overhead nbits:%d\n",
psfch_period, sci_1a_len,
sci_1a->psfch_overhead_indication.nbits);
//Determine number of reserved bits
uint8_t num_reservedbits = 0;
if (rpool->sl_PSCCH_Config_r16 &&
rpool->sl_PSCCH_Config_r16->present == NR_SetupRelease_SL_PSCCH_Config_r16_PR_setup) {
NR_SL_PSCCH_Config_r16_t *pscch_config = rpool->sl_PSCCH_Config_r16->choice.setup;
num_reservedbits = (pscch_config->sl_NumReservedBits_r16)
? *pscch_config->sl_NumReservedBits_r16 : 0;
}
AssertFatal((num_reservedbits>=2) || (num_reservedbits<=4) ,
"Num Reserved bits can only be 2or3or4. Resource Pool Configuration Error.\n");
sci_1a_len += num_reservedbits;
sci_1a->reserved_bits.nbits = num_reservedbits;
LOG_D(NR_MAC,"sci 1A - reserved_bits:%d, sci 1a len:%d, sci_1a->reserved_bits.nbits:%d\n",
num_reservedbits, sci_1a_len, sci_1a->reserved_bits.nbits);
LOG_D(NR_MAC,"sci 1A Length in bits: %d \n",sci_1a_len);
return sci_1a_len;
}
/* This function determines the number of sidelink slots in 1024 frames - DFN cycle
* which can be used for determining reserved slots and REsource pool slots according to bitmap.
* Sidelink slots are the uplink and mixed slots with sidelink support except the SSB slots.
*/
uint32_t sl_determine_num_sidelink_slots(uint8_t mod_id, uint16_t *N_SSB_16frames, uint16_t *N_SL_SLOTS_perframe)
{
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
uint32_t N_SSB_1024frames = 0;
uint32_t N_SL_SLOTS = 0;
*N_SL_SLOTS_perframe = 0;
*N_SSB_16frames = 0;
if (sl_mac->rx_sl_bch.status) {
sl_ssb_timealloc_t *ssb_timealloc = &sl_mac->rx_sl_bch.ssb_time_alloc;
*N_SSB_16frames += ssb_timealloc->sl_NumSSB_WithinPeriod;
LOG_D(MAC, "RX SSB Slots:%d\n", *N_SSB_16frames);
}
if (sl_mac->tx_sl_bch.status) {
sl_ssb_timealloc_t *ssb_timealloc = &sl_mac->tx_sl_bch.ssb_time_alloc;
*N_SSB_16frames += ssb_timealloc->sl_NumSSB_WithinPeriod;
LOG_D(MAC, "TX SSB Slots:%d\n", *N_SSB_16frames);
}
//Total SSB slots in SFN cycle (1024 frames)
N_SSB_1024frames = SL_FRAME_NUMBER_CYCLE/SL_NR_SSB_REPETITION_IN_FRAMES * (*N_SSB_16frames);
sl_nr_phy_config_request_t *sl_cfg = &sl_mac->sl_phy_config.sl_config_req;
uint8_t sl_scs = sl_cfg->sl_bwp_config.sl_scs;
uint8_t num_slots_per_frame = 10*(1<<sl_scs);
uint8_t slot_type = 0;
for (int i = 0; i < num_slots_per_frame; i++) {
slot_type = sl_nr_ue_slot_select(sl_cfg, 0, i, TDD);
if (slot_type == NR_SIDELINK_SLOT) {
*N_SL_SLOTS_perframe = *N_SL_SLOTS_perframe + 1;
sl_mac->sl_slot_bitmap |= (1<<i);
}
}
//Determine total number of Valid Sidelink slots which can be used for Respool in a SFN cycle (1024 frames)
N_SL_SLOTS = (*N_SL_SLOTS_perframe * SL_FRAME_NUMBER_CYCLE) - N_SSB_1024frames;
LOG_D(MAC, "[UE%d]SL-MAC:SSB slots in 1024 frames:%d, N_SL_SLOTS_perframe:%d, N_SL_SLOTs in 1024 frames:%d, SL SLOT bitmap:%x\n",
mod_id,N_SSB_1024frames, *N_SL_SLOTS_perframe,
N_SL_SLOTS, sl_mac->sl_slot_bitmap);
return N_SL_SLOTS;
}
uint8_t count_PSFCH_PRBs_bits(uint8_t* buf, size_t size) {
uint8_t count = 0;
uint8_t byte;
for (size_t i = 0; i < size; i++) {
byte = buf[i];
while(byte) {
count += byte & 1;
byte >>= 1;
}
}
return count;
}
static void compute_params(int module_idP, psfch_params_t* psfch_params) {
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
if (!mac->sl_tx_res_pool->sl_PSFCH_Config_r16 &&
mac->sl_tx_res_pool->sl_PSFCH_Config_r16->present != NR_SetupRelease_SL_PSFCH_Config_r16_PR_setup)
return;
psfch_params->prbs_sets = calloc(1, sizeof(prbs_set_t));
NR_SL_PSFCH_Config_r16_t *sl_psfch_config = mac->sl_tx_res_pool->sl_PSFCH_Config_r16->choice.setup;
const int sl_num_muxcs_pair[4] = {1, 2, 3, 6};
uint8_t sci2_src_id = mac->sci_pdu_rx.source_id;
uint8_t *rb_buf = sl_psfch_config->sl_PSFCH_RB_Set_r16->buf;
size_t size = sl_psfch_config->sl_PSFCH_RB_Set_r16->size / sizeof(rb_buf[0]);
uint8_t m_psfch_prb_set = count_PSFCH_PRBs_bits(rb_buf, size);
long sl_numsubchannel = *mac->sl_tx_res_pool->sl_NumSubchannel_r16;
const uint8_t psfch_periods[] = {0,1,2,4};
long n_psfch_pssch = (sl_psfch_config->sl_PSFCH_Period_r16)
? psfch_periods[*sl_psfch_config->sl_PSFCH_Period_r16] : 0;
long n_psfch_cs = *sl_psfch_config->sl_NumMuxCS_Pair_r16;
double m_psfch_subch_slot = m_psfch_prb_set / (sl_numsubchannel * n_psfch_pssch);
// FIXME: Add second condition from spec. 38213 16.3, current implementation assuming single subchannel
long n_psfch_type = *sl_psfch_config->sl_PSFCH_CandidateResourceType_r16 ? sl_numsubchannel : 1;
uint16_t r_psfch_prb_cs = n_psfch_type * m_psfch_subch_slot * sl_num_muxcs_pair[n_psfch_cs];
uint8_t psfch_rsc_idx = (sci2_src_id + module_idP) / r_psfch_prb_cs;
LOG_D(NR_MAC, "size %lu, m_psfch_prb_set %d, sl_numsubchannel %ld, n_psfch_pssch %ld, n_psfch_cs %d\n", size, m_psfch_prb_set, sl_numsubchannel, n_psfch_pssch, sl_num_muxcs_pair[n_psfch_cs]);
LOG_D(NR_MAC, "m_psfch_subch_slot %f, n_psfch_type %ld, r_psfch_prb_cs %d, psfch_rsc_idx %d\n", m_psfch_subch_slot, n_psfch_type, r_psfch_prb_cs, psfch_rsc_idx);
psfch_params->m0 = table_16_3_1[n_psfch_cs][psfch_rsc_idx];
// 38213 16.3 Compute PRB allocation
psfch_params->prbs_sets->start_prb = (uint16_t**)calloc(n_psfch_pssch, sizeof(uint16_t*));
psfch_params->prbs_sets->end_prb = (uint16_t**)calloc(n_psfch_pssch, sizeof(uint16_t*));
for (int k=0; k<n_psfch_pssch; k++) {
psfch_params->prbs_sets->start_prb[k] = (uint16_t*)calloc(sl_numsubchannel, sizeof(uint16_t));
psfch_params->prbs_sets->end_prb[k] = (uint16_t*)calloc(sl_numsubchannel, sizeof(uint16_t));
}
for (int i = 0; i < n_psfch_pssch; i++) {
for (int j = 0; j < sl_numsubchannel; j++) {
psfch_params->prbs_sets->start_prb[i][j] = (i + j * n_psfch_pssch) * m_psfch_subch_slot;
psfch_params->prbs_sets->end_prb[i][j] = (i + 1 + j * n_psfch_pssch) * m_psfch_subch_slot - 1;
}
}
}
void configure_psfch_params(int module_idP,
NR_UE_MAC_INST_t *mac,
sl_nr_rx_indication_t *rx_ind,
int pdu_id)
{
const uint8_t time_gap[] = {2, 3};
const uint8_t psfch_periods[] = {0,1,2,4};
NR_SL_PSFCH_Config_r16_t *sl_psfch_config = mac->sl_tx_res_pool->sl_PSFCH_Config_r16->choice.setup;
long psfch_period = (sl_psfch_config->sl_PSFCH_Period_r16)
? psfch_periods[*sl_psfch_config->sl_PSFCH_Period_r16] : 0;
uint8_t psfch_min_time_gap = time_gap[*sl_psfch_config->sl_MinTimeGapPSFCH_r16];
int delta_slots = (rx_ind->slot + psfch_min_time_gap) % psfch_period ? psfch_period - (rx_ind->slot + psfch_min_time_gap) % psfch_period: 0;
uint16_t sched_slot = rx_ind->slot + psfch_min_time_gap + delta_slots;
uint16_t sched_frame = rx_ind->sfn;
int scs = get_softmodem_params()->numerology;
if (sched_slot >= nr_slots_per_frame[scs]) {
sched_slot %= nr_slots_per_frame[scs];
sched_frame = (sched_frame + 1) % 1024;
}
uint8_t harq_pid = (rx_ind->rx_indication_body + pdu_id)->rx_slsch_pdu.harq_pid;
mac->sl_info.list[0] = calloc(1, sizeof(NR_SL_UE_info_t));
NR_UE_sl_harq_t *harq_proc = &mac->sl_info.list[0]->UE_sched_ctrl.sl_harq_processes[harq_pid];
harq_proc->feedback_slot = sched_slot;
harq_proc->feedback_frame = sched_frame;
harq_proc->is_active = true;
LOG_D(NR_MAC, "harq pid: %d:%d psfch_period %ld, delta_slots %d, feedback frame:slot %d:%d, frame:slot %d:%d, time_gap %d, harq feedback %d\n",
harq_pid,
mac->sl_info.list[0]->UE_sched_ctrl.sl_harq_processes[harq_pid].is_active,
psfch_period,
delta_slots,
harq_proc->feedback_frame,
harq_proc->feedback_slot,
rx_ind->sfn,
rx_ind->slot,
psfch_min_time_gap,
mac->sci_pdu_rx.harq_feedback);
uint8_t ack_nack = (rx_ind->rx_indication_body + pdu_id)->rx_slsch_pdu.ack_nack;
mac->sl_tx_config_psfch_pdu[harq_pid] = calloc(1, sizeof(sl_nr_tx_config_psfch_pdu_t));
psfch_params_t *psfch_params = calloc(1, sizeof(psfch_params_t));
compute_params(module_idP, psfch_params);
sl_nr_tx_config_psfch_pdu_t *psfch_pdu = mac->sl_tx_config_psfch_pdu[harq_pid];
psfch_pdu->initial_cyclic_shift = psfch_params->m0;
if (mac->sci1_pdu.second_stage_sci_format == 2 ||
mac->sci_pdu_rx.cast_type == 1 ||
mac->sci_pdu_rx.cast_type == 2) {
psfch_pdu->mcs = sequence_cyclic_shift_harq_ack_or_ack_or_only_nack[ack_nack];
} else if (mac->sci1_pdu.second_stage_sci_format == 1 ||
(mac->sci1_pdu.second_stage_sci_format == 1 && mac->sci_pdu_rx.cast_type == 3)) {
psfch_pdu->mcs = sequence_cyclic_shift_harq_ack_or_ack_or_only_nack[0];
}
const uint8_t values[] = {7, 8, 9, 10, 11, 12, 13, 14};
NR_SL_BWP_Generic_r16_t *sl_bwp = mac->sl_bwp->sl_BWP_Generic_r16;
uint8_t sl_num_symbols = *sl_bwp->sl_LengthSymbols_r16 ? values[*sl_bwp->sl_LengthSymbols_r16] : 0;
// start_symbol_index has been used as lprime check 38.213 16.3
psfch_pdu->start_symbol_index = *sl_bwp->sl_StartSymbol_r16 + sl_num_symbols - 2;
LOG_D(NR_PHY, "sl_StartSymbol_r16 %ld, sl_num_symbols: %d, start sym index %d, mcs %d\n", *sl_bwp->sl_StartSymbol_r16, sl_num_symbols, psfch_pdu->start_symbol_index, psfch_pdu->mcs);
psfch_pdu->hopping_id = *mac->sl_bwp->sl_BWP_PoolConfigCommon_r16->sl_TxPoolSelectedNormal_r16->list.array[0]->sl_ResourcePool_r16->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_HopID_r16;
psfch_pdu->prb = psfch_params->prbs_sets->start_prb[rx_ind->slot%psfch_period][0]; // FIXME [0] is based on assumption of number of subchannels = 1; 0 is channel id
print_prb_set_allocation(psfch_params, psfch_period, 1);
LOG_D(NR_PHY, "slot %d, slot mode psfch_period %ld, psfch_pdu->prb %d, start_prb %d\n", rx_ind->slot, rx_ind->slot%psfch_period, psfch_pdu->prb, psfch_params->prbs_sets->start_prb[rx_ind->slot%psfch_period][0]);
int locbw = sl_bwp->sl_BWP_r16->locationAndBandwidth;
psfch_pdu->sl_bwp_start = NRRIV2PRBOFFSET(locbw, MAX_BWP_SIZE);
psfch_pdu->freq_hop_flag = 0;
psfch_pdu->group_hop_flag = 0;
psfch_pdu->second_hop_prb = 0;
psfch_pdu->bit_len_harq = 1;
LOG_D(NR_MAC,"Filled psfch pdu\n");
}
void configure_csi_report_params(NR_UE_MAC_INST_t* mac) {
mac->sl_csi_report = (nr_sl_csi_report_t *) malloc(sizeof(nr_sl_csi_report_t));
mac->sl_csi_report->CQI = mac->csirs_measurements.cqi;
mac->sl_csi_report->RI = mac->csirs_measurements.rank_indicator;
mac->sl_csi_report->R = 0;
}
void nr_ue_process_mac_sl_pdu(int module_idP,
sl_nr_rx_indication_t *rx_ind,
int pdu_id)
{
//LOG_I(NR_MAC,"nr_ue_process_mac_sl_pdu enter\n");
uint8_t *pduP = (rx_ind->rx_indication_body + pdu_id)->rx_slsch_pdu.pdu;
int32_t pdu_len = (int32_t)(rx_ind->rx_indication_body + pdu_id)->rx_slsch_pdu.pdu_length;
uint8_t done = 0;
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
int frame = rx_ind->sfn;
int slot = rx_ind->slot;
if (!pduP){
return;
}
//LOG_I(NR_MAC,"nr_ue_process_mac_sl_pdu pduP not null\n");
if (mac->sci_pdu_rx.harq_feedback) {
configure_psfch_params(module_idP, mac, rx_ind, pdu_id);
}
if (mac->sci_pdu_rx.csi_req) {
LOG_D(NR_MAC, "%4d.%2d Configuring sl_csi_report parameters\n", frame, slot);
configure_csi_report_params(mac);
}
//LOG_I(NR_MAC,"nr_ue_process_mac_sl_pdu pduP not null %d.%d\n",frame,slot);
if ((rx_ind->rx_indication_body + pdu_id)->rx_slsch_pdu.ack_nack == 0)
return;
LOG_D(NR_MAC, "In %s : processing PDU %d (with length %d) of %d total number of PDUs...\n", __FUNCTION__, pdu_id, pdu_len, rx_ind->number_pdus);
NR_SLSCH_MAC_SUBHEADER_FIXED *sl_sch_subheader = (NR_SLSCH_MAC_SUBHEADER_FIXED *) pduP;
LOG_D(NR_PHY, "Rx V %d R %d SRC %d DST %d\n", sl_sch_subheader->V, sl_sch_subheader->R, sl_sch_subheader->SRC, sl_sch_subheader->DST);
pduP += sizeof(*sl_sch_subheader);
pdu_len -= sizeof(*sl_sch_subheader);
while (!done && pdu_len > 0) {
uint16_t mac_len = 0x0000;
uint16_t mac_subheader_len = 0x0001; // default to fixed-length subheader = 1-oct
uint8_t rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)(pduP))->LCID;
LOG_D(NR_MAC, "[UE %x] LCID %d, remaining pdu length %d byte(s)\n", mac->src_id, rx_lcid, pdu_len);
switch (rx_lcid) {
// MAC CE
case SL_SCH_LCID_4_19:
if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len))
return;
LOG_I(NR_MAC, "%4d.%2d : SLSCH -> LCID %d %d bytes with subheader %d\n", frame, slot, rx_lcid, mac_len, mac_subheader_len);
mac_rlc_data_ind(module_idP,
mac->src_id,
0,
frame,
ENB_FLAG_NO,
MBMS_FLAG_NO,
rx_lcid,
(char *)(pduP + mac_subheader_len),
mac_len,
1,
NULL);
break;
case SL_SCH_LCID_SL_CSI_REPORT:
{
NR_MAC_SUBHEADER_FIXED* sub_pdu_header = (NR_MAC_SUBHEADER_FIXED*) pduP;
LOG_D(NR_MAC, "LCID %i, R %i\n", sub_pdu_header->LCID, sub_pdu_header->R);
mac_len = sizeof(*sub_pdu_header);
nr_sl_csi_report_t* nr_sl_csi_report = (nr_sl_csi_report_t *) (pduP + mac_len);
LOG_D(NR_MAC, "%4d.%2d: CQI: %i RI: %i\n", frame, slot, nr_sl_csi_report->CQI, nr_sl_csi_report->RI);
break;
}
case SL_SCH_LCID_SL_PADDING:
LOG_D(NR_MAC,"Received padding\n");
done = 1;
break;
case SL_SCH_LCID_SCCH_PC5_NOT_PROT:
case SL_SCH_LCID_SCCH_PC5_DSMC:
case SL_SCH_LCID_SCCH_PC5_PROT:
case SL_SCH_LCID_SCCH_PC5_RRC:
case SL_SCH_LCID_20_55:
case SL_SCH_LCID_SCCH_RRC_SL_RLC0:
case SL_SCH_LCID_SCCH_RRC_SL_RLC1:
case SL_SCH_LCID_SCCH_SL_DISCOVERY:
case SL_SCH_LCID_SL_INTER_UE_COORD_REQ:
case SL_SCH_LCID_SL_INTER_UE_COORD_INFO:
case SL_SCH_LCID_SL_DRX_CMD:
LOG_W(NR_MAC,"Received unsupported SL LCID %d\n",rx_lcid);
return;
break;
}
pduP += ( mac_subheader_len + mac_len );
pdu_len -= ( mac_subheader_len + mac_len );
LOG_D(NR_MAC, "mac_subhead_len + mac_len = %d\n", mac_subheader_len + mac_len);
LOG_D(NR_MAC, "%4d.%2d : SLSCH -> LCID %d remaining pdu length %d byte(s)\n", frame, slot, rx_lcid, pdu_len);
if (pdu_len < 0)
LOG_E(NR_MAC, "[UE %d][%d.%d] nr_ue_process_mac_pdu_sl, residual mac pdu length %d < 0!\n", module_idP, frame, slot, pdu_len);
}
}

View File

@@ -43,7 +43,7 @@
#include "NR_MAC_COMMON/nr_mac_common.h"
#include "NR_MAC_UE/mac_proto.h"
#include "NR_MAC_UE/mac_extern.h"
#include "NR_MAC_UE/nr_ue_sci.h"
/* utils */
#include "assertions.h"
#include "oai_asn1.h"
@@ -51,7 +51,7 @@
#include "utils.h"
#include <executables/softmodem-common.h>
#include <executables/nr-uesoftmodem.h>
#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h"
#include "LAYER2/RLC/rlc.h"
@@ -87,6 +87,8 @@ void fill_scheduled_response(nr_scheduled_response_t *scheduled_response,
fapi_nr_dl_config_request_t *dl_config,
fapi_nr_ul_config_request_t *ul_config,
fapi_nr_tx_request_t *tx_request,
sl_nr_rx_config_request_t *sl_rx_config,
sl_nr_tx_config_request_t *sl_tx_config,
module_id_t mod_id,
int cc_id,
frame_t frame,
@@ -101,6 +103,8 @@ void fill_scheduled_response(nr_scheduled_response_t *scheduled_response,
scheduled_response->frame = frame;
scheduled_response->slot = slot;
scheduled_response->phy_data = phy_data;
scheduled_response->sl_rx_config = sl_rx_config;
scheduled_response->sl_tx_config = sl_tx_config;
}
@@ -970,7 +974,7 @@ void nr_ue_dl_scheduler(nr_downlink_indication_t *dl_info)
}
dcireq.dl_config_req = *dl_config;
fill_scheduled_response(&scheduled_response, &dcireq.dl_config_req, NULL, NULL, mod_id, cc_id, rx_frame, rx_slot, dl_info->phy_data);
fill_scheduled_response(&scheduled_response, &dcireq.dl_config_req, NULL, NULL, NULL, NULL, mod_id, cc_id, rx_frame, rx_slot, dl_info->phy_data);
if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) {
LOG_D(NR_MAC,"1# scheduled_response transmitted, %d, %d\n", rx_frame, rx_slot);
mac->if_module->scheduled_response(&scheduled_response);
@@ -1079,7 +1083,7 @@ void nr_ue_ul_scheduler(nr_uplink_indication_t *ul_info)
}
}
pthread_mutex_unlock(&ul_config->mutex_ul_config); // avoid double lock
fill_scheduled_response(&scheduled_response, NULL, ul_config, &tx_req, mod_id, cc_id, frame_tx, slot_tx, ul_info->phy_data);
fill_scheduled_response(&scheduled_response, NULL, ul_config, &tx_req, NULL,NULL,mod_id, cc_id, frame_tx, slot_tx, ul_info->phy_data);
if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){
LOG_D(NR_MAC,"3# scheduled_response transmitted,%d, %d\n", frame_tx, slot_tx);
mac->if_module->scheduled_response(&scheduled_response);
@@ -2190,7 +2194,7 @@ void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, vo
&pucch[j],
pucch_pdu);
nr_scheduled_response_t scheduled_response;
fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, module_idP, 0 /*TBR fix*/, frameP, slotP, phy_data);
fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, NULL,NULL,module_idP, 0 /*TBR fix*/, frameP, slotP, phy_data);
if (mac->if_module != NULL && mac->if_module->scheduled_response != NULL)
mac->if_module->scheduled_response(&scheduled_response);
if (mac->state == UE_WAIT_TX_ACK_MSG4)
@@ -2639,7 +2643,7 @@ static void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_fr
prach_config_pdu->prach_tx_power = get_prach_tx_power(module_idP);
set_ra_rnti(mac, prach_config_pdu);
fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, module_idP, 0 /*TBR fix*/, frameP, slotP, NULL);
fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, NULL,NULL,module_idP, 0 /*TBR fix*/, frameP, slotP, NULL);
if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL)
mac->if_module->scheduled_response(&scheduled_response);
@@ -2657,9 +2661,15 @@ typedef struct {
uint8_t phr_ce_len;
uint8_t phr_header_len;
uint16_t sdu_length_total;
NR_BSR_SHORT *bsr_s;
union {
NR_BSR_SHORT *bsr_s;
NR_SL_BSR_SHORT *sl_bsr_s;
};
NR_BSR_LONG *bsr_l;
NR_BSR_SHORT *bsr_t;
union {
NR_BSR_SHORT *bsr_t;
NR_SL_BSR_SHORT *sl_bsr_t;
};
//NR_POWER_HEADROOM_CMD *phr_pr;
int tot_mac_ce_len;
uint8_t total_mac_pdu_header_len;
@@ -2720,15 +2730,16 @@ int nr_ue_get_sdu_mac_ce_pre(module_id_t module_idP,
"Inconsistent BSR Trigger=%d !\n",
mac->BSR_reporting_active);
uint8_t size_bsr = get_softmodem_params()->sl_mode ? sizeof(NR_SL_BSR_SHORT) : sizeof(NR_BSR_SHORT);
//A Regular or Periodic BSR can only be sent if TBS is sufficient as transmitting only a BSR is not allowed if UE has data to transmit
if (num_lcg_id_with_data <= 1) {
if (buflen >= (sizeof(NR_BSR_SHORT)+sizeof(NR_MAC_SUBHEADER_FIXED)+1)) {
mac_ce_p->bsr_ce_len = sizeof(NR_BSR_SHORT); //1 byte
if (buflen >= (size_bsr + sizeof(NR_MAC_SUBHEADER_FIXED) + 1)) {
mac_ce_p->bsr_ce_len = size_bsr;
mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_FIXED); //1 byte
}
} else {
if (buflen >= (num_lcg_id_with_data+1+sizeof(NR_MAC_SUBHEADER_SHORT)+1)) {
mac_ce_p->bsr_ce_len = num_lcg_id_with_data + 1; //variable size
mac_ce_p->bsr_ce_len = num_lcg_id_with_data * size_bsr + 1; //variable size
mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_SHORT); //2 bytes
}
}
@@ -3116,3 +3127,639 @@ void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UL_TIME_ALIG
dl_config->number_pdus += 1;
ul_time_alignment->ta_apply = false;
}
uint16_t sl_adjust_ssb_indices(sl_ssb_timealloc_t *ssb_timealloc,
uint32_t slot_in_16frames,
uint16_t *ssb_slot_ptr) {
uint16_t ssb_slot = ssb_timealloc->sl_TimeOffsetSSB;
uint16_t numssb = 0;
*ssb_slot_ptr = 0;
if (ssb_timealloc->sl_NumSSB_WithinPeriod == 0) {
*ssb_slot_ptr = 0;
return 0;
}
while (slot_in_16frames > ssb_slot) {
numssb = numssb + 1;
if (numssb < ssb_timealloc->sl_NumSSB_WithinPeriod)
ssb_slot = ssb_slot + ssb_timealloc->sl_TimeInterval;
else
break;
}
*ssb_slot_ptr = ssb_slot;
return numssb;
}
/*
* This function calculates the indices based on the new timing (frame,slot)
* acquired by the UE.
* NUM SSB, SLOT_SSB needs to be calculated based on current timing
*/
void sl_adjust_indices_based_on_timing(uint32_t frame, uint32_t slot,
uint32_t frame_tx, uint32_t slot_tx,
uint16_t mod_id, uint16_t slots_per_frame)
{
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
uint16_t frame_16 = frame % SL_NR_SSB_REPETITION_IN_FRAMES;
uint32_t slot_in_16frames = (frame_16 * slots_per_frame) + slot;
uint16_t frame_tx_16 = frame_tx % SL_NR_SSB_REPETITION_IN_FRAMES;
uint32_t slot_tx_in_16frames = (frame_tx_16 * slots_per_frame) + slot_tx;
LOG_I(NR_MAC,"[UE%d]PSBCH params adjusted based on RX current timing %d:%d. frame_16:%d, slot_in_16frames:%d\n",
mod_id, frame, slot, frame_16, slot_in_16frames);
LOG_I(NR_MAC,"[UE%d]PSBCH params adjusted based on TX current timing %d:%d. frame_16:%d, slot_in_16frames:%d\n",
mod_id, frame_tx, slot_tx, frame_tx_16, slot_tx_in_16frames);
//Adjust PSBCH Indices based on current RX timing
sl_ssb_timealloc_t *ssb_timealloc = &sl_mac->rx_sl_bch.ssb_time_alloc;
sl_mac->rx_sl_bch.num_ssb = sl_adjust_ssb_indices(ssb_timealloc, slot_in_16frames, &sl_mac->rx_sl_bch.ssb_slot);
//Adjust PSBCH Indices based on current TX timing
ssb_timealloc = &sl_mac->tx_sl_bch.ssb_time_alloc;
sl_mac->tx_sl_bch.num_ssb = sl_adjust_ssb_indices(ssb_timealloc, slot_tx_in_16frames, &sl_mac->tx_sl_bch.ssb_slot);
LOG_I(NR_MAC,"[UE%d]PSBCH params adjusted based on RX current timing %d:%d. NumSSB:%d, ssb_slot:%d\n",
mod_id, frame, slot, sl_mac->rx_sl_bch.num_ssb,
sl_mac->rx_sl_bch.ssb_slot);
LOG_I(NR_MAC,"[UE%d]PSBCH params adjusted based on TX current timing %d:%d. NumSSB:%d, ssb_slot:%d\n",
mod_id, frame_tx, slot_tx, sl_mac->tx_sl_bch.num_ssb,
sl_mac->tx_sl_bch.ssb_slot);
}
/*
DETERMINE IF SLOT IS MARKED AS SSB SLOT
ACCORDING TO THE SSB TIME ALLOCATION PARAMETERS.
sl_numSSB_withinPeriod - NUM SSBS in 16frames
sl_timeoffset_SSB - time offset for first SSB at start of 16 frames cycle
sl_timeinterval - distance in slots between 2 SSBs
*/
uint8_t sl_determine_if_SSB_slot(uint16_t frame, uint16_t slot, uint16_t slots_per_frame,
sl_bch_params_t *sl_bch,
sl_sidelink_slot_type_t slot_type) {
uint16_t frame_16 = frame % SL_NR_SSB_REPETITION_IN_FRAMES;
uint32_t slot_in_16frames = (frame_16 * slots_per_frame) + slot;
uint16_t sl_NumSSB_WithinPeriod = sl_bch->ssb_time_alloc.sl_NumSSB_WithinPeriod;
uint16_t sl_TimeOffsetSSB = sl_bch->ssb_time_alloc.sl_TimeOffsetSSB;
uint16_t sl_TimeInterval = sl_bch->ssb_time_alloc.sl_TimeInterval;
uint16_t num_ssb = sl_bch->num_ssb, ssb_slot = sl_bch->ssb_slot;
LOG_D(NR_MAC, "%d:%d. slot_type:%d, num_ssb:%d,ssb_slot:%d, %d-%d-%d, status:%d\n",
frame, slot, slot_type,
sl_bch->num_ssb,sl_bch->ssb_slot,
sl_NumSSB_WithinPeriod, sl_TimeOffsetSSB, sl_TimeInterval, sl_bch->status);
if (sl_NumSSB_WithinPeriod && sl_bch->status) {
if (slot_in_16frames == sl_TimeOffsetSSB) {
num_ssb = 0;
ssb_slot = sl_TimeOffsetSSB;
}
if (num_ssb < sl_NumSSB_WithinPeriod && slot_in_16frames == ssb_slot) {
num_ssb += 1;
ssb_slot = (num_ssb < sl_NumSSB_WithinPeriod)
? (ssb_slot + sl_TimeInterval) : sl_TimeOffsetSSB;
//Update the time when the same slot with RX SLOT type is called
if (slot_type == SIDELINK_SLOT_TYPE_RX) {
sl_bch->ssb_slot = ssb_slot;
sl_bch->num_ssb = num_ssb;
}
LOG_D(NR_MAC, "%d:%d is a PSBCH SLOT. Slot type:%d Next PSBCH Slot:%d, num_ssb:%d\n",
frame, slot, slot_type,
sl_bch->ssb_slot,sl_bch->num_ssb);
return 1;
}
}
LOG_D(NR_MAC, "%d:%d is NOT a PSBCH SLOT. Next PSBCH Slot:%d, num_ssb:%d\n",
frame, slot, sl_bch->ssb_slot,sl_bch->num_ssb);
return 0;
}
bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
nr_sidelink_indication_t *sl_ind,
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
const NR_SL_ResourcePool_r16_t *sl_res_pool,
sl_nr_tx_config_request_t *tx_config,
uint8_t *config_type) {
uint16_t slot = sl_ind->slot_tx;
uint16_t frame = sl_ind->frame_tx;
int lcid = 4;
int sdu_length = 0;
uint16_t sdu_length_total = 0;
uint8_t total_mac_pdu_header_len = 0;
sl_nr_ue_mac_params_t* sl_mac_params = mac->SL_MAC_PARAMS;
if ((frame & 127) == 0 && slot == 0) {
print_meas(&mac->rlc_data_req,"rlc_data_req",NULL,NULL);
}
if (sl_ind->slot_type != SIDELINK_SLOT_TYPE_TX) return false;
if (slot > 17 && get_nrUE_params()->sync_ref) return false;
/*
if ((frame&127) > 0) return false;
if ((slot % 10) != 6) return false;
*/
LOG_D(NR_MAC,"[UE%d] SL-PSSCH SCHEDULER: Frame:SLOT %d:%d, slot_type:%d\n",
sl_ind->module_id, frame, slot,sl_ind->slot_type);
uint16_t slsch_pdu_length_max;
tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu.slsch_payload = mac->slsch_payload;
bool schedule_slsch = nr_schedule_slsch(mac, frame, slot, &mac->sci1_pdu, &mac->sci2_pdu, tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu.slsch_payload, NR_SL_SCI_FORMAT_2A, &slsch_pdu_length_max);
if (!schedule_slsch) return false;
LOG_D(NR_MAC,"SLSCH : slsch_pdu_length_max %d\n",slsch_pdu_length_max);
const uint8_t sh_size = sizeof(NR_MAC_SUBHEADER_LONG);
uint8_t *pdu = tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu.slsch_payload;
*config_type = SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH;
tx_config->number_pdus = 1;
tx_config->sfn = frame;
tx_config->slot = slot;
tx_config->tx_config_list[0].pdu_type = *config_type;
fill_pssch_pscch_pdu(sl_mac_params,
&tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu,
sl_bwp,
sl_res_pool,
&mac->sci1_pdu,
&mac->sci2_pdu,
slsch_pdu_length_max,
NR_SL_SCI_FORMAT_1A,
NR_SL_SCI_FORMAT_2A);
int buflen = tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu.tb_size;
LOG_D(NR_MAC, "[UE%d] TTI-%d:%d TX PSCCH_PSSCH REQ TBS %d\n", sl_ind->module_id, frame, slot, buflen);
NR_SLSCH_MAC_SUBHEADER_FIXED *sl_sch_subheader = (NR_SLSCH_MAC_SUBHEADER_FIXED *) pdu;
sl_sch_subheader->V = 0;
sl_sch_subheader->R = 0;
sl_sch_subheader->SRC = get_softmodem_params()->node_number;
sl_sch_subheader->DST = 0xab;
pdu += sizeof(NR_SLSCH_MAC_SUBHEADER_FIXED);
LOG_D(NR_PHY, "Tx V %d, R %d, SRC %d, DST %d\n", sl_sch_subheader->V, sl_sch_subheader->R, sl_sch_subheader->SRC, sl_sch_subheader->DST);
int buflen_remain = buflen - sizeof(NR_SLSCH_MAC_SUBHEADER_FIXED);
LOG_D(NR_PHY, "buflen_remain after adding SL_SCH_MAC_SUBHEADER_FIXED %d\n", buflen_remain);
int num_sdus=0;
while (buflen_remain > 0) {
// Pointer used to build the MAC sub-PDU headers in the ULSCH buffer for each SDU
NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) pdu;
pdu += sh_size;
start_meas(&mac->rlc_data_req);
sdu_length = mac_rlc_data_req(0,
mac->src_id,
0,
frame,
ENB_FLAG_NO,
MBMS_FLAG_NO,
lcid,
buflen_remain,
(char *)pdu,
0,
0);
stop_meas(&mac->rlc_data_req);
AssertFatal(buflen_remain >= sdu_length, "In %s: LCID = 0x%02x RLC has segmented %d bytes but MAC has max %d remaining bytes\n",
__FUNCTION__,
lcid,
sdu_length,
buflen_remain);
if (sdu_length > 0) {
LOG_I(NR_MAC, "In %s: [UE %d] [%d.%d] SL-DXCH -> SLSCH, Generating SL MAC sub-PDU for SDU %d, length %d bytes, RB with LCID 0x%02x (buflen (TBS) %d bytes)\n",
__FUNCTION__,
0,
frame,
slot,
num_sdus + 1,
sdu_length,
lcid,
buflen);
header->R = 0;
header->F = 1;
header->LCID = lcid;
header->L = htons(sdu_length);
pdu += sdu_length;
sdu_length_total += sdu_length;
total_mac_pdu_header_len += sh_size;
buflen_remain -= (sh_size + sdu_length);
LOG_D(NR_PHY, "buflen_remain %d, subtracting (sh_size + sdu_length) %d, total_mac_pdu_header_len %hhu sdu total length %d, sdu_length %d\n", buflen_remain, (sh_size + sdu_length), total_mac_pdu_header_len, sdu_length_total, sdu_length);
num_sdus++;
} else {
pdu -= sh_size;
LOG_D(NR_MAC, "In %s: no data to transmit for RB with LCID 0x%02x\n", __FUNCTION__, lcid);
break;
}
}
if (buflen_remain > 0) {
NR_UE_MAC_CE_INFO *mac_ce_p = (NR_UE_MAC_CE_INFO *) pdu;
mac_ce_p->bsr_len = 0;
mac_ce_p->bsr_ce_len = 0;
mac_ce_p->bsr_header_len = 0;
mac_ce_p->phr_len = 0;
mac_ce_p->sdu_length_total = sdu_length_total;
mac_ce_p->total_mac_pdu_header_len = total_mac_pdu_header_len;
//nr_ue_get_sdu_mac_ce_pre updates all mac_ce related header field related to length
mac_ce_p->tot_mac_ce_len = nr_ue_get_sdu_mac_ce_pre(0, 0, frame, slot, 0, pdu, buflen, mac_ce_p);
buflen_remain -= mac_ce_p->tot_mac_ce_len;
pdu += mac_ce_p->tot_mac_ce_len;
LOG_D(NR_PHY, "buflen_remain %d, sdu_length_total %d, total_mac_pdu_header_len %d, adding tot_mac_ce_len %d, \n", buflen_remain, mac_ce_p->sdu_length_total, mac_ce_p->total_mac_pdu_header_len, mac_ce_p->tot_mac_ce_len);
}
if (buflen_remain > 0) {
if (mac->sl_csi_report != NULL) {
((NR_MAC_SUBHEADER_FIXED *) pdu)->R = 0;
((NR_MAC_SUBHEADER_FIXED *) pdu)->LCID = SL_SCH_LCID_SL_CSI_REPORT;
pdu++;
buflen_remain--;
((nr_sl_csi_report_t *) pdu)->RI = mac->sl_csi_report->RI;
((nr_sl_csi_report_t *) pdu)->CQI = mac->sl_csi_report->CQI;
((nr_sl_csi_report_t *) pdu)->R = mac->sl_csi_report->R;
LOG_D(NR_MAC, "%4d.%2d Sending sl_csi_report with CQI %i, RI %i\n", frame, slot, ((nr_sl_csi_report_t *) pdu)->CQI, ((nr_sl_csi_report_t *) pdu)->RI);
pdu++;
buflen_remain--;
free(mac->sl_csi_report);
mac->sl_csi_report = NULL;
}
}
if (buflen_remain > 0) {
LOG_D(NR_MAC, "In %s filling remainder %d bytes to the UL PDU \n", __FUNCTION__, buflen_remain);
((NR_MAC_SUBHEADER_FIXED *) pdu)->R = 0;
((NR_MAC_SUBHEADER_FIXED *) pdu)->LCID = SL_SCH_LCID_SL_PADDING;
pdu++;
buflen_remain--;
if (IS_SOFTMODEM_RFSIM) {
for (int j = 0; j < buflen_remain; j++) {
pdu[j] = (unsigned char) rand();
}
} else {
memset(pdu, 0, buflen_remain);
}
}
return true;
}
void nr_ue_sl_pscch_rx_scheduler(nr_sidelink_indication_t *sl_ind,
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
const NR_SL_ResourcePool_r16_t *sl_res_pool,
sl_nr_rx_config_request_t *rx_config,
uint8_t *config_type) {
*config_type = SL_NR_CONFIG_TYPE_RX_PSCCH;
rx_config->number_pdus = 1;
rx_config->sfn = sl_ind->frame_rx;
rx_config->slot = sl_ind->slot_rx;
rx_config->sl_rx_config_list[0].pdu_type = *config_type;
config_pscch_pdu_rx(&rx_config->sl_rx_config_list[0].rx_pscch_config_pdu,
sl_bwp,
sl_res_pool);
LOG_D(NR_MAC, "[UE%d] TTI-%d:%d RX PSCCH REQ \n", sl_ind->module_id,sl_ind->frame_rx, sl_ind->slot_rx);
}
/*
* determine if sidelink slot is a PSBCH slot
* If PSBCH rx slot and sync_source == SYNC_REF_UE
* TTI COMMAND = PSBCH RX
* if PSBCH tx slot and transmit SLSS == true
* TTI_COMMAND = PSBCH TX
* Sidelink UE can rx and tx a SSB however the SSB time
* allocation will be different
*/
uint8_t nr_ue_sl_psbch_scheduler(nr_sidelink_indication_t *sl_ind,
sl_nr_ue_mac_params_t *sl_mac_params,
sl_nr_rx_config_request_t *rx_config,
sl_nr_tx_config_request_t *tx_config,
uint8_t *config_type) {
uint8_t ret_status = 0, is_psbch_rx_slot = 0, is_psbch_tx_slot = 0;
uint16_t slot = sl_ind->slot_rx;
uint16_t frame = sl_ind->frame_rx;
// Schedule TX only if slot type is TX.
if (sl_ind->slot_type == SIDELINK_SLOT_TYPE_TX) {
slot = sl_ind->slot_tx;
frame = sl_ind->frame_tx;
}
sl_nr_phy_config_request_t *sl_cfg = &sl_mac_params->sl_phy_config.sl_config_req;
uint16_t scs = sl_cfg->sl_bwp_config.sl_scs;
uint16_t slots_per_frame = nr_slots_per_frame[scs];
LOG_D(NR_MAC,"[UE%d] SL-PSBCH SCHEDULER: Frame:SLOT %d:%d, slot_type:%d\n",
sl_ind->module_id, frame, slot,sl_ind->slot_type);
is_psbch_rx_slot = sl_determine_if_SSB_slot(frame, slot, slots_per_frame,
&sl_mac_params->rx_sl_bch,
sl_ind->slot_type);
if (is_psbch_rx_slot &&
sl_ind->slot_type == SIDELINK_SLOT_TYPE_RX) {
*config_type = SL_NR_CONFIG_TYPE_RX_PSBCH;
rx_config->number_pdus = 1;
rx_config->sfn = frame;
rx_config->slot = slot;
rx_config->sl_rx_config_list[0].pdu_type = *config_type;
LOG_D(NR_MAC, "[UE%d] TTI-%d:%d RX PSBCH REQ- rx_slss_id:%d, numSSB:%d, next slot_SSB:%d\n",
sl_ind->module_id,frame, slot,
sl_cfg->sl_sync_source.rx_slss_id,
sl_mac_params->rx_sl_bch.num_ssb,
sl_mac_params->rx_sl_bch.ssb_slot);
}
if (!is_psbch_rx_slot) {
is_psbch_tx_slot = sl_determine_if_SSB_slot(frame, slot, slots_per_frame,
&sl_mac_params->tx_sl_bch,
sl_ind->slot_type);
if (is_psbch_tx_slot &&
sl_ind->slot_type == SIDELINK_SLOT_TYPE_TX) {
*config_type = SL_NR_CONFIG_TYPE_TX_PSBCH;
tx_config->number_pdus = 1;
tx_config->sfn = frame;
tx_config->slot = slot;
tx_config->tx_config_list[0].pdu_type = *config_type;
tx_config->tx_config_list[0].tx_psbch_config_pdu.tx_slss_id = sl_mac_params->tx_sl_bch.slss_id;
tx_config->tx_config_list[0].tx_psbch_config_pdu.psbch_tx_power = 0;//TBD...
memcpy(tx_config->tx_config_list[0].tx_psbch_config_pdu.psbch_payload, sl_mac_params->tx_sl_bch.sl_mib, 4);
if ((frame&127) ==0 ) LOG_I(NR_MAC, "[SyncRefUE%d] TTI-%d:%d TX PSBCH REQ- tx_slss_id:%d, sl-mib:%x, numSSB:%d, next SSB slot:%d\n",
sl_ind->module_id,frame, slot,
sl_mac_params->tx_sl_bch.slss_id,
(*(uint32_t *)tx_config->tx_config_list[0].tx_psbch_config_pdu.psbch_payload),
sl_mac_params->tx_sl_bch.num_ssb,
sl_mac_params->tx_sl_bch.ssb_slot);
}
}
ret_status = is_psbch_rx_slot | is_psbch_tx_slot;
LOG_D(NR_MAC,"[UE%d] SL-PSBCH SCHEDULER: %d:%d,is psbch slot:%d, config type:%d\n",
sl_ind->module_id,frame, slot, ret_status, *config_type);
return ret_status;
}
/*
// This function will be called only for SIDELINK CAPABLE SLOTS.
// UPLINK SLOT OR MIXED SLOT which is SIDELINK SLOT
//Determine if PSBCH SLOT and if PSBCH RX/TX should be done
// IF NOT PSBCH SLOT continue ahead
// IF RX RES POOL CONFIGURED
// Determine if SLOT is a RX RES POOL RESERVED
// OR RX RES POOL RESOURCE SLOT according to time resource bitmap
// IF resource slot PSCCH RX action should be done
// IF TX RES POOL CONFIGURED
// Determine if SLOT is a TX RES POOL RESERVED
// OR RX RES POOL RESOURCE SLOT according to time resource bitmap
// IF resource slot PSCCH TX action should be done in case TX is scheduled
// ELSE SENSING SHOULD BE DONE
// IF TX/RX ACTION SHOULD BE DONE in this slot
// SEND SIDELINK TX/RX CONFIG REQUEST TO PHY
*/
void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind) {
AssertFatal(sl_ind != NULL, "sl_indication cannot be NULL\n");
module_id_t mod_id = sl_ind->module_id;
frame_t frame = sl_ind->frame_rx;
slot_t slot = sl_ind->slot_rx;
if (sl_ind->slot_type == SIDELINK_SLOT_TYPE_TX) {
frame = sl_ind->frame_tx;
slot = sl_ind->slot_tx;
}
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
sl_nr_phy_config_request_t *sl_cfg = &sl_mac->sl_phy_config.sl_config_req;
uint8_t mu = sl_cfg->sl_bwp_config.sl_scs;
uint8_t slots_per_frame = nr_slots_per_frame[mu];
//Adjust indices as new timing is acquired
if (sl_mac->adjust_timing) {
sl_adjust_indices_based_on_timing(sl_ind->frame_rx, sl_ind->slot_rx,
sl_ind->frame_tx, sl_ind->slot_tx,
mod_id, slots_per_frame);
sl_mac->adjust_timing = 0;
}
sl_nr_rx_config_request_t rx_config;
sl_nr_tx_config_request_t tx_config;
rx_config.number_pdus = 0;
tx_config.number_pdus = 0;
nr_scheduled_response_t scheduled_response;
memset(&scheduled_response,0, sizeof(nr_scheduled_response_t));
uint8_t tti_action = 0, is_psbch_slot = 0;
// Check if PSBCH slot and PSBCH should be transmitted or Received
is_psbch_slot = nr_ue_sl_psbch_scheduler(sl_ind, sl_mac, &rx_config, &tx_config, &tti_action);
bool tx_allowed=true,rx_allowed=true;
if (mac->sl_tx_res_pool && mac->sl_tx_res_pool->ext1 && mac->sl_tx_res_pool->ext1->sl_TimeResource_r16) {
int sl_tx_period = 8*mac->sl_tx_res_pool->ext1->sl_TimeResource_r16->size - mac->sl_tx_res_pool->ext1->sl_TimeResource_r16->bits_unused;
int slot_mod_period = sl_ind->slot_tx%sl_tx_period;
uint8_t mask = mac->sl_tx_res_pool->ext1->sl_TimeResource_r16->buf[slot_mod_period>>3];
if (((1<<slot_mod_period) % mask) == 0) tx_allowed=0;
}
if (mac->sl_rx_res_pool && mac->sl_rx_res_pool->ext1 && mac->sl_tx_res_pool->ext1->sl_TimeResource_r16) {
int sl_rx_period = 8*mac->sl_rx_res_pool->ext1->sl_TimeResource_r16->size - mac->sl_rx_res_pool->ext1->sl_TimeResource_r16->bits_unused;
int slot_mod_period = sl_ind->slot_rx%sl_rx_period;
uint8_t mask = mac->sl_rx_res_pool->ext1->sl_TimeResource_r16->buf[slot_mod_period>>3];
if (((1<<slot_mod_period) % mask) == 0) rx_allowed=false;
}
if (sl_ind->slot_type==SIDELINK_SLOT_TYPE_TX || sl_ind->phy_data==NULL) rx_allowed=false;
if (((get_nrUE_params()->sync_ref && sl_ind->slot_rx > 5) ||
(!get_nrUE_params()->sync_ref && sl_ind->slot_rx < 17)) && rx_allowed && !is_psbch_slot) {
LOG_D(NR_MAC,"Scheduling PSCCH RX processing slot %d, sync_ref %d\n",slot,get_nrUE_params()->sync_ref);
nr_ue_sl_pscch_rx_scheduler(sl_ind, mac->sl_bwp, mac->sl_rx_res_pool,&rx_config, &tti_action);
}
if (!is_psbch_slot && tx_allowed && sl_ind->slot_type == SIDELINK_SLOT_TYPE_TX) {
//Check if reserved slot or a sidelink resource configured in Rx/Tx resource pool timeresource bitmap
bool schedule_slsch = nr_ue_sl_pssch_scheduler(mac, sl_ind, mac->sl_bwp, mac->sl_tx_res_pool, &tx_config, &tti_action);
bool is_csi_rs_sent = false;
if (((slots_per_frame * sl_ind->frame_tx + sl_ind->slot_tx - sl_mac->slot_offset) % sl_mac->slot_periodicity) == 0 &&
schedule_slsch && mac->sci2_pdu.csi_req) {
nr_ue_sl_csi_rs_scheduler(mac, mu, mac->sl_bwp, &tx_config, NULL, &tti_action);
is_csi_rs_sent = true;
LOG_D(NR_MAC, "%4d.%2d Scheduling CSI-RS\n", frame, slot);
}
if (mac->sci_pdu_rx.harq_feedback && mac->sl_tx_res_pool->sl_PSFCH_Config_r16 && mac->sl_tx_res_pool->sl_PSFCH_Config_r16->choice.setup) {
NR_SL_PSFCH_Config_r16_t *sl_psfch_config = mac->sl_tx_res_pool->sl_PSFCH_Config_r16->choice.setup;
const uint8_t psfch_periods[] = {0,1,2,4};
long psfch_period = (sl_psfch_config->sl_PSFCH_Period_r16)
? psfch_periods[*sl_psfch_config->sl_PSFCH_Period_r16] : 0;
NR_UE_sl_harq_t *current_harq;
if (slot%psfch_period == 0) {
for (int harq_pid=0; harq_pid<NR_MAX_HARQ_PROCESSES; harq_pid++) {
current_harq = &mac->sl_info.list[0]->UE_sched_ctrl.sl_harq_processes[harq_pid];
sl_ind->slot_tx = current_harq->feedback_slot;
sl_ind->frame_tx = current_harq->feedback_frame;
sl_ind->slot_type = SIDELINK_SLOT_TYPE_TX;
if (current_harq->is_active && current_harq->feedback_slot == slot && current_harq->feedback_frame == frame) {
LOG_D(NR_MAC, "Scheduling PSFCH transmission at frame.slot (%d.%d) for harq_pid %d\n", current_harq->feedback_frame, current_harq->feedback_slot, harq_pid);
nr_ue_sl_psfch_scheduler(mac, psfch_period, sl_ind, mac->sl_bwp, mac->sl_tx_res_pool, &tx_config, &tti_action, is_csi_rs_sent);
current_harq->is_active = false;
current_harq->feedback_slot = -1;
current_harq->feedback_frame = -1;
mac->sci_pdu_rx.harq_feedback = 0;
break;
}
}
}
}
}
if (tti_action == SL_NR_CONFIG_TYPE_RX_PSBCH || tti_action == SL_NR_CONFIG_TYPE_RX_PSCCH || tti_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SCI ||
tti_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH) {
fill_scheduled_response(&scheduled_response, NULL, NULL, NULL, &rx_config, NULL, mod_id, 0,frame, slot, sl_ind->phy_data);
}
if (tti_action == SL_NR_CONFIG_TYPE_TX_PSBCH || tti_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH || tti_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH ||
tti_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH_CSI_RS || tti_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS) {
fill_scheduled_response(&scheduled_response, NULL, NULL, NULL, NULL, &tx_config, mod_id, 0,frame, slot, sl_ind->phy_data);
}
LOG_D(NR_MAC,"[UE%d]SL-SCHEDULER: TTI-RX-%d:%d, TX-%d:%d is_psbch_slot:%d TTIaction:%d\n",
mod_id,sl_ind->frame_rx, sl_ind->slot_rx,
sl_ind->frame_tx, sl_ind->slot_tx,
is_psbch_slot, tti_action);
if (tti_action) {
if ((mac->if_module != NULL) && (mac->if_module->scheduled_response != NULL))
mac->if_module->scheduled_response(&scheduled_response);
}
}
void nr_ue_sl_psfch_scheduler(NR_UE_MAC_INST_t *mac,
long psfch_period,
nr_sidelink_indication_t *sl_ind,
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
const NR_SL_ResourcePool_r16_t *sl_res_pool,
sl_nr_tx_config_request_t *tx_config,
uint8_t *config_type,
bool is_csi_rs_sent) {
uint16_t slot = sl_ind->slot_tx;
uint16_t frame = sl_ind->frame_tx;
int num_psfch_symbols = 0;
if (psfch_period == 1) num_psfch_symbols = 3;
else if (psfch_period == 2 || psfch_period == 4) {
num_psfch_symbols = mac->SL_MAC_PARAMS->sl_RxPool[0]->sci_1a.psfch_overhead_indication.nbits ? 3 : 0;
}
NR_UE_sl_harq_t *current_harq;
for (int harq_pid = 0; harq_pid < NR_MAX_HARQ_PROCESSES; harq_pid++) {
current_harq = &mac->sl_info.list[0]->UE_sched_ctrl.sl_harq_processes[harq_pid];
if (current_harq->is_active && current_harq->feedback_slot == slot && current_harq->feedback_frame == frame) {
sl_nr_tx_config_psfch_pdu_t *mac_psfch_pdu = mac->sl_tx_config_psfch_pdu[harq_pid];
fill_psfch_pdu(mac_psfch_pdu, tx_config, num_psfch_symbols);
*config_type = is_csi_rs_sent ? SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH_CSI_RS : SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH;
tx_config->number_pdus = 1;
tx_config->tx_config_list[0].pdu_type = *config_type;
LOG_D(NR_MAC,"Harq id: %d, SL-PSFCH SCHEDULER: frame.slot (%d.%d), slot_type:%d\n",
harq_pid, frame, slot,sl_ind->slot_type);
break;
}
}
}
void fill_psfch_pdu(sl_nr_tx_config_psfch_pdu_t *mac_psfch_pdu,
sl_nr_tx_config_request_t *tx_config,
int num_psfch_symbols) {
sl_nr_tx_config_psfch_pdu_t *tx_psfch_pdu = &tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu.psfch_pdu;
tx_psfch_pdu->start_symbol_index = mac_psfch_pdu->start_symbol_index;
tx_psfch_pdu->hopping_id = mac_psfch_pdu->hopping_id;
tx_psfch_pdu->prb = mac_psfch_pdu->prb;
tx_psfch_pdu->sl_bwp_start = mac_psfch_pdu->sl_bwp_start;
tx_psfch_pdu->initial_cyclic_shift = mac_psfch_pdu->initial_cyclic_shift;
tx_psfch_pdu->mcs = mac_psfch_pdu->mcs;
tx_psfch_pdu->freq_hop_flag = mac_psfch_pdu->freq_hop_flag;
tx_psfch_pdu->second_hop_prb = mac_psfch_pdu->second_hop_prb;
tx_psfch_pdu->group_hop_flag = mac_psfch_pdu->group_hop_flag;
tx_psfch_pdu->sequence_hop_flag = mac_psfch_pdu->sequence_hop_flag;
tx_psfch_pdu->nr_of_symbols = num_psfch_symbols ? num_psfch_symbols - 2 : 0; // (num_psfch_symbols - 2) excludes PSFCH AGC and Guard
AssertFatal(tx_psfch_pdu->nr_of_symbols >= 0, "Number of PSFCH symbols can not be negative!!!\n");
tx_psfch_pdu->bit_len_harq = mac_psfch_pdu->bit_len_harq;
}
void nr_ue_sl_csi_rs_scheduler(NR_UE_MAC_INST_t *mac,
uint8_t scs,
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
sl_nr_tx_config_request_t *tx_config,
sl_nr_rx_config_request_t *rx_config,
uint8_t *config_type) {
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
sl_nr_tti_csi_rs_pdu_t *csi_rs_pdu = NULL;
if (tx_config != NULL) {
csi_rs_pdu = &tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu.nr_sl_csi_rs_pdu;
tx_config->number_pdus = 1;
*config_type = SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS;
tx_config->tx_config_list[0].pdu_type = *config_type;
} else if (rx_config != NULL) {
csi_rs_pdu = &rx_config->sl_rx_config_list[0].rx_csi_rs_config_pdu;
rx_config->number_pdus = 1;
rx_config->sl_rx_config_list[0].pdu_type = SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_CSI_RS;
}
AssertFatal(csi_rs_pdu != NULL, "tx_config and rx_config both cannot be NULL\n");
fill_csi_rs_pdu(sl_mac, csi_rs_pdu, sl_bwp, scs);
}
void fill_csi_rs_pdu(sl_nr_ue_mac_params_t *sl_mac, sl_nr_tti_csi_rs_pdu_t *csi_rs_pdu, const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp, uint8_t scs) {
long* cyclicPrefix = sl_bwp->sl_BWP_Generic_r16->sl_BWP_r16->cyclicPrefix;
csi_rs_pdu->cyclic_prefix = cyclicPrefix == NULL ? 0 : *cyclicPrefix; // (0: normal; 1: Extended)
csi_rs_pdu->measurement_bitmap = sl_mac->measurement_bitmap;
csi_rs_pdu->subcarrier_spacing = scs;
csi_rs_pdu->start_rb = sl_mac->start_rb;
csi_rs_pdu->nr_of_rbs = sl_mac->nr_of_rbs;
csi_rs_pdu->csi_type = sl_mac->csi_type;
csi_rs_pdu->row = sl_mac->row;
csi_rs_pdu->freq_domain = sl_mac->freq_domain;
csi_rs_pdu->symb_l0 = sl_mac->symb_l0;
csi_rs_pdu->cdm_type = sl_mac->cdm_type;
csi_rs_pdu->freq_density = sl_mac->freq_density;
csi_rs_pdu->power_control_offset = sl_mac->power_control_offset;
csi_rs_pdu->power_control_offset_ss = sl_mac->power_control_offset_ss;
}

View File

@@ -0,0 +1,77 @@
/*
* 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 nr_ue_sci.h
* \brief Definitions and Structures for sci/slsch procedures for Sidelink UE
* \author R. Knopp
* \date 2023
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr
* \note
* \warning
*/
#ifndef __LAYER2_NR_UE_SCI_H__
#define __LAYER2_NR_UE_SCI_H__
#include "NR_MAC_COMMON/nr_mac.h"
typedef enum {
NR_SL_SCI_FORMAT_1A = 0,
NR_SL_SCI_FORMAT_2A = 1,
NR_SL_SCI_FORMAT_2B = 2,
NR_SL_SCI_FORMAT_2C = 3
} nr_sci_format_t;
typedef struct {
// 1st stage fields
uint8_t priority; // 3 bits
dci_field_t frequency_resource_assignment; // depending on sl-MaxNumPerReserve and N_subChannel^SL
dci_field_t time_resource_assignment; // depending on sl_MaxNumPerReserve
dci_field_t resource_reservation_period; // sl-ResourceReservePeriodList and sl-MultiReserveResource
dci_field_t dmrs_pattern; // depending on N_pattern and sl-PSSCH-DMRS-TimePatternList
uint8_t second_stage_sci_format; // 2 bits - Table 8.3.1.1-1
uint8_t beta_offset_indicator; // 2 bits - depending sl-BetaOffsets2ndSCI and Table 8.3.1.1-2
uint8_t number_of_dmrs_port; // 1 bit - Table 8.3.1.1-3
uint8_t mcs; // 5 bits
dci_field_t additional_mcs; // depending on sl-Additional-MCS-Table
dci_field_t psfch_overhead; // depending on sl-PSFCH-Period
dci_field_t reserved; // depending on N_reserved (sl-NumReservedBits) and sl-IndicationUE-B
dci_field_t conflict_information_receiver; // depending on sl-IndicationUE-B
// 2nd stage fields
uint8_t harq_pid; // 4 bits
uint8_t ndi; // 1 bit
uint8_t rv_index; // 2 bits
uint8_t source_id; // 8 bits
uint16_t dest_id; // 16 bits
uint8_t harq_feedback; //1 bit
uint8_t cast_type; // 2 bits formac 2A
uint8_t csi_req; // 1 bit format 2A, format 2C
uint16_t zone_id; // 12 bits format 2B
dci_field_t communication_range; // 4 bits depending on sl-ZoneConfigMCR-Index, format 2B
uint8_t providing_req_ind; // 1 bit, format 2C
dci_field_t resource_combinations; // depending on n_subChannel^SL (sl-NumSubchennel), N_rsv_period (sl-ResourceReservePeriodList) and sl-MultiReservedResource, format 2C
uint8_t first_resource_location; // 8 bits, format 2C
dci_field_t reference_slot_location; // depending on mu, format 2C
uint8_t resource_set_type; // 1 bit, format 2C
dci_field_t lowest_subchannel_indices; // depending on n_subChannel^SL, format 2C
} nr_sci_pdu_t;
#endif

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