This assert and assumption is incorrect, according to 38.101-1 UE channel is defined only by the BWP size
and BWP size can be any value supported by the RRC parameters defining the BWP.
To determine the UE channel the smallest bandwidth supporting the BWP is selected. This is an assumption based
on references in the same document to UE channel bandwidth being equal to one of the values in set
{5, 10, 15, 20, 25, 30, 35, 40, 50, 60, 70, 80, 90, 100}.
Also:
- calculated P_CMIN during BWP setup since the parameter doesn't depend on DCI.
- initiialize uniqCfg structure in test_nr_ue_power_procedures main function which enables LOG prints during tests
535 lines
25 KiB
C
535 lines
25 KiB
C
/*
|
|
* 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(NR_UE_MAC_INST_t *mac)
|
|
{
|
|
|
|
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, FR1, 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:%u, scaling:%d, pointa:%u, ssb:%u\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;
|
|
|
|
// Sync source is identified, timing needs to be adjusted.
|
|
sl_mac->timing_acquired = true;
|
|
}
|
|
|
|
//Do not copy TDD config yet as SYNC source is not yet found
|
|
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->timing_acquired = true;
|
|
|
|
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);
|
|
|
|
DevAssert(mac->if_module != NULL && mac->if_module->sl_phy_config_request != NULL);
|
|
mac->if_module->sl_phy_config_request(&sl_mac->sl_phy_config);
|
|
}
|
|
}
|
|
|