Merge remote-tracking branch 'origin/NR_PSBCH_MERGE2' into integration_2024_w06
This commit is contained in:
@@ -1384,9 +1384,11 @@ 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
|
||||
|
||||
@@ -987,6 +987,8 @@ void init_NR_UE(int nb_inst, char *uecap_file, char *reconfig_file, char *rbconf
|
||||
init_nsa_message(rrc_inst, reconfig_file, rbconfig_file);
|
||||
nr_rlc_activate_srb0(mac_inst->crnti, NULL, send_srb0_rrc);
|
||||
}
|
||||
//TODO: Move this call to RRC
|
||||
start_sidelink((&rrc_inst[i])->ue_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -106,11 +106,9 @@ extern "C"
|
||||
#define CONFIG_L1_EMULATOR "Run in L1 emulated mode (disable PHY layer)\n"
|
||||
#define CONFIG_HLP_CONTINUOUS_TX "perform continuous transmission, even in TDD mode (to work around USRP issues)\n"
|
||||
#define CONFIG_HLP_STATS_DISABLE "disable globally the stats generation and persistence"
|
||||
#define CONFIG_HLP_SYNC_REF "Sync Reference in Sidelink\n"
|
||||
#define CONFIG_HLP_NID1 "Set NID1 value in Sidelink\n"
|
||||
#define CONFIG_HLP_NID2 "Set NID2 value in Sidelink\n"
|
||||
#define CONFIG_HLP_NOITTI "Do not start itti threads, call queue processing in place, inside the caller thread"
|
||||
#define CONFIG_HLP_LDPC_OFFLOAD "Enable LDPC offload to AMD Xilinx T2 telco card\n"
|
||||
#define CONFIG_HLP_SYNC_REF "UE acts a Sync Reference in Sidelink. 0-none 1-GNB 2-GNSS 4-localtiming\n"
|
||||
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* command line parameters common to eNodeB and UE */
|
||||
@@ -143,8 +141,6 @@ extern "C"
|
||||
#define EMULATE_L1 softmodem_params.emulate_l1
|
||||
#define CONTINUOUS_TX softmodem_params.continuous_tx
|
||||
#define SYNC_REF softmodem_params.sync_ref
|
||||
#define NID1 softmodem_params.nid1
|
||||
#define NID2 softmodem_params.nid2
|
||||
#define LDPC_OFFLOAD_FLAG softmodem_params.ldpc_offload_flag
|
||||
|
||||
#define REORDER_THREAD_DISABLE softmodem_params.reorder_thread_disable
|
||||
@@ -191,10 +187,9 @@ extern int usrp_tx_thread;
|
||||
{"emulate-l1", CONFIG_L1_EMULATOR, PARAMFLAG_BOOL, .iptr=&EMULATE_L1, .defintval=0, TYPE_INT, 0}, \
|
||||
{"continuous-tx", CONFIG_HLP_CONTINUOUS_TX, PARAMFLAG_BOOL, .iptr=&CONTINUOUS_TX, .defintval=0, TYPE_INT, 0}, \
|
||||
{"disable-stats", CONFIG_HLP_STATS_DISABLE, PARAMFLAG_BOOL, .iptr=&stats_disabled, .defintval=0, TYPE_INT, 0}, \
|
||||
{"nid1", CONFIG_HLP_NID1, 0, .iptr=&NID1, .defintval=10, TYPE_INT, 0}, \
|
||||
{"nid2", CONFIG_HLP_NID2, 0, .iptr=&NID2, .defintval=1, TYPE_INT, 0}, \
|
||||
{"no-itti-threads", CONFIG_HLP_NOITTI, PARAMFLAG_BOOL, .iptr=&softmodem_params.no_itti, .defintval=0, TYPE_INT, 0}, \
|
||||
{"ldpc-offload-enable", CONFIG_HLP_LDPC_OFFLOAD, PARAMFLAG_BOOL, .iptr=&LDPC_OFFLOAD_FLAG, .defstrval=0, TYPE_INT, 0}, \
|
||||
{"sync-ref", CONFIG_HLP_SYNC_REF, 0, .uptr=&SYNC_REF, .defintval=0, TYPE_UINT, 0}, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
@@ -353,9 +348,7 @@ typedef struct {
|
||||
int non_stop;
|
||||
int emulate_l1;
|
||||
int continuous_tx;
|
||||
int sync_ref;
|
||||
int nid1;
|
||||
int nid2;
|
||||
uint32_t sync_ref;
|
||||
int no_itti;
|
||||
int ldpc_offload_flag;
|
||||
} softmodem_params_t;
|
||||
|
||||
@@ -351,7 +351,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 +363,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;
|
||||
|
||||
|
||||
@@ -57,4 +57,5 @@ MESSAGE_DEF(RRC_MAC_DRX_CONFIG_REQ, MESSAGE_PRIORITY_MED, rrc_mac_drx_config_req
|
||||
// gNB
|
||||
MESSAGE_DEF(NR_RRC_MAC_CCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacCcchDataInd, nr_rrc_mac_ccch_data_ind)
|
||||
MESSAGE_DEF(NR_RRC_MAC_BCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacBcchDataInd, nr_rrc_mac_bcch_data_ind)
|
||||
MESSAGE_DEF(NR_RRC_MAC_SBCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacSBcchDataInd, nr_rrc_mac_sbcch_data_ind)
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#define RRC_MAC_BCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_data_req
|
||||
#define RRC_MAC_BCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_data_ind
|
||||
#define NR_RRC_MAC_BCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_bcch_data_ind
|
||||
#define NR_RRC_MAC_SBCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_sbcch_data_ind
|
||||
|
||||
#define RRC_MAC_BCCH_MBMS_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_mbms_data_req
|
||||
#define RRC_MAC_BCCH_MBMS_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_mbms_data_ind
|
||||
@@ -119,6 +120,17 @@ typedef struct NRRrcMacBcchDataInd_s {
|
||||
uint8_t rsrp;
|
||||
} NRRrcMacBcchDataInd;
|
||||
|
||||
typedef struct NRRrcMacSBcchDataInd_s {
|
||||
uint32_t frame;
|
||||
uint8_t slot;
|
||||
uint32_t sdu_size;
|
||||
uint8_t sdu[BCCH_SDU_SIZE];
|
||||
uint8_t gnb_index;
|
||||
uint16_t rx_slss_id;
|
||||
uint8_t rsrq;
|
||||
uint8_t rsrp;
|
||||
} NRRrcMacSBcchDataInd;
|
||||
|
||||
typedef struct RrcMacBcchMbmsDataReq_s {
|
||||
uint32_t frame;
|
||||
uint32_t sdu_size;
|
||||
|
||||
@@ -0,0 +1,533 @@
|
||||
/*
|
||||
* 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 "NR_SidelinkPreconfigNR-r16.h"
|
||||
#include "mac_proto.h"
|
||||
|
||||
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) {
|
||||
ASN_STRUCT_FREE (asn_DEF_NR_TDD_UL_DL_Pattern, mac->SL_MAC_PARAMS->sl_TDD_config);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void sl_set_tdd_config_nr_ue(fapi_nr_tdd_table_t *tdd_table,
|
||||
int mu,
|
||||
NR_TDD_UL_DL_Pattern_t *pattern)
|
||||
{
|
||||
const int nrofUplinkSlots = pattern->nrofUplinkSlots;
|
||||
const int nrofUplinkSymbols = pattern->nrofUplinkSymbols;
|
||||
const int nb_periods_per_frame = get_nb_periods_per_frame(pattern->dl_UL_TransmissionPeriodicity);
|
||||
const int nb_slots_per_period = ((1 << mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME) / nb_periods_per_frame;
|
||||
tdd_table->tdd_period_in_slots = nb_slots_per_period;
|
||||
|
||||
LOG_I(PHY,"UL slots:%d, symbols:%d, slots_per_period:%d\n",
|
||||
nrofUplinkSlots, nrofUplinkSymbols, nb_slots_per_period);
|
||||
|
||||
tdd_table->max_tdd_periodicity_list = (fapi_nr_max_tdd_periodicity_t *) malloc(nb_slots_per_period * sizeof(fapi_nr_max_tdd_periodicity_t));
|
||||
|
||||
for(int memory_alloc = 0 ; memory_alloc < nb_slots_per_period; memory_alloc++)
|
||||
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));
|
||||
|
||||
int slot_number = (nb_slots_per_period - nrofUplinkSlots) - (nrofUplinkSymbols ? 1 : 0);
|
||||
if (nrofUplinkSymbols != 0) {
|
||||
for(int number_of_symbol = NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofUplinkSymbols; number_of_symbol < NR_NUMBER_OF_SYMBOLS_PER_SLOT; number_of_symbol++) {
|
||||
tdd_table->max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol].slot_config = 1;
|
||||
}
|
||||
slot_number++;
|
||||
}
|
||||
while(slot_number < nb_slots_per_period) {
|
||||
for (int number_of_symbol = 0; number_of_symbol < nrofUplinkSlots * NR_NUMBER_OF_SYMBOLS_PER_SLOT; number_of_symbol++) {
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//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)
|
||||
{
|
||||
|
||||
|
||||
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;
|
||||
//REL 16 3GPP spec 38.101 section 5.2E.1 specifies 2 bands for operation on PC5 interface.
|
||||
//Band 47, Band 38
|
||||
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);
|
||||
|
||||
//FREQSHIFT_7P5KHZ is DISABLED
|
||||
phycfg->sl_carrier_config.sl_frequency_shift_7p5khz = 0;
|
||||
phycfg->sl_carrier_config.sl_value_N = freqcfg->valueN_r16;
|
||||
|
||||
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); // 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
|
||||
sl_set_tdd_config_nr_ue(&phycfg->tdd_table,
|
||||
phycfg->sl_bwp_config.sl_scs,
|
||||
&sl_TDD_config->pattern1);
|
||||
|
||||
LOG_I(NR_MAC, "SIDELINK CONFIGs: tdd config period:%ld, mu:%ld, DLslots:%ld,ULslots:%ld Mixedslotsym DL:UL %ld:%ld\n",
|
||||
sl_TDD_config->pattern1.dl_UL_TransmissionPeriodicity, 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, 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_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)
|
||||
{
|
||||
|
||||
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);
|
||||
AssertFatal(sl_preconfiguration !=NULL,"SL-Preconfig Cannot be NULL");
|
||||
AssertFatal(mac, "mac should have an instance");
|
||||
|
||||
if (!mac->SL_MAC_PARAMS)
|
||||
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;
|
||||
|
||||
//Indicates if CSI Reporting is enabled in UNICAST. is 0-ENABLED, 1-DISABLED
|
||||
sl_mac->sl_CSI_Acquisition = (sl_preconfig->sl_CSI_Acquisition_r16) ? 0 : 1;
|
||||
|
||||
//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];
|
||||
|
||||
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));
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
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->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_mac->sl_TDD_config->pattern1.nrofUplinkSlots =
|
||||
NR_NUMBER_OF_SUBFRAMES_PER_FRAME*(1<<cfg->sl_bwp_config.sl_scs);
|
||||
}
|
||||
|
||||
sl_set_tdd_config_nr_ue(&cfg->tdd_table,
|
||||
cfg->sl_bwp_config.sl_scs,
|
||||
&sl_mac->sl_TDD_config->pattern1);
|
||||
LOG_I(MAC, "SIDELINK CONFIGs: tdd config period:%ld, mu:%ld, DLslots:%ld,ULslots:%ld Mixedslotsym DL:UL %ld:%ld\n",
|
||||
sl_mac->sl_TDD_config->pattern1.dl_UL_TransmissionPeriodicity,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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h"
|
||||
#include "LAYER2/MAC/mac.h"
|
||||
#include "NR_MAC_COMMON/nr_mac_extern.h"
|
||||
#include "mac_defs_sl.h"
|
||||
|
||||
/* RRC */
|
||||
#include "NR_DRX-Config.h"
|
||||
@@ -543,6 +544,9 @@ typedef struct NR_UE_MAC_INST_s {
|
||||
|
||||
pthread_mutex_t mutex_dl_info;
|
||||
|
||||
//SIDELINK MAC PARAMETERS
|
||||
sl_nr_ue_mac_params_t *SL_MAC_PARAMS;
|
||||
|
||||
} NR_UE_MAC_INST_t;
|
||||
|
||||
/*@}*/
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
#define SL_NR_MAC_NUM_RX_RESOURCE_POOLS 1
|
||||
#define SL_NR_MAC_NUM_TX_RESOURCE_POOLS 1
|
||||
#define SL_NUM_BYTES_TIMERESOURCEBITMAP 20
|
||||
|
||||
// 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 NR_SBCCH_SL_BCH 0xFF
|
||||
|
||||
#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;
|
||||
|
||||
//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;
|
||||
|
||||
} sl_nr_ue_mac_params_t;
|
||||
|
||||
|
||||
#endif
|
||||
@@ -515,4 +515,28 @@ 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);
|
||||
|
||||
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 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);
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,524 @@
|
||||
/*
|
||||
* 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_sl.h"
|
||||
|
||||
#define SL_DEBUG
|
||||
|
||||
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,
|
||||
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;
|
||||
}
|
||||
@@ -94,6 +94,32 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id,
|
||||
AssertFatal(false, "use RLC instead\n");
|
||||
break;
|
||||
|
||||
case NR_SBCCH_SL_BCH:
|
||||
if (pdu_len>0) {
|
||||
LOG_T(NR_RRC, "[UE %d] Received SL-MIB for NR_SBCCH_SL_BCH.\n", module_id);
|
||||
|
||||
MessageDef *message_p;
|
||||
int msg_sdu_size = BCCH_SDU_SIZE;
|
||||
|
||||
if (pdu_len > msg_sdu_size) {
|
||||
LOG_E(NR_RRC, "SDU larger than NR_SBCCH_SL_BCH SDU buffer size (%d, %d)", sdu_size, msg_sdu_size);
|
||||
sdu_size = msg_sdu_size;
|
||||
} else {
|
||||
sdu_size = pdu_len;
|
||||
}
|
||||
|
||||
message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_SBCCH_DATA_IND);
|
||||
memset(NR_RRC_MAC_SBCCH_DATA_IND (message_p).sdu, 0, BCCH_SDU_SIZE);
|
||||
memcpy(NR_RRC_MAC_SBCCH_DATA_IND (message_p).sdu, pduP, sdu_size);
|
||||
NR_RRC_MAC_SBCCH_DATA_IND (message_p).frame = frame; //frameP
|
||||
NR_RRC_MAC_SBCCH_DATA_IND (message_p).slot = slot;
|
||||
NR_RRC_MAC_SBCCH_DATA_IND (message_p).sdu_size = sdu_size;
|
||||
NR_RRC_MAC_SBCCH_DATA_IND (message_p).gnb_index = gNB_index;
|
||||
NR_RRC_MAC_SBCCH_DATA_IND (message_p).rx_slss_id = rnti;//rx_slss_id is rnti
|
||||
itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(module_id), message_p);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -324,10 +324,8 @@ NR_UE_RRC_INST_t* nr_rrc_init_ue(char* uecap_file, int nb_inst)
|
||||
// SRB0 activated by default
|
||||
ptr->Srb[0] = RB_ESTABLISHED;
|
||||
}
|
||||
}
|
||||
|
||||
if (get_softmodem_params()->sl_mode) {
|
||||
configure_NR_SL_Preconfig(get_softmodem_params()->sync_ref);
|
||||
init_sidelink(rrc);
|
||||
}
|
||||
|
||||
return NR_UE_rrc_inst;
|
||||
@@ -1437,6 +1435,14 @@ void *rrc_nrue(void *notUsed)
|
||||
nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(rrc, bcch->gnb_index, bcch->sdu, bcch->sdu_size, bcch->rsrq, bcch->rsrp);
|
||||
break;
|
||||
|
||||
case NR_RRC_MAC_SBCCH_DATA_IND:
|
||||
LOG_D(NR_RRC, "[UE %ld] Received %s: gNB %d\n", instance, ITTI_MSG_NAME(msg_p), NR_RRC_MAC_SBCCH_DATA_IND(msg_p).gnb_index);
|
||||
NRRrcMacSBcchDataInd *sbcch = &NR_RRC_MAC_SBCCH_DATA_IND(msg_p);
|
||||
|
||||
nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(rrc, sbcch->gnb_index,sbcch->frame, sbcch->slot, sbcch->sdu,
|
||||
sbcch->sdu_size, sbcch->rx_slss_id);
|
||||
break;
|
||||
|
||||
case NR_RRC_MAC_CCCH_DATA_IND: {
|
||||
NRRrcMacCcchDataInd *ind = &NR_RRC_MAC_CCCH_DATA_IND(msg_p);
|
||||
nr_rrc_ue_decode_ccch(rrc, ind, 0);
|
||||
@@ -1921,3 +1927,17 @@ void handle_t300_expiry(NR_UE_RRC_INST_t *rrc)
|
||||
// TODO handle connEstFailureControl
|
||||
// TODO inform upper layers about the failure to establish the RRC connection
|
||||
}
|
||||
|
||||
//This calls the sidelink preconf message after RRC, MAC instances are created.
|
||||
void start_sidelink(int instance)
|
||||
{
|
||||
|
||||
NR_UE_RRC_INST_t *rrc = &NR_UE_rrc_inst[instance];
|
||||
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
|
||||
//Process the Sidelink Preconfiguration
|
||||
rrc_ue_process_sidelink_Preconfiguration(rrc, get_softmodem_params()->sync_ref);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,8 @@
|
||||
#include "NR_DL-DCCH-Message.h"
|
||||
#include "NR_SystemInformation.h"
|
||||
#include "NR_UE-NR-Capability.h"
|
||||
#include "NR_SL-PreconfigurationNR-r16.h"
|
||||
#include "NR_MasterInformationBlockSidelink.h"
|
||||
|
||||
#include "RRC/NR/nr_rrc_common.h"
|
||||
#include "as_message.h"
|
||||
@@ -210,6 +212,10 @@ typedef struct NR_UE_RRC_INST_s {
|
||||
long selected_plmn_identity;
|
||||
Rrc_State_NR_t nrRrcState;
|
||||
as_nas_info_t initialNasMsg;
|
||||
|
||||
//Sidelink params
|
||||
NR_SL_PreconfigurationNR_r16_t *sl_preconfig;
|
||||
|
||||
} NR_UE_RRC_INST_t;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -121,7 +121,20 @@ void handle_rlf_sync(NR_UE_Timers_Constants_t *tac, nr_sync_msg_t sync_msg);
|
||||
void nr_rrc_handle_SetupRelease_RLF_TimersAndConstants(NR_UE_RRC_INST_t *rrc,
|
||||
struct NR_SetupRelease_RLF_TimersAndConstants *rlf_TimersAndConstants);
|
||||
|
||||
int configure_NR_SL_Preconfig(int sync_source);
|
||||
int configure_NR_SL_Preconfig(NR_UE_RRC_INST_t *rrc,int sync_source);
|
||||
|
||||
void init_sidelink(NR_UE_RRC_INST_t *rrc);
|
||||
void start_sidelink(int instance);
|
||||
|
||||
void rrc_ue_process_sidelink_Preconfiguration(NR_UE_RRC_INST_t *rrc_inst, int sync_ref);
|
||||
|
||||
void nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(NR_UE_RRC_INST_t *rrc,
|
||||
const uint8_t gNB_index,
|
||||
const frame_t frame,
|
||||
const int slot,
|
||||
uint8_t* pduP,
|
||||
const sdu_size_t pdu_len,
|
||||
const uint16_t rx_slss_id);
|
||||
|
||||
/** @}*/
|
||||
#endif
|
||||
|
||||
@@ -27,6 +27,17 @@
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "sl_preconfig_paramvalues.h"
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "rrc_defs.h"
|
||||
#include "LAYER2/NR_MAC_UE/mac_proto.h"
|
||||
#include "nr-uesoftmodem.h"
|
||||
|
||||
void free_sl_rrc(NR_UE_RRC_INST_t *rrc)
|
||||
{
|
||||
|
||||
if (rrc->sl_preconfig) {
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SL_PreconfigurationNR_r16, rrc->sl_preconfig);
|
||||
}
|
||||
}
|
||||
|
||||
static void prepare_NR_SL_SyncConfig(NR_SL_SyncConfig_r16_t *sl_syncconfig)
|
||||
{
|
||||
@@ -399,8 +410,7 @@ NR_SL_PreconfigurationNR_r16_t *prepare_NR_SL_PRECONFIGURATION(uint16_t num_tx_p
|
||||
return sl_preconfiguration;
|
||||
}
|
||||
|
||||
|
||||
int configure_NR_SL_Preconfig(int sync_source)
|
||||
int configure_NR_SL_Preconfig(NR_UE_RRC_INST_t *rrc,int sync_source)
|
||||
{
|
||||
|
||||
NR_SL_PreconfigurationNR_r16_t *sl_preconfig = NULL;
|
||||
@@ -424,9 +434,136 @@ int configure_NR_SL_Preconfig(int sync_source)
|
||||
}
|
||||
}
|
||||
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SL_PreconfigurationNR_r16, sl_preconfig);
|
||||
sl_preconfig = NULL;
|
||||
//END.......
|
||||
rrc->sl_preconfig = sl_preconfig;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*decode SL-BCH (SL-MIB) message*/
|
||||
static int8_t nr_sl_rrc_ue_decode_SL_MIB(const uint8_t gNB_index,
|
||||
uint8_t *const bufferP,
|
||||
const uint8_t buffer_len)
|
||||
{
|
||||
NR_MasterInformationBlockSidelink_t *sl_mib = NULL;
|
||||
|
||||
asn_dec_rval_t dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_MasterInformationBlockSidelink,
|
||||
(void **)&sl_mib,
|
||||
(const void *)bufferP, buffer_len);
|
||||
|
||||
int ret = 0;
|
||||
if ((dec_rval.code != RC_OK) || (dec_rval.consumed == 0)) {
|
||||
LOG_E(NR_RRC, "SL-MIB decode error\n");
|
||||
ret = -1;
|
||||
} else {
|
||||
|
||||
int bits_unused = sl_mib->directFrameNumber_r16.bits_unused;
|
||||
uint16_t val_fn = sl_mib->directFrameNumber_r16.buf[0];
|
||||
val_fn = (val_fn << (8 - bits_unused)) + (sl_mib->directFrameNumber_r16.buf[1] >> bits_unused);
|
||||
|
||||
uint8_t val_slot = sl_mib->slotIndex_r16.buf[0];
|
||||
|
||||
LOG_D(NR_RRC, "SL-RRC - Received MIB\n");
|
||||
LOG_D(NR_RRC, "SL-MIB Contents - DFN:%d\n" , val_fn);
|
||||
LOG_D(NR_RRC, "SL-MIB Contents - SLOT:%d\n" , val_slot >> 1);
|
||||
LOG_D(NR_RRC, "SL-MIB Contents - Incoverage:%d\n", sl_mib->inCoverage_r16);
|
||||
LOG_D(NR_RRC, "SL-MIB Contents - sl-TDD-Config:%x\n" , *((uint16_t *)(sl_mib->sl_TDD_Config_r16.buf)));
|
||||
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_MasterInformationBlockSidelink, sl_mib);
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(NR_UE_RRC_INST_t *rrc,
|
||||
const uint8_t gNB_index,
|
||||
const frame_t frame,
|
||||
const int slot,
|
||||
uint8_t* pduP,
|
||||
const sdu_size_t pdu_len,
|
||||
const uint16_t rx_slss_id)
|
||||
{
|
||||
|
||||
nr_sl_rrc_ue_decode_SL_MIB(gNB_index, (uint8_t*)pduP, pdu_len);
|
||||
|
||||
DevAssert(rrc->sl_preconfig);
|
||||
|
||||
NR_SL_FreqConfigCommon_r16_t *fcfg = NULL;
|
||||
if (rrc->sl_preconfig->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16)
|
||||
fcfg = rrc->sl_preconfig->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16->list.array[0];
|
||||
DevAssert(fcfg);
|
||||
|
||||
NR_SL_SSB_TimeAllocation_r16_t *sl_SSB_TimeAllocation = NULL;
|
||||
|
||||
//Current implementation only supports one SSB Timeallocation
|
||||
//Extend RRC to use multiple SSB Time allocations TBD....
|
||||
if (fcfg->sl_SyncConfigList_r16)
|
||||
sl_SSB_TimeAllocation = fcfg->sl_SyncConfigList_r16->list.array[0]->sl_SSB_TimeAllocation1_r16;
|
||||
DevAssert(sl_SSB_TimeAllocation);
|
||||
|
||||
nr_rrc_mac_config_req_sl_mib(rrc->ue_id,
|
||||
sl_SSB_TimeAllocation,
|
||||
rx_slss_id,
|
||||
pduP);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void rrc_ue_process_sidelink_Preconfiguration(NR_UE_RRC_INST_t *rrc_inst,
|
||||
sl_sync_source_enum_t sync_source)
|
||||
{
|
||||
|
||||
AssertFatal(rrc_inst, "RRC instance not created.\n");
|
||||
|
||||
NR_SL_PreconfigurationNR_r16_t *sl_preconfig = rrc_inst->sl_preconfig;
|
||||
AssertFatal(rrc_inst->sl_preconfig, "Check if SL-preconfig was created");
|
||||
|
||||
AssertFatal(sync_source != SL_SYNC_SOURCE_GNBENB, "Sync source GNB not supported\n");
|
||||
|
||||
nr_rrc_mac_config_req_sl_preconfig(rrc_inst->ue_id, sl_preconfig, sync_source);
|
||||
|
||||
//TBD.. These should be chosen by RRC according to 3GPP 38.331 RRC specification.
|
||||
//Currently hardcoding the values to these
|
||||
uint16_t slss_id = 671, ssb_ta_index = 1;
|
||||
//12 bits -sl-TDD-config will be filled by MAC
|
||||
//Incoverage 1bit is FALSE as this is mode 2
|
||||
//DFN, sfn will be filled by PHY
|
||||
uint8_t sl_mib_payload[4] = {0,0,0,0};
|
||||
|
||||
NR_SL_SSB_TimeAllocation_r16_t *ssb_ta = NULL;
|
||||
NR_SL_FreqConfigCommon_r16_t *fcfg = NULL;
|
||||
NR_SL_SyncConfig_r16_t *synccfg = NULL;
|
||||
if (sl_preconfig->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16)
|
||||
fcfg = sl_preconfig->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16->list.array[0];
|
||||
AssertFatal(fcfg, "Fcfg cannot be NULL\n");
|
||||
if (fcfg->sl_SyncConfigList_r16)
|
||||
synccfg = fcfg->sl_SyncConfigList_r16->list.array[0];
|
||||
AssertFatal(synccfg, "Synccfg cannot be NULL\n");
|
||||
|
||||
if (ssb_ta_index == 1)
|
||||
ssb_ta = synccfg->sl_SSB_TimeAllocation1_r16;
|
||||
else if (ssb_ta_index == 2)
|
||||
ssb_ta = synccfg->sl_SSB_TimeAllocation2_r16;
|
||||
else if (ssb_ta_index == 3)
|
||||
ssb_ta = synccfg->sl_SSB_TimeAllocation3_r16;
|
||||
else DevAssert(0);
|
||||
|
||||
AssertFatal(ssb_ta, "SSB_timeallocation cannot be NULL\n");
|
||||
|
||||
if (sync_source == SL_SYNC_SOURCE_LOCAL_TIMING || sync_source == SL_SYNC_SOURCE_GNSS)
|
||||
nr_rrc_mac_transmit_slss_req(rrc_inst->ue_id,sl_mib_payload, slss_id, ssb_ta);
|
||||
|
||||
}
|
||||
|
||||
//For Sidelink mode 2 operation this prepares the sidelink preconfiguration
|
||||
void init_sidelink(NR_UE_RRC_INST_t *rrc)
|
||||
{
|
||||
int sync_ref = get_softmodem_params()->sync_ref;
|
||||
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
//Preparation of the Sidelink PRE-Configuration message
|
||||
configure_NR_SL_Preconfig(rrc, sync_ref);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user