SL PSBCH: MAC->PHY cfg, PSBCH scheduler + supporting functions + enable system testing & scope

- 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
	- Enable Scope for PSBCH use -d or --dqt
	- Enable system testing of PSBCH for example using RFSIMULATOR:

		- UE1 is a SYNCRONISATION SOURCE UE which transmits PSBCH

		  started using command -
		  sudo ./nr-uesoftmodem --sl-mode 2 --sync-ref 4 --rfsim --rfsimulator.serveraddr server

		- UE2 syncs onto UE1 during sidelink search, gets the timing and continues to receive PSBCH

		  started using command -
		  sudo ./nr-uesoftmodem --sl-mode 2 --rfsim --rfsimulator.serveraddr 127.0.0.1

		- In the default use case 2 Sidelink SSBs sent over 16 frames.

		- In case SL-SSB configuration needs to be changed use -O option in the above command like

		-O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sidelink_preconfig_1txpool.conf
This commit is contained in:
Raghavendra Dinavahi
2024-06-21 09:40:16 +02:00
parent 9fab212441
commit 798ceeeef2
42 changed files with 1409 additions and 318 deletions
+8 -5
View File
@@ -23,11 +23,9 @@
#include "NR_SidelinkPreconfigNR-r16.h"
#include "mac_proto.h"
void sl_ue_mac_free(uint8_t module_id)
void sl_ue_mac_free(NR_UE_MAC_INST_t *mac)
{
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;
@@ -372,6 +370,9 @@ int nr_rrc_mac_config_req_sl_preconfig(module_id_t module_id,
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->timing_acquired = true;
}
//Do not copy TDD config yet as SYNC source is not yet found
@@ -474,12 +475,13 @@ void nr_rrc_mac_config_req_sl_mib(module_id_t module_id,
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) {
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->timing_acquired = true;
sl_mac->rx_sl_bch.status = 1;
sl_mac->rx_sl_bch.slss_id = rx_slss_id;
@@ -524,7 +526,8 @@ void nr_rrc_mac_config_req_sl_mib(module_id_t module_id,
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);
}
}
+32
View File
@@ -32,6 +32,10 @@
#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
@@ -127,6 +131,13 @@ typedef struct sl_bch_params {
} sl_bch_params_t;
typedef struct sl_stored_tti_req {
uint32_t sl_action;
int frame;
int slot;
} sl_stored_tti_req_t;
typedef struct sl_nr_ue_mac_params {
//Holds the RX resource pool from RRC and its related parameters
@@ -151,6 +162,27 @@ typedef struct sl_nr_ue_mac_params {
//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.
bool timing_acquired;
// Sidelink slots per frame
uint16_t N_SL_SLOTS_perframe;
uint16_t decoded_DFN;
uint16_t decoded_slot;
uint32_t N_SL_SLOTS;
uint16_t N_SSB_16frames;
sl_stored_tti_req_t *future_ttis;
} sl_nr_ue_mac_params_t;
+21
View File
@@ -382,6 +382,7 @@ 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 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);
@@ -393,4 +394,24 @@ uint8_t sl_decode_sl_TDD_Config(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config,
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);
/** \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_slot, uint8_t frame_duplex_type);
void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_INST_t *mac);
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);
#endif
+27 -23
View File
@@ -19,7 +19,8 @@
* contact@openairinterface.org
*/
#include "mac_defs_sl.h"
#include "mac_defs.h"
#include "mac_proto.h"
#define SL_DEBUG
@@ -348,35 +349,37 @@ uint32_t sl_prepare_MIB(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config,
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);
//sl-NumSubchannel - Indicates the number of subchannels in the corresponding resource pool
//which consists of contiguous PRBs only.
uint16_t num_subch = (rpool->sl_NumSubchannel_r16) ? *rpool->sl_NumSubchannel_r16 : 0;
AssertFatal(num_subch,"NUM Subchannels cannot be 0. Resource Pool Configuration Error\n");
return num_subch;
}
uint16_t sl_get_subchannel_size(NR_SL_ResourcePool_r16_t *rpool)
{
uint16_t num_subch = sl_get_num_subch(rpool);
//sl-RB-Number - Indicates the number of PRBs in the corresponding resource pool.
//which consists of contiguous PRBs only.The remaining RB cannot be used
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;
uint16_t subch_size = 0;
subch_size = num_rbs/num_subch;
LOG_I(NR_MAC, "Subch_size:%d, numRBS:%d, num_subch:%d\n",
subch_size,num_rbs,num_subch);
return (num_subch);
return (subch_size);
}
//This function determines SCI 1A Len in bits based on the configuration in the resource pool.
@@ -474,10 +477,11 @@ uint8_t sl_determine_sci_1a_len(uint16_t *num_subchannels,
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,
sci_1a_len,
sci_1a->additional_mcs_table_indicator.nbits);
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 &&
@@ -0,0 +1,426 @@
/*
* 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"
static 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;
}
static uint8_t sl_get_elapsed_slots(uint32_t slot, uint32_t sl_slot_bitmap)
{
uint8_t elapsed_slots = 0;
for (int i = 0; i < slot; i++) {
if (sl_slot_bitmap & (1 << i))
elapsed_slots++;
}
return elapsed_slots;
}
static void sl_determine_slot_bitmap(sl_nr_ue_mac_params_t *sl_mac, int ue_id)
{
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, i, TDD);
if (slot_type == NR_SIDELINK_SLOT) {
sl_mac->N_SL_SLOTS_perframe += 1;
sl_mac->sl_slot_bitmap |= (1 << i);
}
}
sl_mac->future_ttis = calloc(num_slots_per_frame, sizeof(sl_stored_tti_req_t));
LOG_I(NR_MAC,
"[UE%d] SL-MAC: N_SL_SLOTS_perframe:%d, SL SLOT bitmap:%x\n",
ue_id,
sl_mac->N_SL_SLOTS_perframe,
sl_mac->sl_slot_bitmap);
}
/* 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.
*/
static uint32_t sl_determine_num_sidelink_slots(sl_nr_ue_mac_params_t *sl_mac, int ue_id, uint16_t *N_SSB_16frames)
{
uint32_t N_SSB_1024frames = 0;
uint32_t N_SL_SLOTS = 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(NR_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(NR_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);
// Determine total number of Valid Sidelink slots which can be used for Respool in a SFN cycle (1024 frames)
N_SL_SLOTS = (sl_mac->N_SL_SLOTS_perframe * SL_FRAME_NUMBER_CYCLE) - N_SSB_1024frames;
LOG_I(NR_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",
ue_id,
N_SSB_1024frames,
sl_mac->N_SL_SLOTS_perframe,
N_SL_SLOTS,
sl_mac->sl_slot_bitmap);
return N_SL_SLOTS;
}
/**
* 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)
{
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;
#ifdef SL_DEBUG
LOG_D(NR_MAC,
"%d:%d. num_ssb:%d,ssb_slot:%d, %d-%d-%d, status:%d\n",
frame,
slot,
sl_bch->num_ssb,
sl_bch->ssb_slot,
sl_NumSSB_WithinPeriod,
sl_TimeOffsetSSB,
sl_TimeInterval,
sl_bch->status);
#endif
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;
sl_bch->ssb_slot = ssb_slot;
sl_bch->num_ssb = num_ssb;
LOG_D(NR_MAC, "%d:%d is a PSBCH SLOT. Next PSBCH Slot:%d, num_ssb:%d\n", frame, slot, 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;
}
static uint8_t sl_psbch_scheduler(sl_nr_ue_mac_params_t *sl_mac_params, int ue_id, int frame, int slot)
{
uint8_t config_type = 0, is_psbch_rx_slot = 0, is_psbch_tx_slot = 0;
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];
if (sl_mac_params->rx_sl_bch.status) {
is_psbch_rx_slot = sl_determine_if_SSB_slot(frame, slot, slots_per_frame, &sl_mac_params->rx_sl_bch);
if (is_psbch_rx_slot)
config_type = SL_NR_CONFIG_TYPE_RX_PSBCH;
} else if (sl_mac_params->tx_sl_bch.status) {
is_psbch_tx_slot = sl_determine_if_SSB_slot(frame, slot, slots_per_frame, &sl_mac_params->tx_sl_bch);
if (is_psbch_tx_slot)
config_type = SL_NR_CONFIG_TYPE_TX_PSBCH;
}
sl_mac_params->future_ttis[slot].frame = frame;
sl_mac_params->future_ttis[slot].slot = slot;
sl_mac_params->future_ttis[slot].sl_action = config_type;
LOG_D(NR_MAC, "[UE%d] SL-PSBCH SCHEDULER: %d:%d, config type:%d\n", ue_id, frame, slot, config_type);
return config_type;
}
/*
* 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
*/
static void sl_adjust_indices_based_on_timing(sl_nr_ue_mac_params_t *sl_mac,
int ue_id,
int frame, int slot,
int slots_per_frame)
{
uint8_t elapsed_slots = 0;
elapsed_slots = sl_get_elapsed_slots(slot, sl_mac->sl_slot_bitmap);
AssertFatal(elapsed_slots <= sl_mac->N_SL_SLOTS_perframe,
"Elapsed slots cannot be > N_SL_SLOTS_perframe %d,%d\n",
elapsed_slots,
sl_mac->N_SL_SLOTS_perframe);
uint16_t frame_16 = frame % SL_NR_SSB_REPETITION_IN_FRAMES;
uint32_t slot_in_16frames = (frame_16 * slots_per_frame) + slot;
LOG_I(NR_MAC,
"[UE%d]PSBCH params adjusted based on current timing %d:%d. frame_16:%d, slot_in_16frames:%d\n",
ue_id,
frame,
slot,
frame_16,
slot_in_16frames);
// Adjust PSBCH Indices based on current timing
if (sl_mac->rx_sl_bch.status) {
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);
LOG_I(NR_MAC,
"[UE%d]PSBCH RX params adjusted. NumSSB:%d, ssb_slot:%d\n",
ue_id,
sl_mac->rx_sl_bch.num_ssb,
sl_mac->rx_sl_bch.ssb_slot);
}
if (sl_mac->tx_sl_bch.status) {
sl_ssb_timealloc_t *ssb_timealloc = &sl_mac->tx_sl_bch.ssb_time_alloc;
sl_mac->tx_sl_bch.num_ssb = sl_adjust_ssb_indices(ssb_timealloc, slot_in_16frames, &sl_mac->tx_sl_bch.ssb_slot);
LOG_I(NR_MAC,
"[UE%d]PSBCH TX params adjusted. NumSSB:%d, ssb_slot:%d\n",
ue_id,
sl_mac->tx_sl_bch.num_ssb,
sl_mac->tx_sl_bch.ssb_slot);
}
}
// Adjust indices as new timing is acquired
static void sl_actions_after_new_timing(sl_nr_ue_mac_params_t *sl_mac,
int ue_id,
int frame, int slot)
{
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];
sl_determine_slot_bitmap(sl_mac, ue_id);
sl_mac->N_SL_SLOTS = sl_determine_num_sidelink_slots(sl_mac, ue_id, &sl_mac->N_SSB_16frames);
sl_adjust_indices_based_on_timing(sl_mac, ue_id, frame, slot, slots_per_frame);
}
static void sl_schedule_rx_actions(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_INST_t *mac)
{
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
int ue_id = mac->ue_id;
int rx_action = 0;
sl_nr_rx_config_request_t rx_config;
rx_config.number_pdus = 0;
rx_config.sfn = sl_ind->frame_rx;
rx_config.slot = sl_ind->slot_rx;
if (sl_ind->sci_ind != NULL) {
// TBD..
} else {
rx_action = sl_mac->future_ttis[sl_ind->slot_rx].sl_action;
}
if (rx_action == SL_NR_CONFIG_TYPE_RX_PSBCH) {
rx_config.number_pdus = 1;
rx_config.sl_rx_config_list[0].pdu_type = rx_action;
LOG_I(NR_MAC, "[UE%d] %d:%d CMD to PHY: RX PSBCH \n", ue_id, sl_ind->frame_rx, sl_ind->slot_rx);
} else if (rx_action >= SL_NR_CONFIG_TYPE_RX_PSCCH && rx_action <= SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH) {
// TBD..
} else if (rx_action == SL_NR_CONFIG_TYPE_RX_PSFCH) {
// TBD..
}
if (rx_config.number_pdus) {
AssertFatal(sl_ind->slot_type == SIDELINK_SLOT_TYPE_RX || sl_ind->slot_type == SIDELINK_SLOT_TYPE_BOTH,
"RX action cannot be scheduled in non Sidelink RX slot\n");
nr_scheduled_response_t scheduled_response = {.sl_rx_config = &rx_config,
.module_id = sl_ind->module_id,
.CC_id = sl_ind->cc_id,
.phy_data = sl_ind->phy_data,
.mac = mac};
sl_mac->future_ttis[sl_ind->slot_rx].sl_action = 0;
if ((mac->if_module != NULL) && (mac->if_module->scheduled_response != NULL))
mac->if_module->scheduled_response(&scheduled_response);
}
}
static void sl_schedule_tx_actions(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_INST_t *mac)
{
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
int ue_id = mac->ue_id;
int tx_action = 0;
sl_nr_tx_config_request_t tx_config;
tx_config.number_pdus = 0;
tx_config.sfn = sl_ind->frame_tx;
tx_config.slot = sl_ind->slot_tx;
tx_action = sl_mac->future_ttis[sl_ind->slot_tx].sl_action;
if (tx_action == SL_NR_CONFIG_TYPE_TX_PSBCH) {
tx_config.number_pdus = 1;
tx_config.tx_config_list[0].pdu_type = tx_action;
tx_config.tx_config_list[0].tx_psbch_config_pdu.tx_slss_id = sl_mac->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->tx_sl_bch.sl_mib, 4);
LOG_I(NR_MAC, "[UE%d] %d:%d CMD to PHY: TX PSBCH \n", ue_id, sl_ind->frame_tx, sl_ind->slot_tx);
} else if (tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH) {
// TBD....
} else if (tx_action == SL_NR_CONFIG_TYPE_TX_PSFCH) {
// TBD....
}
if (tx_config.number_pdus == 1) {
AssertFatal(sl_ind->slot_type == SIDELINK_SLOT_TYPE_TX || sl_ind->slot_type == SIDELINK_SLOT_TYPE_BOTH,
"TX action cannot be scheduled in non Sidelink TX slot\n");
nr_scheduled_response_t scheduled_response = {.sl_tx_config = &tx_config,
.module_id = sl_ind->module_id,
.CC_id = sl_ind->cc_id,
.phy_data = sl_ind->phy_data,
.mac = mac};
sl_mac->future_ttis[sl_ind->slot_tx].sl_action = 0;
if ((mac->if_module != NULL) && (mac->if_module->scheduled_response != NULL))
mac->if_module->scheduled_response(&scheduled_response);
}
}
void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_INST_t *mac)
{
AssertFatal(sl_ind != NULL, "sl_indication cannot be NULL\n");
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
int ue_id = mac->ue_id;
LOG_D(NR_MAC,
"[UE%d]SL-SCHEDULER: RX %d-%d- TX %d-%d. slot_type:%d\n",
ue_id,
sl_ind->frame_rx,
sl_ind->slot_rx,
sl_ind->frame_tx,
sl_ind->slot_tx,
sl_ind->slot_type);
// Adjust indices as new timing is acquired
if (sl_mac->timing_acquired) {
sl_actions_after_new_timing(sl_mac, ue_id, sl_ind->frame_tx, sl_ind->slot_tx);
sl_mac->timing_acquired = false;
}
if (sl_ind->slot_type == SIDELINK_SLOT_TYPE_TX || sl_ind->slot_type == SIDELINK_SLOT_TYPE_BOTH) {
int frame = sl_ind->frame_tx;
int slot = sl_ind->slot_tx;
int is_sl_slot = 0;
is_sl_slot = sl_mac->sl_slot_bitmap & (1 << slot);
if (is_sl_slot) {
uint8_t tti_action = 0;
// Check if PSBCH slot and PSBCH should be transmitted or Received
tti_action = sl_psbch_scheduler(sl_mac, ue_id, frame, slot);
#if 0 // To be expanded later
// TBD .. Check for Actions coming out of TX resource pool
if (!tti_action && sl_mac->sl_TxPool[0])
tti_action = sl_tx_scheduler(ue_id, frame, slot, sl_mac, sl_mac->sl_TxPool[0]);
//TBD .. Check for Actions coming out of RX resource pool
if (!tti_action && sl_mac->sl_RxPool[0])
tti_action = sl_rx_scheduler(ue_id, frame, slot, sl_mac, sl_mac->sl_RxPool[0]);
#endif
LOG_D(NR_MAC, "[UE%d]SL-SCHED: TTI - %d:%d scheduled action:%d\n", ue_id, frame, slot, tti_action);
} else {
AssertFatal(1 == 0, "TX SLOT not a sidelink slot. Should not occur\n");
}
// Schedule the Tx actions if any
sl_schedule_tx_actions(sl_ind, mac);
}
if (sl_ind->slot_type == SIDELINK_SLOT_TYPE_RX || sl_ind->slot_type == SIDELINK_SLOT_TYPE_BOTH)
sl_schedule_rx_actions(sl_ind, mac);
}