Commit 70f586cb authored by Raghavendra Dinavahi's avatar Raghavendra Dinavahi

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
parent 745cc733
......@@ -1369,9 +1369,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
......
......@@ -973,6 +973,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_softmodem_params()->sync_ref);
}
}
void init_NR_UE_threads(int nb_inst) {
......
......@@ -503,6 +503,10 @@ int main( int argc, char **argv ) {
if (!get_softmodem_params()->nsa && get_softmodem_params()->emulate_l1)
start_oai_nrue_threads();
if (get_softmodem_params()->sl_mode) {
nr_UE_configure_Sidelink(0, get_softmodem_params()->sync_ref);
}
if (!get_softmodem_params()->emulate_l1) {
for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
PHY_vars_UE_g[0][CC_id] = (PHY_VARS_NR_UE *)malloc(sizeof(PHY_VARS_NR_UE));
......
......@@ -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;
......
/*
* 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 &&
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_to_set:%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)
{
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); // 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)
{
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");
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_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);
}
}
\ No newline at end of file
......@@ -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"
......@@ -526,6 +527,9 @@ typedef struct {
pthread_mutex_t mutex_dl_info;
//SIDELINK MAC PARAMETERS
sl_nr_ue_mac_params_t *SL_MAC_PARAMS;
} NR_UE_MAC_INST_t;
/*@}*/
......
/*
* 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 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
......@@ -430,5 +430,29 @@ 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
/** @}*/
/*
* 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;
}
\ No newline at end of file
......@@ -453,7 +453,7 @@ NR_UE_RRC_INST_t* openair_rrc_top_init_ue_nr(char* uecap_file, char* rrc_config_
}
if (get_softmodem_params()->sl_mode) {
configure_NR_SL_Preconfig(get_softmodem_params()->sync_ref);
configure_NR_SL_Preconfig(0,get_softmodem_params()->sync_ref);
}
}
else{
......
......@@ -53,6 +53,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"
......@@ -254,6 +256,11 @@ typedef struct NR_UE_RRC_INST_s {
Rrc_State_NR_t nrRrcState;
Rrc_Sub_State_NR_t nrRrcSubState;
as_nas_info_t initialNasMsg;
//Sidelink params
NR_SL_PreconfigurationNR_r16_t *sl_preconfig;
NR_MasterInformationBlockSidelink_t *sl_mib;
} NR_UE_RRC_INST_t;
#endif
......
......@@ -173,7 +173,9 @@ void handle_rlf_sync(NR_UE_Timers_Constants_t *tac,
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(uint8_t id,int sync_source);
void nr_UE_configure_Sidelink(uint8_t id, uint8_t is_sync_source);
/** @}*/
#endif
......@@ -27,6 +27,19 @@
#include "common/utils/LOG/log.h"
#include "sl_preconfig_paramvalues.h"
#include "common/config/config_userapi.h"
#include "rrc_defs.h"
#include "rrc_vars.h"
#include "LAYER2/NR_MAC_UE/mac_proto.h"
#define GNSS_SUPPORT 0
#define SL_SYNC_SOURCE_NONE 0 //No sync source selected
#define SL_SYNC_SOURCE_GNBENB 1 // GNB/ENB as sync source
#define SL_SYNC_SOURCE_GNSS 2 // GPS as sync source
#define SL_SYNC_SOURCE_SYNC_REF_UE 3 // another SYNC REF UE as sync source
#define SL_SYNC_SOURCE_LOCAL_TIMING 4 //UE acts as sync source
static void prepare_NR_SL_SyncConfig(NR_SL_SyncConfig_r16_t *sl_syncconfig)
{
......@@ -399,8 +412,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(uint8_t id,int sync_source)
{
NR_SL_PreconfigurationNR_r16_t *sl_preconfig = NULL;
......@@ -424,9 +436,155 @@ int configure_NR_SL_Preconfig(int sync_source)
}
}
ASN_STRUCT_FREE(asn_DEF_NR_SL_PreconfigurationNR_r16, sl_preconfig);
sl_preconfig = NULL;
//END.......
NR_UE_RRC_INST_t *rrc = &NR_UE_rrc_inst[id];
rrc->sl_preconfig = sl_preconfig;
return 0;
}
/*
* This functions configures SIdelink operation in the UE.
* RRC configures MAC with sidelink parameters
* In case UE is a sync source/Master UE - then sends transmit SLSS REQ
*/
void nr_UE_configure_Sidelink(uint8_t id, uint8_t is_sync_source) {
NR_UE_RRC_INST_t *rrc = &NR_UE_rrc_inst[id];
AssertFatal(rrc, "Check if rrc instance was created.");
NR_SL_PreconfigurationNR_r16_t *sl_preconfig = rrc->sl_preconfig;
AssertFatal(sl_preconfig, "Check if SL-preconfig was created.");
uint8_t sync_source = SL_SYNC_SOURCE_NONE;
if (is_sync_source) {
sync_source = (GNSS_SUPPORT) ? SL_SYNC_SOURCE_GNSS
: SL_SYNC_SOURCE_LOCAL_TIMING;
}
nr_rrc_mac_config_req_sl_preconfig(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
//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 (rrc->sl_preconfig->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16)
fcfg = rrc->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(id,sl_mib_payload, slss_id, ssb_ta);
}
/*decode SL-BCH (SL-MIB) message*/
static int8_t nr_sl_rrc_ue_decode_SL_MIB(const module_id_t module_id,
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);
uint16_t val_fn = sl_mib->directFrameNumber_r16.buf[0];
val_fn = (val_fn << 2) + (sl_mib->directFrameNumber_r16.buf[1] >> sl_mib->directFrameNumber_r16.bits_unused);
uint8_t val_slot = sl_mib->slotIndex_r16.buf[0];
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)));
int ret = 1;
if ((dec_rval.code != RC_OK) || (dec_rval.consumed == 0)) {
LOG_E(NR_RRC, "SL-MIB decode error\n");
ret = -1;
} else {
ret = 0;
if (NR_UE_rrc_inst[module_id].sl_mib == NULL) {
LOG_I(NR_RRC, "Sidelink RRC first MIB reception\n");
} else {
ASN_STRUCT_FREE(asn_DEF_NR_MasterInformationBlockSidelink, NR_UE_rrc_inst[module_id].sl_mib);
}
NR_UE_rrc_inst[module_id].sl_mib = sl_mib;
}
return ret;
}
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)
{
nr_sl_rrc_ue_decode_SL_MIB(module_id, gNB_index, (uint8_t*)pduP, pdu_len);
DevAssert(NR_UE_rrc_inst[module_id].sl_preconfig);
NR_SL_FreqConfigCommon_r16_t *fcfg = NULL;
if (NR_UE_rrc_inst[module_id].sl_preconfig->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16)
fcfg = NR_UE_rrc_inst[module_id].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(module_id,
sl_SSB_TimeAllocation,
rx_slss_id,
pduP);
return;
}
void free_sl_rrc(uint8_t id) {
NR_UE_RRC_INST_t *rrc = &NR_UE_rrc_inst[id];
if (rrc->sl_preconfig) {
ASN_STRUCT_FREE(asn_DEF_NR_SL_PreconfigurationNR_r16, rrc->sl_preconfig);
}
if (rrc->sl_mib) {
ASN_STRUCT_FREE(asn_DEF_NR_MasterInformationBlockSidelink, rrc->sl_mib);
}
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment