Commit 4d369a69 authored by Raghavendra Dinavahi's avatar Raghavendra Dinavahi

Sidelink config MAC->PHY, PSBCH scheduler and supporting functions

	- Phy config update and Sidelink frame parameters initialisation
	- PSBCH scheduler to trigger TX PSBCH/RX PSBCH actions
	- Sidelink indication with rx ind to trigger send SL-MIB to MAC
parent 70f586cb
...@@ -312,13 +312,15 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){ ...@@ -312,13 +312,15 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){
} }
void init_openair0(void) { void init_openair0(uint8_t is_sidelink) {
int card; int card;
int freq_off = 0; int freq_off = 0;
NR_DL_FRAME_PARMS *frame_parms = &PHY_vars_UE_g[0][0]->frame_parms; NR_DL_FRAME_PARMS *frame_parms = &PHY_vars_UE_g[0][0]->frame_parms;
if (is_sidelink)
frame_parms = &PHY_vars_UE_g[0][0]->SL_UE_PHY_PARAMS.sl_frame_params;
for (card=0; card<MAX_CARDS; card++) { for (card=0; card<MAX_CARDS; card++) {
uint64_t dl_carrier, ul_carrier, sl_carrier; uint64_t dl_carrier, ul_carrier;
openair0_cfg[card].configFilename = NULL; openair0_cfg[card].configFilename = NULL;
openair0_cfg[card].threequarter_fs = frame_parms->threequarter_fs; openair0_cfg[card].threequarter_fs = frame_parms->threequarter_fs;
openair0_cfg[card].sample_rate = frame_parms->samples_per_subframe * 1e3; openair0_cfg[card].sample_rate = frame_parms->samples_per_subframe * 1e3;
...@@ -344,15 +346,14 @@ void init_openair0(void) { ...@@ -344,15 +346,14 @@ void init_openair0(void) {
openair0_cfg[card].rx_num_channels, openair0_cfg[card].rx_num_channels,
duplex_mode[openair0_cfg[card].duplex_mode]); duplex_mode[openair0_cfg[card].duplex_mode]);
nr_get_carrier_frequencies(PHY_vars_UE_g[0][0], &dl_carrier, &ul_carrier); if (is_sidelink) {
dl_carrier = frame_parms->dl_CarrierFreq;
ul_carrier = frame_parms->ul_CarrierFreq;
} else
nr_get_carrier_frequencies(PHY_vars_UE_g[0][0], &dl_carrier, &ul_carrier);
nr_rf_card_config_freq(&openair0_cfg[card], ul_carrier, dl_carrier, freq_off); nr_rf_card_config_freq(&openair0_cfg[card], ul_carrier, dl_carrier, freq_off);
if (get_softmodem_params()->sl_mode == 2) {
nr_get_carrier_frequencies_sl(PHY_vars_UE_g[0][0], &sl_carrier);
nr_rf_card_config_freq(&openair0_cfg[card], sl_carrier, sl_carrier, freq_off);
}
nr_rf_card_config_gain(&openair0_cfg[card], rx_gain_off); nr_rf_card_config_gain(&openair0_cfg[card], rx_gain_off);
openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file; openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file;
...@@ -503,10 +504,6 @@ int main( int argc, char **argv ) { ...@@ -503,10 +504,6 @@ int main( int argc, char **argv ) {
if (!get_softmodem_params()->nsa && get_softmodem_params()->emulate_l1) if (!get_softmodem_params()->nsa && get_softmodem_params()->emulate_l1)
start_oai_nrue_threads(); 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) { if (!get_softmodem_params()->emulate_l1) {
for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { 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)); PHY_vars_UE_g[0][CC_id] = (PHY_VARS_NR_UE *)malloc(sizeof(PHY_VARS_NR_UE));
...@@ -536,10 +533,26 @@ int main( int argc, char **argv ) { ...@@ -536,10 +533,26 @@ int main( int argc, char **argv ) {
*mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]); *mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]);
} }
UE[CC_id]->sl_mode = get_softmodem_params()->sl_mode;
init_nr_ue_vars(UE[CC_id], 0, abstraction_flag); init_nr_ue_vars(UE[CC_id], 0, abstraction_flag);
if (UE[CC_id]->sl_mode) {
AssertFatal(UE[CC_id]->sl_mode == 2, "Only Sidelink mode 2 supported. Mode 1 not yet supported\n");
nr_UE_configure_Sidelink(0, get_softmodem_params()->sync_ref);
DevAssert(mac->if_module != NULL && mac->if_module->sl_phy_config_request != NULL);
sl_nr_ue_phy_params_t *sl_phy = &UE[CC_id]->SL_UE_PHY_PARAMS;
mac->if_module->sl_phy_config_request(&mac->SL_MAC_PARAMS->sl_phy_config);
nr_init_frame_parms_ue_sl(&sl_phy->sl_frame_params,&sl_phy->sl_config,
get_nrUE_params()->threequarter_fs,
get_nrUE_params()->ofdm_offset_divisor);
sl_ue_phy_init(UE[CC_id]);
}
} }
init_openair0(); uint8_t is_sl = (get_softmodem_params()->sl_mode) ? 1 : 0;
init_openair0(is_sl);
// init UE_PF_PO and mutex lock // init UE_PF_PO and mutex lock
pthread_mutex_init(&ue_pf_po_mutex, NULL); pthread_mutex_init(&ue_pf_po_mutex, NULL);
memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*NUMBER_OF_UE_MAX*MAX_NUM_CCs); memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*NUMBER_OF_UE_MAX*MAX_NUM_CCs);
......
...@@ -297,8 +297,12 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) ...@@ -297,8 +297,12 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
// init RX buffers // init RX buffers
common_vars->rxdata = malloc16(fp->nb_antennas_rx * sizeof(c16_t *)); common_vars->rxdata = malloc16(fp->nb_antennas_rx * sizeof(c16_t *));
int num_samples = 2 * fp->samples_per_frame + fp->ofdm_symbol_size;
if (ue->sl_mode == 2)
num_samples = (SL_NR_PSBCH_REPETITION_IN_FRAMES * fp->samples_per_frame) + fp->ofdm_symbol_size;
for (i=0; i<fp->nb_antennas_rx; i++) { for (i=0; i<fp->nb_antennas_rx; i++) {
common_vars->rxdata[i] = malloc16_clear((2 * (fp->samples_per_frame) + fp->ofdm_symbol_size) * sizeof(c16_t)); common_vars->rxdata[i] = malloc16_clear(num_samples * sizeof(c16_t));
} }
// ceil(((NB_RB<<1)*3)/32) // 3 RE *2(QPSK) // ceil(((NB_RB<<1)*3)/32) // 3 RE *2(QPSK)
...@@ -646,7 +650,8 @@ void init_N_TA_offset(PHY_VARS_NR_UE *ue){ ...@@ -646,7 +650,8 @@ void init_N_TA_offset(PHY_VARS_NR_UE *ue){
NR_DL_FRAME_PARMS *fp = &ue->frame_parms; NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
if (fp->frame_type == FDD) { // No timing offset for Sidelink, refer to 3GPP 38.211 Section 8.5
if (fp->frame_type == FDD || ue->sl_mode == 2) {
ue->N_TA_offset = 0; ue->N_TA_offset = 0;
} else { } else {
int N_TA_offset = fp->ul_CarrierFreq < 6e9 ? 400 : 431; // reference samples for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2 int N_TA_offset = fp->ul_CarrierFreq < 6e9 ? 400 : 431; // reference samples for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2
...@@ -940,6 +945,4 @@ void sl_ue_phy_init(PHY_VARS_NR_UE *UE) { ...@@ -940,6 +945,4 @@ void sl_ue_phy_init(PHY_VARS_NR_UE *UE) {
// Generate PSS time domain samples used for correlation during SLSS reception. // Generate PSS time domain samples used for correlation during SLSS reception.
sl_generate_pss_ifft_samples(&UE->SL_UE_PHY_PARAMS, &UE->SL_UE_PHY_PARAMS.init_params); sl_generate_pss_ifft_samples(&UE->SL_UE_PHY_PARAMS, &UE->SL_UE_PHY_PARAMS.init_params);
init_symbol_rotation(sl_fp);
init_timeshift_rotation(sl_fp);
} }
\ No newline at end of file
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "common/utils/nr/nr_common.h" #include "common/utils/nr/nr_common.h"
#include "common/utils/LOG/log.h" #include "common/utils/LOG/log.h"
#include "executables/softmodem-common.h" #include "executables/softmodem-common.h"
#include "PHY/MODULATION/nr_modulation.h"
/// Subcarrier spacings in Hz indexed by numerology index /// Subcarrier spacings in Hz indexed by numerology index
static const uint32_t nr_subcarrier_spacing[MAX_NUM_SUBCARRIER_SPACING] = {15e3, 30e3, 60e3, 120e3, 240e3}; static const uint32_t nr_subcarrier_spacing[MAX_NUM_SUBCARRIER_SPACING] = {15e3, 30e3, 60e3, 120e3, 240e3};
...@@ -42,18 +43,6 @@ static const int nr_ssb_table[48][3] = { ...@@ -42,18 +43,6 @@ static const int nr_ssb_table[48][3] = {
{93, 15, nr_ssb_type_A}, {94, 15, nr_ssb_type_A}, {96, 30, nr_ssb_type_C}}; {93, 15, nr_ssb_type_A}, {94, 15, nr_ssb_type_A}, {96, 30, nr_ssb_type_C}};
void set_Lmax(NR_DL_FRAME_PARMS *fp) { void set_Lmax(NR_DL_FRAME_PARMS *fp) {
if (get_softmodem_params()->sl_mode == 2) {
int sl_NumSSB_WithinPeriod = 1; //TODO: Needs to be updated from RRC parameters
int sl_TimeOffsetSSB = 1; //TODO: Needs to be updated from RRC parameters
int sl_TimeInterval = 1; //TODO: Needs to be updated from RRC parameters
if ((sl_NumSSB_WithinPeriod == 4) && ((sl_TimeOffsetSSB % fp->slots_per_frame) + 3 * sl_TimeInterval < NR_NUMBER_OF_SUBFRAMES_PER_FRAME * 2))
fp->Lmax = 4;
else if ((sl_NumSSB_WithinPeriod == 2) && ((sl_TimeOffsetSSB % fp->slots_per_frame) + sl_TimeInterval < NR_NUMBER_OF_SUBFRAMES_PER_FRAME))
fp->Lmax = 2;
else
fp->Lmax = 1;
return;
}
// definition of Lmax according to ts 38.213 section 4.1 // definition of Lmax according to ts 38.213 section 4.1
if (fp->dl_CarrierFreq < 6e9) { if (fp->dl_CarrierFreq < 6e9) {
if(fp->frame_type && (fp->ssb_type==2)) if(fp->frame_type && (fp->ssb_type==2))
...@@ -115,23 +104,27 @@ void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, int N_RB_DL) ...@@ -115,23 +104,27 @@ void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, int N_RB_DL)
case NR_MU_0: //15kHz scs case NR_MU_0: //15kHz scs
fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_0]; fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_0];
fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_0]; fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_0];
fp->ssb_type = nr_ssb_type_A; if (fp->nr_band != 47) {
while(nr_ssb_table[idx][0]!=fp->nr_band) fp->ssb_type = nr_ssb_type_A;
idx++; while(nr_ssb_table[idx][0]!=fp->nr_band)
AssertFatal(nr_ssb_table[idx][1]==15,"SCS %d not applicable to band %d\n", idx++;
fp->subcarrier_spacing,fp->nr_band); AssertFatal(nr_ssb_table[idx][1]==15,"SCS %d not applicable to band %d\n",
fp->subcarrier_spacing,fp->nr_band);
}
break; break;
case NR_MU_1: //30kHz scs case NR_MU_1: //30kHz scs
fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_1]; fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_1];
fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_1]; fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_1];
while(nr_ssb_table[idx][0]!=fp->nr_band || if (fp->nr_band != 47) {
nr_ssb_table[idx][1]!=30) { while(nr_ssb_table[idx][0]!=fp->nr_band ||
AssertFatal(nr_ssb_table[idx][0]<=fp->nr_band,"SCS %d not applicable to band %d\n", nr_ssb_table[idx][1]!=30) {
fp->subcarrier_spacing,fp->nr_band); AssertFatal(nr_ssb_table[idx][0]<=fp->nr_band,"SCS %d not applicable to band %d\n",
idx++; fp->subcarrier_spacing,fp->nr_band);
idx++;
}
fp->ssb_type = nr_ssb_table[idx][2];
} }
fp->ssb_type = nr_ssb_table[idx][2];
break; break;
case NR_MU_2: //60kHz scs case NR_MU_2: //60kHz scs
...@@ -164,9 +157,6 @@ void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, int N_RB_DL) ...@@ -164,9 +157,6 @@ void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, int N_RB_DL)
fp->ofdm_symbol_size <<= 1; fp->ofdm_symbol_size <<= 1;
fp->first_carrier_offset = fp->ofdm_symbol_size - (N_RB_DL * 12 / 2); fp->first_carrier_offset = fp->ofdm_symbol_size - (N_RB_DL * 12 / 2);
// TODO: Temporarily setting fp->first_carrier_offset = 0 for SL until MAC is developed
if (get_softmodem_params()->sl_mode == 2)
fp->first_carrier_offset = 0;
fp->nb_prefix_samples = fp->ofdm_symbol_size / 128 * 9; fp->nb_prefix_samples = fp->ofdm_symbol_size / 128 * 9;
fp->nb_prefix_samples0 = fp->ofdm_symbol_size / 128 * (9 + (1 << mu)); fp->nb_prefix_samples0 = fp->ofdm_symbol_size / 128 * (9 + (1 << mu));
LOG_W(PHY,"Init: N_RB_DL %d, first_carrier_offset %d, nb_prefix_samples %d,nb_prefix_samples0 %d, ofdm_symbol_size %d\n", LOG_W(PHY,"Init: N_RB_DL %d, first_carrier_offset %d, nb_prefix_samples %d,nb_prefix_samples0 %d, ofdm_symbol_size %d\n",
...@@ -299,11 +289,6 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, ...@@ -299,11 +289,6 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
LOG_D(PHY,"dl_bw_kHz %lu\n",dl_bw_khz); LOG_D(PHY,"dl_bw_kHz %lu\n",dl_bw_khz);
LOG_D(PHY,"dl_CarrierFreq %lu\n",fp->dl_CarrierFreq); LOG_D(PHY,"dl_CarrierFreq %lu\n",fp->dl_CarrierFreq);
if (get_softmodem_params()->sl_mode == 2) {
uint64_t sl_bw_khz = (12 * config->carrier_config.sl_grid_size[config->ssb_config.scs_common]) * (15 << config->ssb_config.scs_common);
fp->sl_CarrierFreq = ((sl_bw_khz >> 1) + config->carrier_config.sl_frequency) * 1000;
}
uint64_t ul_bw_khz = (12*config->carrier_config.ul_grid_size[config->ssb_config.scs_common])*(15<<config->ssb_config.scs_common); uint64_t ul_bw_khz = (12*config->carrier_config.ul_grid_size[config->ssb_config.scs_common])*(15<<config->ssb_config.scs_common);
fp->ul_CarrierFreq = ((ul_bw_khz>>1) + config->carrier_config.uplink_frequency)*1000 ; fp->ul_CarrierFreq = ((ul_bw_khz>>1) + config->carrier_config.uplink_frequency)*1000 ;
...@@ -329,7 +314,7 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, ...@@ -329,7 +314,7 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
AssertFatal(fp->numerology_index == NR_MU_2,"Invalid cyclic prefix %d for numerology index %d\n", Ncp, fp->numerology_index); AssertFatal(fp->numerology_index == NR_MU_2,"Invalid cyclic prefix %d for numerology index %d\n", Ncp, fp->numerology_index);
fp->Ncp = Ncp; fp->Ncp = Ncp;
int N_RB = (get_softmodem_params()->sl_mode == 2) ? fp->N_RB_SL : fp->N_RB_DL; int N_RB = fp->N_RB_DL;
set_scs_parameters(fp, fp->numerology_index, N_RB); set_scs_parameters(fp, fp->numerology_index, N_RB);
fp->slots_per_frame = 10* fp->slots_per_subframe; fp->slots_per_frame = 10* fp->slots_per_subframe;
...@@ -354,10 +339,6 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, ...@@ -354,10 +339,6 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
} }
fp->ssb_start_subcarrier = (12 * config->ssb_table.ssb_offset_point_a + sco); fp->ssb_start_subcarrier = (12 * config->ssb_table.ssb_offset_point_a + sco);
// TODO: Temporarily setting fp->ssb_start_subcarrier = 0 for SL until MAC is developed
if (get_softmodem_params()->sl_mode == 2) {
fp->ssb_start_subcarrier = 0;
}
set_Lmax(fp); set_Lmax(fp);
fp->L_ssb = (((uint64_t) config->ssb_table.ssb_mask_list[0].ssb_mask)<<32) | config->ssb_table.ssb_mask_list[1].ssb_mask; fp->L_ssb = (((uint64_t) config->ssb_table.ssb_mask_list[0].ssb_mask)<<32) | config->ssb_table.ssb_mask_list[1].ssb_mask;
...@@ -407,12 +388,6 @@ void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink ...@@ -407,12 +388,6 @@ void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink
} }
void nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *frame_parms, uint64_t sidelink_frequency, uint16_t nr_band) {
LOG_D(NR_PHY, "SL init parameters. SL freq %lu\n", sidelink_frequency);
frame_parms->sl_CarrierFreq = sidelink_frequency;
frame_parms->nr_band = nr_band;
}
void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp) void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp)
{ {
LOG_I(PHY,"fp->scs=%d\n",fp->subcarrier_spacing); LOG_I(PHY,"fp->scs=%d\n",fp->subcarrier_spacing);
...@@ -429,5 +404,106 @@ void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp) ...@@ -429,5 +404,106 @@ void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp)
LOG_I(PHY,"fp->Nid_cell=%d\n",fp->Nid_cell); LOG_I(PHY,"fp->Nid_cell=%d\n",fp->Nid_cell);
LOG_I(PHY,"fp->first_carrier_offset=%d\n",fp->first_carrier_offset); LOG_I(PHY,"fp->first_carrier_offset=%d\n",fp->first_carrier_offset);
LOG_I(PHY,"fp->ssb_start_subcarrier=%d\n",fp->ssb_start_subcarrier); LOG_I(PHY,"fp->ssb_start_subcarrier=%d\n",fp->ssb_start_subcarrier);
LOG_I(PHY,"fp->Ncp=%d\n",fp->Ncp);
LOG_I(PHY,"fp->N_RB_DL=%d\n",fp->N_RB_DL);
LOG_I(PHY,"fp->numerology_index=%d\n",fp->numerology_index);
LOG_I(PHY,"fp->nr_band=%d\n",fp->nr_band);
LOG_I(PHY,"fp->ofdm_offset_divisor=%d\n",fp->ofdm_offset_divisor);
LOG_I(PHY,"fp->threequarter_fs=%d\n",fp->threequarter_fs);
LOG_I(PHY,"fp->sl_CarrierFreq=%lu\n",fp->sl_CarrierFreq);
LOG_I(PHY,"fp->N_RB_SL=%d\n",fp->N_RB_SL);
} }
int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp,
sl_nr_phy_config_request_t* config,
int threequarter_fs,
uint32_t ofdm_offset_divisor)
{
//Set also these parameters here instead of some where else.
fp->ofdm_offset_divisor = ofdm_offset_divisor;
fp->threequarter_fs = threequarter_fs;
fp->nr_band = get_band(config->sl_carrier_config.sl_frequency, 0);
fp->att_rx = config->sl_carrier_config.sl_num_rx_ant;
fp->att_tx = config->sl_carrier_config.sl_num_tx_ant;
fp->nb_antennas_rx = fp->att_rx;
fp->nb_antennas_tx = fp->att_tx;
fp->numerology_index = config->sl_bwp_config.sl_scs;
fp->N_RB_SL = config->sl_carrier_config.sl_grid_size;
fp->N_RB_DL = fp->N_RB_SL;
fp->N_RB_UL = fp->N_RB_SL;
fp->Ncp = config->sl_bwp_config.sl_cyclic_prefix;
fp->frame_type = get_frame_type(fp->nr_band, fp->numerology_index);
int32_t uplink_frequency_offset = get_delta_duplex(fp->nr_band, fp->numerology_index);
uplink_frequency_offset *= 1000;
uint64_t bw_khz = (12*config->sl_carrier_config.sl_grid_size)*(15<<config->sl_bwp_config.sl_scs);
//REfer to section 3GPP spec 38.101 5.4E.2.1
//FrefV2x = Fref + deltashift + valueN*5Khz
uint32_t deltashift = (config->sl_carrier_config.sl_frequency_shift_7p5khz) ? 7500 : 0; //In Hz
deltashift += config->sl_carrier_config.sl_value_N * 5000; //In Hz
fp->sl_CarrierFreq = ((bw_khz >> 1) + config->sl_carrier_config.sl_frequency)*1000 ;
fp->sl_CarrierFreq += (deltashift >> 1);
fp->dl_CarrierFreq = fp->sl_CarrierFreq;
fp->ul_CarrierFreq = fp->dl_CarrierFreq + uplink_frequency_offset;
LOG_D(PHY,"bw_kHz %lu, deltashift:%d Hz\n",bw_khz,deltashift);
LOG_D(PHY,"CarrierFreq %lu Hz\n",fp->sl_CarrierFreq);
LOG_I(PHY, "Initializing frame parms: DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %d Hz\n",
fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, uplink_frequency_offset);
AssertFatal(fp->frame_type==TDD, "Sidelink bands only support TDD");
AssertFatal(fp->ul_CarrierFreq == (fp->dl_CarrierFreq + uplink_frequency_offset),
"Disagreement in uplink frequency for band %d: ul_CarrierFreq = %lu Hz vs expected %lu Hz\n",
fp->nr_band, fp->ul_CarrierFreq, fp->dl_CarrierFreq + uplink_frequency_offset);
LOG_I(PHY,"Initializing frame parms for mu %d, N_RB %d, Ncp %d\n",fp->numerology_index, fp->N_RB_DL, fp->Ncp);
if (fp->Ncp == EXTENDED)
AssertFatal(fp->numerology_index == NR_MU_2,"Invalid cyclic prefix %d for numerology index %d\n",
fp->Ncp, fp->numerology_index);
set_scs_parameters(fp, fp->numerology_index, fp->N_RB_SL);
fp->slots_per_frame = 10* fp->slots_per_subframe;
fp->symbols_per_slot = ((fp->Ncp == NORMAL)? 14 : 12); // to redefine for different slot formats
fp->samples_per_subframe_wCP = fp->ofdm_symbol_size * fp->symbols_per_slot * fp->slots_per_subframe;
fp->samples_per_frame_wCP = 10 * fp->samples_per_subframe_wCP;
fp->samples_per_slot_wCP = fp->symbols_per_slot*fp->ofdm_symbol_size;
fp->samples_per_slotN0 = (fp->nb_prefix_samples + fp->ofdm_symbol_size) * fp->symbols_per_slot;
fp->samples_per_slot0 = fp->nb_prefix_samples0 + ((fp->symbols_per_slot-1)*fp->nb_prefix_samples) + (fp->symbols_per_slot*fp->ofdm_symbol_size);
fp->samples_per_subframe = (fp->nb_prefix_samples0 + fp->ofdm_symbol_size) * 2 +
(fp->nb_prefix_samples + fp->ofdm_symbol_size) * (fp->symbols_per_slot * fp->slots_per_subframe - 2);
fp->get_samples_per_slot = &get_samples_per_slot;
fp->get_samples_slot_timestamp = &get_samples_slot_timestamp;
fp->samples_per_frame = 10 * fp->samples_per_subframe;
fp->freq_range = (fp->dl_CarrierFreq < 6e9)? nr_FR1 : nr_FR2;
//ssb_offset_pointa points to the first RE where Sidelink-PSBCH starts
fp->ssb_start_subcarrier = config->sl_bwp_config.sl_ssb_offset_point_a;
init_symbol_rotation(fp);
init_timeshift_rotation(fp);
//Not used for Sidelink
fp->Lmax = 0;
fp->L_ssb = 0;
fp->N_ssb = 0;
fp->half_frame_bit = 0;
fp->ssb_index = 0;
fp->ssb_type = 0;
//#ifdef SL_DEBUG
LOG_I(PHY, "Dumping Sidelink Frame Parameters\n");
nr_dump_frame_parms(fp);
//#endif
return 0;
}
...@@ -29,7 +29,10 @@ int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp,uint8_t i_ssb); ...@@ -29,7 +29,10 @@ int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp,uint8_t i_ssb);
int nr_init_frame_parms(nfapi_nr_config_request_scf_t *config, NR_DL_FRAME_PARMS *frame_parms); int nr_init_frame_parms(nfapi_nr_config_request_scf_t *config, NR_DL_FRAME_PARMS *frame_parms);
int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *frame_parms, fapi_nr_config_request_t *config, uint16_t nr_band); int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *frame_parms, fapi_nr_config_request_t *config, uint16_t nr_band);
void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink_frequency, int32_t uplink_frequency_offset, uint8_t mu, uint16_t nr_band); void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink_frequency, int32_t uplink_frequency_offset, uint8_t mu, uint16_t nr_band);
void nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *frame_parms, uint64_t sidelink_frequency, uint16_t nr_band); int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp,
sl_nr_phy_config_request_t* config,
int threequarter_fs,
uint32_t ofdm_offset_divisor);
int init_nr_ue_signal(PHY_VARS_NR_UE *ue,int nb_connected_eNB); int init_nr_ue_signal(PHY_VARS_NR_UE *ue,int nb_connected_eNB);
void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB); void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB);
void init_nr_ue_transport(PHY_VARS_NR_UE *ue); void init_nr_ue_transport(PHY_VARS_NR_UE *ue);
...@@ -58,5 +61,4 @@ void phy_init_nr_top(PHY_VARS_NR_UE *ue); ...@@ -58,5 +61,4 @@ void phy_init_nr_top(PHY_VARS_NR_UE *ue);
void phy_term_nr_top(void); void phy_term_nr_top(void);
void sl_ue_phy_init(PHY_VARS_NR_UE *UE); void sl_ue_phy_init(PHY_VARS_NR_UE *UE);
void sl_ue_phy_init(PHY_VARS_NR_UE *UE);
#endif #endif
...@@ -601,7 +601,7 @@ void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) { ...@@ -601,7 +601,7 @@ void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) {
uint64_t dl_CarrierFreq = fp->dl_CarrierFreq; uint64_t dl_CarrierFreq = fp->dl_CarrierFreq;
uint64_t ul_CarrierFreq = fp->ul_CarrierFreq; uint64_t ul_CarrierFreq = fp->ul_CarrierFreq;
uint64_t sl_CarrierFreq = fp->sl_CarrierFreq; uint64_t sl_CarrierFreq = fp->sl_CarrierFreq;
double f[2] = {(double)dl_CarrierFreq, (double)ul_CarrierFreq}; double f[3] = {(double)dl_CarrierFreq, (double)ul_CarrierFreq, (double)sl_CarrierFreq};
const int nsymb = fp->symbols_per_slot * fp->slots_per_frame/10; const int nsymb = fp->symbols_per_slot * fp->slots_per_frame/10;
const double Tc=(1/480e3/4096); const double Tc=(1/480e3/4096);
...@@ -609,15 +609,12 @@ void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) { ...@@ -609,15 +609,12 @@ void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) {
const double Ncp0=16*64 + (144*64*(1/(float)(1<<fp->numerology_index))); const double Ncp0=16*64 + (144*64*(1/(float)(1<<fp->numerology_index)));
const double Ncp1=(144*64*(1/(float)(1<<fp->numerology_index))); const double Ncp1=(144*64*(1/(float)(1<<fp->numerology_index)));
for (uint8_t ll = 0; ll < 2; ll++){ for (uint8_t ll = 0; ll < 3; ll++){
double f0 = f[ll]; double f0 = f[ll];
if (f0 == 0) continue;
LOG_D(PHY, "Doing symbol rotation calculation for gNB TX/RX, f0 %f Hz, Nsymb %d\n", f0, nsymb); LOG_D(PHY, "Doing symbol rotation calculation for gNB TX/RX, f0 %f Hz, Nsymb %d\n", f0, nsymb);
c16_t *symbol_rotation = fp->symbol_rotation[ll]; c16_t *symbol_rotation = fp->symbol_rotation[ll];
if (get_softmodem_params()->sl_mode == 2) {
f0 = (double)sl_CarrierFreq;
symbol_rotation = fp->symbol_rotation[link_type_sl];
}
double tl = 0.0; double tl = 0.0;
double poff = 0.0; double poff = 0.0;
......
...@@ -362,7 +362,7 @@ void nr_sl_psbch_rsrp_measurements(sl_nr_ue_phy_params_t *sl_phy_params, ...@@ -362,7 +362,7 @@ void nr_sl_psbch_rsrp_measurements(sl_nr_ue_phy_params_t *sl_phy_params,
dB_fixed(fp->ofdm_symbol_size); dB_fixed(fp->ofdm_symbol_size);
LOG_I(PHY, "PSBCH RSRP (DMRS REs): numREs:%d RSRP :%d dB/RE ,RSRP:%d dBm/RE\n", LOG_D(PHY, "PSBCH RSRP (DMRS REs): numREs:%d RSRP :%d dB/RE ,RSRP:%d dBm/RE\n",
num_re, psbch_rx->rsrp_dB_per_RE, psbch_rx->rsrp_dBm_per_RE); num_re, psbch_rx->rsrp_dB_per_RE, psbch_rx->rsrp_dBm_per_RE);
} }
\ No newline at end of file
...@@ -47,15 +47,7 @@ void nr_get_carrier_frequencies(PHY_VARS_NR_UE *ue, uint64_t *dl_carrier, uint64 ...@@ -47,15 +47,7 @@ void nr_get_carrier_frequencies(PHY_VARS_NR_UE *ue, uint64_t *dl_carrier, uint64
} }
void nr_get_carrier_frequencies_sl(PHY_VARS_NR_UE *ue, uint64_t *sl_carrier) {
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
if (ue->if_freq!=0) {
*sl_carrier = ue->if_freq;
} else {
*sl_carrier = fp->sl_CarrierFreq;
}
}
void nr_rf_card_config_gain(openair0_config_t *openair0_cfg, void nr_rf_card_config_gain(openair0_config_t *openair0_cfg,
double rx_gain_off){ double rx_gain_off){
......
...@@ -75,6 +75,7 @@ ...@@ -75,6 +75,7 @@
#define SL_NR_NUM_IDs_IN_PSS 2 #define SL_NR_NUM_IDs_IN_PSS 2
#define SL_NR_NUM_IDs_IN_SSS 336 #define SL_NR_NUM_IDs_IN_SSS 336
#define SL_NR_NUM_SLSS_IDs 672 #define SL_NR_NUM_SLSS_IDs 672
#define SL_NR_PSBCH_REPETITION_IN_FRAMES 16
typedef enum sl_nr_sidelink_mode { typedef enum sl_nr_sidelink_mode {
SL_NOT_SUPPORTED = 0, SL_NOT_SUPPORTED = 0,
......
...@@ -98,6 +98,7 @@ SystemInformationBlockType1_nr_t; ...@@ -98,6 +98,7 @@ SystemInformationBlockType1_nr_t;
#define NR_DOWNLINK_SLOT (0x01) #define NR_DOWNLINK_SLOT (0x01)
#define NR_UPLINK_SLOT (0x02) #define NR_UPLINK_SLOT (0x02)
#define NR_MIXED_SLOT (0x03) #define NR_MIXED_SLOT (0x03)
#define NR_SIDELINK_SLOT NR_UPLINK_SLOT
#define FRAME_DURATION_MICRO_SEC (10000) /* frame duration in microsecond */ #define FRAME_DURATION_MICRO_SEC (10000) /* frame duration in microsecond */
......
...@@ -198,5 +198,14 @@ void psbch_pscch_processing(PHY_VARS_NR_UE *ue, ...@@ -198,5 +198,14 @@ void psbch_pscch_processing(PHY_VARS_NR_UE *ue,
int phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue, int phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc, UE_nr_rxtx_proc_t *proc,
nr_phy_data_tx_t *phy_data); nr_phy_data_tx_t *phy_data);
/*! \brief This function prepares the sl indication to pass to the MAC
*/
void nr_fill_sl_indication(nr_sidelink_indication_t *sl_ind,
sl_nr_rx_indication_t *rx_ind,
sl_nr_sci_indication_t *sci_ind,
UE_nr_rxtx_proc_t *proc,
PHY_VARS_NR_UE *ue,
void *phy_data);
#endif #endif
...@@ -391,6 +391,11 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ ...@@ -391,6 +391,11 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){
bool found = false; bool found = false;
if(scheduled_response != NULL){ if(scheduled_response != NULL){
if (scheduled_response->sl_rx_config || scheduled_response->sl_tx_config) {
sl_handle_scheduled_response(scheduled_response);
return 0;
}
module_id_t module_id = scheduled_response->module_id; module_id_t module_id = scheduled_response->module_id;
uint8_t cc_id = scheduled_response->CC_id; uint8_t cc_id = scheduled_response->CC_id;
int slot = scheduled_response->slot; int slot = scheduled_response->slot;
...@@ -661,3 +666,84 @@ void nr_ue_synch_request(nr_synch_request_t *synch_request) ...@@ -661,3 +666,84 @@ void nr_ue_synch_request(nr_synch_request_t *synch_request)
PHY_vars_UE_g[synch_request->Mod_id][synch_request->CC_id]->synch_request.received_synch_request = 1; PHY_vars_UE_g[synch_request->Mod_id][synch_request->CC_id]->synch_request.received_synch_request = 1;
} }
int8_t nr_ue_sl_phy_config_request(nr_sl_phy_config_t *phy_config)
{
sl_nr_phy_config_request_t *sl_config = &PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->SL_UE_PHY_PARAMS.sl_config;
if(phy_config != NULL) {
memcpy(sl_config,&phy_config->sl_config_req,sizeof(sl_nr_phy_config_request_t));
}
return 0;
}
/*
* MAC sends the scheduled response with either TX configrequest for Sidelink Transmission requests
* or RX config request for Sidelink Reception requests.
* This procedure handles these TX/RX config requests received in this slot and configures PHY
* with a TTI action to be performed in this slot(TTI)
*/
int8_t sl_handle_scheduled_response(nr_scheduled_response_t *scheduled_response) {
module_id_t module_id = scheduled_response->module_id;
uint32_t slot = scheduled_response->slot;
uint32_t frame = scheduled_response->frame;
const char *sl_rx_action[]={"NONE", "RX_PSBCH", "RX_PSCCH", "RX_SCI2_ON_PSSCH", "RX_SLSCH_ON_PSSCH"};
const char *sl_tx_action[]={"TX_PSBCH", "TX_PSCCH_PSSCH", "TX_PSFCH"};
if(scheduled_response->sl_rx_config != NULL) {
sl_nr_rx_config_request_t *sl_rx_config = scheduled_response->sl_rx_config;
nr_phy_data_t *phy_data = (nr_phy_data_t *)scheduled_response->phy_data;
AssertFatal(sl_rx_config->number_pdus == SL_NR_RX_CONFIG_LIST_NUM,
"sl_rx_config->number_pdus incorrect\n");
switch(sl_rx_config->sl_rx_config_list[0].pdu_type) {
case SL_NR_CONFIG_TYPE_RX_PSBCH:
phy_data->sl_rx_action = SL_NR_CONFIG_TYPE_RX_PSBCH;
LOG_D(PHY, "Recvd CONFIG_TYPE_RX_PSBCH\n");
break;
default:
AssertFatal(0,"Incorrect sl_rx config req pdutype \n");
break;
}
LOG_D(PHY, "[UE%d] TTI %d:%d, SL-RX action:%s\n",
module_id,frame,slot,
sl_rx_action[phy_data->sl_rx_action]);
} else if(scheduled_response->sl_tx_config != NULL) {
sl_nr_tx_config_request_t *sl_tx_config = scheduled_response->sl_tx_config;
nr_phy_data_tx_t *phy_data_tx = (nr_phy_data_tx_t *)scheduled_response->phy_data;
AssertFatal(sl_tx_config->number_pdus == SL_NR_TX_CONFIG_LIST_NUM,
"sl_tx_config->number_pdus incorrect \n");
switch(sl_tx_config->tx_config_list[0].pdu_type) {
case SL_NR_CONFIG_TYPE_TX_PSBCH:
phy_data_tx->sl_tx_action = SL_NR_CONFIG_TYPE_TX_PSBCH;
LOG_D(PHY, "Recvd CONFIG_TYPE_TX_PSBCH\n");
*((uint32_t *)phy_data_tx->psbch_vars.psbch_payload) =
*((uint32_t *) sl_tx_config->tx_config_list[0].tx_psbch_config_pdu.psbch_payload);
phy_data_tx->psbch_vars.psbch_tx_power =
sl_tx_config->tx_config_list[0].tx_psbch_config_pdu.psbch_tx_power;
phy_data_tx->psbch_vars.tx_slss_id =
sl_tx_config->tx_config_list[0].tx_psbch_config_pdu.tx_slss_id;
break;
default:
AssertFatal(0,"Incorrect sl_tx config req pdutype \n");
break;
}
LOG_D(PHY, "[UE%d] TTI %d:%d, SL-TX action:%s slss_id:%d, sl-mib:%x, psbch pwr:%d\n",
module_id,frame,slot,
sl_tx_action[phy_data_tx->sl_tx_action - 6],
phy_data_tx->psbch_vars.tx_slss_id,
*((uint32_t *)phy_data_tx->psbch_vars.psbch_payload),
phy_data_tx->psbch_vars.psbch_tx_power);
}
return 0;
}
\ No newline at end of file
...@@ -40,12 +40,14 @@ ...@@ -40,12 +40,14 @@
/**\brief NR UE FAPI-like P7 messages, scheduled response from L2 indicating L1 /**\brief NR UE FAPI-like P7 messages, scheduled response from L2 indicating L1
\param scheduled_response including transmission config(dl_config, ul_config) and data transmission (tx_req)*/ \param scheduled_response including transmission config(dl_config, ul_config) and data transmission (tx_req)*/
int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response); int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response);
int8_t sl_handle_scheduled_response(nr_scheduled_response_t *scheduled_response);
int8_t nr_ue_scheduled_response_stub(nr_scheduled_response_t *scheduled_response); int8_t nr_ue_scheduled_response_stub(nr_scheduled_response_t *scheduled_response);
/**\brief NR UE FAPI-like P5 message, physical configuration from L2 to configure L1 /**\brief NR UE FAPI-like P5 message, physical configuration from L2 to configure L1
\param scheduled_response including transmission config(dl_config, ul_config) and data transmission (tx_req)*/ \param scheduled_response including transmission config(dl_config, ul_config) and data transmission (tx_req)*/
int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config); int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config);
int8_t nr_ue_sl_phy_config_request(nr_sl_phy_config_t *phy_config);
/**\brief NR UE FAPI message to schedule a synchronization with target gNB /**\brief NR UE FAPI message to schedule a synchronization with target gNB
\param synch_request including target_Nid_cell*/ \param synch_request including target_Nid_cell*/
......
...@@ -99,3 +99,66 @@ int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_frame, int nr_slot) ...@@ -99,3 +99,66 @@ int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_frame, int nr_slot)
} }
} }
} }
/*
* This function determines if the mixed slot is a Sidelink slot
*/
uint8_t sl_determine_if_sidelink_slot(uint8_t sl_startsym, uint8_t sl_lensym, uint8_t num_ulsym) {
uint8_t ul_startsym = NR_NUMBER_OF_SYMBOLS_PER_SLOT - num_ulsym;
if ((sl_startsym >= ul_startsym) && (sl_lensym <= NR_NUMBER_OF_SYMBOLS_PER_SLOT)) {
LOG_D(MAC,"MIXED SLOT is a SIDELINK SLOT. Sidelink Symbols: %d-%d, Uplink Symbols: %d-%d\n",
sl_startsym,sl_lensym-1,
ul_startsym, ul_startsym+num_ulsym-1);
return NR_SIDELINK_SLOT;
}
else {
LOG_D(MAC,"MIXED SLOT is NOT SIDELINK SLOT. Sidelink Symbols: %d-%d, Uplink Symbols: %d-%d\n",
sl_startsym,sl_lensym-1,
ul_startsym, ul_startsym+num_ulsym-1);
return 0;
}
}
/*
* This function determines if the Slot is a SIDELINK SLOT
* Every Uplink Slot is a Sidelink slot
* Mixed Slot is a sidelink slot if the uplink symbols in Mixed slot
* overlaps with Sidelink start symbol and number of symbols.
*/
int sl_nr_ue_slot_select(sl_nr_phy_config_request_t *cfg,
int nr_frame, int nr_slot,
uint8_t frame_duplex_type)
{
int mu = cfg->sl_bwp_config.sl_scs, ul_sym = 0, slot_type = 0;
//All PC5 bands are TDD bands , hence handling only TDD in this function.
AssertFatal(frame_duplex_type == TDD, "No Sidelink operation defined for FDD in 3GPP rel16\n");
if (cfg->tdd_table.max_tdd_periodicity_list == NULL) { // this happens before receiving TDD configuration
return 0;
}
int slot = (nr_frame%2 == 0) ? nr_slot : ((1<<mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME) + nr_slot;
for(int symbol_count=0; symbol_count<NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) {
if (cfg->tdd_table.max_tdd_periodicity_list[slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 1) {
ul_sym++;
}
}
if(ul_sym == NR_NUMBER_OF_SYMBOLS_PER_SLOT) {
slot_type = NR_SIDELINK_SLOT;
} else if (ul_sym){
slot_type = sl_determine_if_sidelink_slot(cfg->sl_bwp_config.sl_start_symbol,
cfg->sl_bwp_config.sl_num_symbols,
ul_sym);
}
return slot_type;
}
\ No newline at end of file
...@@ -49,6 +49,7 @@ void nr_fill_sl_indication(nr_sidelink_indication_t *sl_ind, ...@@ -49,6 +49,7 @@ void nr_fill_sl_indication(nr_sidelink_indication_t *sl_ind,
sl_ind->frame_tx = proc->frame_tx; sl_ind->frame_tx = proc->frame_tx;
sl_ind->slot_tx = proc->nr_slot_tx; sl_ind->slot_tx = proc->nr_slot_tx;
sl_ind->phy_data = phy_data; sl_ind->phy_data = phy_data;
sl_ind->slot_type = SIDELINK_SLOT_TYPE_RX;
if (rx_ind) { if (rx_ind) {
sl_ind->rx_ind = rx_ind; // hang on rx_ind instance sl_ind->rx_ind = rx_ind; // hang on rx_ind instance
......
...@@ -49,3 +49,12 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, ...@@ -49,3 +49,12 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id,
const channel_t channel, const channel_t channel,
const uint8_t* pduP, const uint8_t* pduP,
const sdu_size_t pdu_len) { return 0; } const sdu_size_t pdu_len) { return 0; }
int8_t nr_mac_rrc_sl_mib_ind(const module_id_t module_id,
const int CC_id,
const uint8_t gNB_index,
const frame_t frame,
const int slot,
const int channel,
const uint8_t* pduP,
const sdu_size_t pdu_len,
const uint16_t rx_slss_id) {return 1;}
...@@ -65,6 +65,10 @@ int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, ...@@ -65,6 +65,10 @@ int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP,
nr_bler_struct nr_bler_data[NR_NUM_MCS]; nr_bler_struct nr_bler_data[NR_NUM_MCS];
void get_nrUE_params(void) { return;} void get_nrUE_params(void) { return;}
uint8_t check_if_ue_is_sl_syncsource() {return 0;} uint8_t check_if_ue_is_sl_syncsource() {return 0;}
void nr_rrc_mac_config_req_sl_mib(module_id_t module_id,
NR_SL_SSB_TimeAllocation_r16_t *ssb_ta,
uint16_t rx_slss_id,
uint8_t *sl_mib) {}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
static void prepare_mib_bits(uint8_t *buf, uint32_t frame_tx, uint32_t slot_tx) { static void prepare_mib_bits(uint8_t *buf, uint32_t frame_tx, uint32_t slot_tx) {
......
...@@ -86,7 +86,7 @@ static int sl_set_tdd_config_nr_ue(sl_nr_phy_config_request_t *cfg, ...@@ -86,7 +86,7 @@ static int sl_set_tdd_config_nr_ue(sl_nr_phy_config_request_t *cfg,
if (nrofDownlinkSymbols) nrofDownlinkSlots -= 1; 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", LOG_I(NR_MAC,"Set Phy Sidelink TDD Config: scs:%d,dl:%d-%d, ul:%d-%d, nb_periods_per_frame:%d, nb_slots_per_period:%d\n",
mu, nrofDownlinkSlots, nrofDownlinkSymbols, nrofUplinkSlots, nrofUplinkSymbols, nb_periods_per_frame, nb_slots_per_period); mu, nrofDownlinkSlots, nrofDownlinkSymbols, nrofUplinkSlots, nrofUplinkSymbols, nb_periods_per_frame, nb_slots_per_period);
if ( (nrofDownlinkSymbols + nrofUplinkSymbols) == 0 ) if ( (nrofDownlinkSymbols + nrofUplinkSymbols) == 0 )
...@@ -436,6 +436,9 @@ int nr_rrc_mac_config_req_sl_preconfig(module_id_t module_id, ...@@ -436,6 +436,9 @@ int nr_rrc_mac_config_req_sl_preconfig(module_id_t module_id,
AssertFatal((tdd_uldl_config->pattern2 == NULL), "Sidelink MAC CFG: pattern2 not yet supported"); 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; sl_mac->sl_TDD_config = sl_preconfig->sl_PreconfigGeneral_r16->sl_TDD_Configuration_r16;
//Sync source is identified, timing needs to be adjusted.
sl_mac->adjust_timing = 1;
} }
//Do not copy TDD config yet as SYNC source is not yet found //Do not copy TDD config yet as SYNC source is not yet found
...@@ -538,12 +541,13 @@ void nr_rrc_mac_config_req_sl_mib(module_id_t module_id, ...@@ -538,12 +541,13 @@ void nr_rrc_mac_config_req_sl_mib(module_id_t module_id,
sl_nr_phy_config_request_t *sl_config = &sl_mac->sl_phy_config.sl_config_req; 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 //Update configs if Sync source is not set else nothing to be done
if ( sl_config->sl_sync_source.sync_source == SL_SYNC_SOURCE_NONE) { if (sl_config->sl_sync_source.sync_source == SL_SYNC_SOURCE_NONE) {
//Set SYNC source as SYNC REF UE and send the remaining config to PHY //Set SYNC source as SYNC REF UE and send the remaining config to PHY
sl_config->config_mask = 0xF;//all configs done. 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.sync_source = SL_SYNC_SOURCE_SYNC_REF_UE;
sl_config->sl_sync_source.rx_slss_id = rx_slss_id; sl_config->sl_sync_source.rx_slss_id = rx_slss_id;
sl_mac->adjust_timing = 1;
sl_mac->rx_sl_bch.status = 1; sl_mac->rx_sl_bch.status = 1;
sl_mac->rx_sl_bch.slss_id = rx_slss_id; sl_mac->rx_sl_bch.slss_id = rx_slss_id;
...@@ -603,6 +607,8 @@ void nr_rrc_mac_config_req_sl_mib(module_id_t module_id, ...@@ -603,6 +607,8 @@ void nr_rrc_mac_config_req_sl_mib(module_id_t module_id,
sl_mac->sl_TDD_config->pattern1.nrofDownlinkSlots, sl_mac->sl_TDD_config->pattern1.nrofUplinkSlots, sl_mac->sl_TDD_config->pattern1.nrofDownlinkSlots, sl_mac->sl_TDD_config->pattern1.nrofUplinkSlots,
sl_mac->sl_TDD_config->pattern1.nrofDownlinkSymbols,sl_mac->sl_TDD_config->pattern1.nrofUplinkSymbols); 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);
} }
} }
\ No newline at end of file
...@@ -33,10 +33,15 @@ ...@@ -33,10 +33,15 @@
#define SL_NR_MAC_NUM_TX_RESOURCE_POOLS 1 #define SL_NR_MAC_NUM_TX_RESOURCE_POOLS 1
#define SL_NUM_BYTES_TIMERESOURCEBITMAP 20 #define SL_NUM_BYTES_TIMERESOURCEBITMAP 20
//every 16 frames, SSB is repeated.
#define SL_NR_SSB_REPETITION_IN_FRAMES 16
#define SL_FRAME_NUMBER_CYCLE 1024
// Size of Fixed fields prio (3), sci_2ndstage(2), // Size of Fixed fields prio (3), sci_2ndstage(2),
// betaoffsetindicator(2), num dmrs ports (1), mcs (5bits) // betaoffsetindicator(2), num dmrs ports (1), mcs (5bits)
#define SL_SCI_FORMAT_1A_LEN_IN_BITS_FIXED_FIELDS 13 #define SL_SCI_FORMAT_1A_LEN_IN_BITS_FIXED_FIELDS 13
#define sci_field_t dci_field_t #define sci_field_t dci_field_t
typedef struct sidelink_sci_format_1a_fields { typedef struct sidelink_sci_format_1a_fields {
...@@ -150,6 +155,22 @@ typedef struct sl_nr_ue_mac_params { ...@@ -150,6 +155,22 @@ typedef struct sl_nr_ue_mac_params {
//Holds Broadcast params incase UE receives SL-SSB //Holds Broadcast params incase UE receives SL-SSB
sl_bch_params_t rx_sl_bch; sl_bch_params_t rx_sl_bch;
//SSB RSRP in dBm
int16_t ssb_rsrp_dBm;
//Bitmap indicating which slots belong to sidelink
//Right now supports 30Khz and 15Khz
uint32_t sl_slot_bitmap;
//adjust timing after new timing from sync is acquired.
uint8_t adjust_timing;
//Sidelink slots per frame
uint16_t N_SL_SLOTS_perframe;
uint16_t decoded_DFN;
uint16_t decoded_slot;
} sl_nr_ue_mac_params_t; } sl_nr_ue_mac_params_t;
......
...@@ -113,6 +113,8 @@ void nr_ue_dl_scheduler(nr_downlink_indication_t *dl_info); ...@@ -113,6 +113,8 @@ void nr_ue_dl_scheduler(nr_downlink_indication_t *dl_info);
@param fapi_nr_dl_config_request_t* pointer to dl_config, @param fapi_nr_dl_config_request_t* pointer to dl_config,
@param fapi_nr_ul_config_request_t* pointer to ul_config, @param fapi_nr_ul_config_request_t* pointer to ul_config,
@param fapi_nr_tx_request_t* pointer to tx_request; @param fapi_nr_tx_request_t* pointer to tx_request;
@param sl_nr_rx_config_request_t* pointer to sl_rx_config,
@param sl_nr_tx_config_request_t* pointer to sl_tx_config,
@param module_id_t mod_id module ID @param module_id_t mod_id module ID
@param int cc_id CC ID @param int cc_id CC ID
@param frame_t frame frame number @param frame_t frame frame number
...@@ -122,6 +124,8 @@ void fill_scheduled_response(nr_scheduled_response_t *scheduled_response, ...@@ -122,6 +124,8 @@ void fill_scheduled_response(nr_scheduled_response_t *scheduled_response,
fapi_nr_dl_config_request_t *dl_config, fapi_nr_dl_config_request_t *dl_config,
fapi_nr_ul_config_request_t *ul_config, fapi_nr_ul_config_request_t *ul_config,
fapi_nr_tx_request_t *tx_request, fapi_nr_tx_request_t *tx_request,
sl_nr_rx_config_request_t *sl_rx_config,
sl_nr_tx_config_request_t *sl_tx_config,
module_id_t mod_id, module_id_t mod_id,
int cc_id, int cc_id,
frame_t frame, frame_t frame,
...@@ -443,6 +447,7 @@ void nr_rrc_mac_config_req_sl_mib(module_id_t module_id, ...@@ -443,6 +447,7 @@ void nr_rrc_mac_config_req_sl_mib(module_id_t module_id,
NR_SL_SSB_TimeAllocation_r16_t *ssb_ta, NR_SL_SSB_TimeAllocation_r16_t *ssb_ta,
uint16_t rx_slss_id, uint16_t rx_slss_id,
uint8_t *sl_mib); uint8_t *sl_mib);
void sl_prepare_psbch_payload(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config, 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 *bits_0_to_7, uint8_t *bits_8_to_11,
uint8_t mu, uint8_t L, uint8_t Y); uint8_t mu, uint8_t L, uint8_t Y);
...@@ -454,5 +459,26 @@ uint8_t sl_decode_sl_TDD_Config(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config, ...@@ -454,5 +459,26 @@ uint8_t sl_decode_sl_TDD_Config(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config,
uint8_t sl_determine_sci_1a_len(uint16_t *num_subchannels, uint8_t sl_determine_sci_1a_len(uint16_t *num_subchannels,
NR_SL_ResourcePool_r16_t *rpool, NR_SL_ResourcePool_r16_t *rpool,
sidelink_sci_format_1a_fields_t *sci_1a); sidelink_sci_format_1a_fields_t *sci_1a);
/** \brief This function checks nr UE slot for Sidelink direction : Sidelink
* @param cfg : Sidelink config request
* @param nr_frame : frame number
* @param nr_slot : slot number
* @param frame duplex type : Frame type
@returns int : 0 or Sidelink slot type */
int sl_nr_ue_slot_select(sl_nr_phy_config_request_t *cfg,
int nr_frame, int nr_slot,
uint8_t frame_duplex_type);
void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind);
void nr_mac_rrc_sl_mib_ind(const module_id_t module_id,
const int CC_id,
const uint8_t gNB_index,
const frame_t frame,
const int slot,
const channel_t channel,
uint8_t* pduP,
const sdu_size_t pdu_len,
const uint16_t rx_slss_id);
#endif #endif
/** @}*/ /** @}*/
...@@ -19,7 +19,8 @@ ...@@ -19,7 +19,8 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
#include "mac_defs_sl.h" #include "mac_defs.h"
#include "mac_proto.h"
#define SL_DEBUG #define SL_DEBUG
...@@ -474,7 +475,7 @@ uint8_t sl_determine_sci_1a_len(uint16_t *num_subchannels, ...@@ -474,7 +475,7 @@ uint8_t sl_determine_sci_1a_len(uint16_t *num_subchannels,
} }
LOG_D(NR_MAC,"sci 1A - additional_table:%ld, sci 1a len:%d, additional table nbits:%d\n", LOG_D(NR_MAC,"sci 1A - additional_table:%ld, sci 1a len:%d, additional table nbits:%d\n",
*rpool->sl_Additional_MCS_Table_r16, rpool->sl_Additional_MCS_Table_r16 ? *rpool->sl_Additional_MCS_Table_r16 : 0,
sci_1a_len, sci_1a_len,
sci_1a->additional_mcs_table_indicator.nbits); sci_1a->additional_mcs_table_indicator.nbits);
...@@ -520,4 +521,57 @@ uint8_t sl_determine_sci_1a_len(uint16_t *num_subchannels, ...@@ -520,4 +521,57 @@ uint8_t sl_determine_sci_1a_len(uint16_t *num_subchannels,
LOG_D(NR_MAC,"sci 1A Length in bits: %d \n",sci_1a_len); LOG_D(NR_MAC,"sci 1A Length in bits: %d \n",sci_1a_len);
return sci_1a_len; return sci_1a_len;
} }
\ No newline at end of file
/* This function determines the number of sidelink slots in 1024 frames - DFN cycle
* which can be used for determining reserved slots and REsource pool slots according to bitmap.
* Sidelink slots are the uplink and mixed slots with sidelink support except the SSB slots.
*/
uint32_t sl_determine_num_sidelink_slots(uint8_t mod_id, uint16_t *N_SSB_16frames, uint16_t *N_SL_SLOTS_perframe)
{
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
uint32_t N_SSB_1024frames = 0;
uint32_t N_SL_SLOTS = 0;
*N_SL_SLOTS_perframe = 0;
*N_SSB_16frames = 0;
if (sl_mac->rx_sl_bch.status) {
sl_ssb_timealloc_t *ssb_timealloc = &sl_mac->rx_sl_bch.ssb_time_alloc;
*N_SSB_16frames += ssb_timealloc->sl_NumSSB_WithinPeriod;
LOG_D(MAC, "RX SSB Slots:%d\n", *N_SSB_16frames);
}
if (sl_mac->tx_sl_bch.status) {
sl_ssb_timealloc_t *ssb_timealloc = &sl_mac->tx_sl_bch.ssb_time_alloc;
*N_SSB_16frames += ssb_timealloc->sl_NumSSB_WithinPeriod;
LOG_D(MAC, "TX SSB Slots:%d\n", *N_SSB_16frames);
}
//Total SSB slots in SFN cycle (1024 frames)
N_SSB_1024frames = SL_FRAME_NUMBER_CYCLE/SL_NR_SSB_REPETITION_IN_FRAMES * (*N_SSB_16frames);
sl_nr_phy_config_request_t *sl_cfg = &sl_mac->sl_phy_config.sl_config_req;
uint8_t sl_scs = sl_cfg->sl_bwp_config.sl_scs;
uint8_t num_slots_per_frame = 10*(1<<sl_scs);
uint8_t slot_type = 0;
for (int i=0; i<num_slots_per_frame;i++) {
slot_type = sl_nr_ue_slot_select(sl_cfg, 0, i, TDD);
if (slot_type == NR_SIDELINK_SLOT) {
*N_SL_SLOTS_perframe = *N_SL_SLOTS_perframe + 1;
sl_mac->sl_slot_bitmap |= (1<<i);
}
}
//Determine total number of Valid Sidelink slots which can be used for Respool in a SFN cycle (1024 frames)
N_SL_SLOTS = (*N_SL_SLOTS_perframe * SL_FRAME_NUMBER_CYCLE) - N_SSB_1024frames;
LOG_I(MAC, "[UE%d]SL-MAC:SSB slots in 1024 frames:%d, N_SL_SLOTS_perframe:%d, N_SL_SLOTs in 1024 frames:%d, SL SLOT bitmap:%x\n",
mod_id,N_SSB_1024frames, *N_SL_SLOTS_perframe,
N_SL_SLOTS, sl_mac->sl_slot_bitmap);
return N_SL_SLOTS;
}
...@@ -87,6 +87,8 @@ void fill_scheduled_response(nr_scheduled_response_t *scheduled_response, ...@@ -87,6 +87,8 @@ void fill_scheduled_response(nr_scheduled_response_t *scheduled_response,
fapi_nr_dl_config_request_t *dl_config, fapi_nr_dl_config_request_t *dl_config,
fapi_nr_ul_config_request_t *ul_config, fapi_nr_ul_config_request_t *ul_config,
fapi_nr_tx_request_t *tx_request, fapi_nr_tx_request_t *tx_request,
sl_nr_rx_config_request_t *sl_rx_config,
sl_nr_tx_config_request_t *sl_tx_config,
module_id_t mod_id, module_id_t mod_id,
int cc_id, int cc_id,
frame_t frame, frame_t frame,
...@@ -101,6 +103,8 @@ void fill_scheduled_response(nr_scheduled_response_t *scheduled_response, ...@@ -101,6 +103,8 @@ void fill_scheduled_response(nr_scheduled_response_t *scheduled_response,
scheduled_response->frame = frame; scheduled_response->frame = frame;
scheduled_response->slot = slot; scheduled_response->slot = slot;
scheduled_response->phy_data = phy_data; scheduled_response->phy_data = phy_data;
scheduled_response->sl_rx_config = sl_rx_config;
scheduled_response->sl_tx_config = sl_tx_config;
} }
...@@ -970,7 +974,7 @@ void nr_ue_dl_scheduler(nr_downlink_indication_t *dl_info) ...@@ -970,7 +974,7 @@ void nr_ue_dl_scheduler(nr_downlink_indication_t *dl_info)
} }
dcireq.dl_config_req = *dl_config; dcireq.dl_config_req = *dl_config;
fill_scheduled_response(&scheduled_response, &dcireq.dl_config_req, NULL, NULL, mod_id, cc_id, rx_frame, rx_slot, dl_info->phy_data); fill_scheduled_response(&scheduled_response, &dcireq.dl_config_req, NULL, NULL, NULL, NULL,mod_id, cc_id, rx_frame, rx_slot, dl_info->phy_data);
if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) { if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) {
LOG_D(NR_MAC,"1# scheduled_response transmitted, %d, %d\n", rx_frame, rx_slot); LOG_D(NR_MAC,"1# scheduled_response transmitted, %d, %d\n", rx_frame, rx_slot);
mac->if_module->scheduled_response(&scheduled_response); mac->if_module->scheduled_response(&scheduled_response);
...@@ -1079,7 +1083,7 @@ void nr_ue_ul_scheduler(nr_uplink_indication_t *ul_info) ...@@ -1079,7 +1083,7 @@ void nr_ue_ul_scheduler(nr_uplink_indication_t *ul_info)
} }
} }
pthread_mutex_unlock(&ul_config->mutex_ul_config); // avoid double lock pthread_mutex_unlock(&ul_config->mutex_ul_config); // avoid double lock
fill_scheduled_response(&scheduled_response, NULL, ul_config, &tx_req, mod_id, cc_id, frame_tx, slot_tx, ul_info->phy_data); fill_scheduled_response(&scheduled_response, NULL, ul_config, &tx_req, NULL, NULL,mod_id, cc_id, frame_tx, slot_tx, ul_info->phy_data);
if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){ if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){
LOG_D(NR_MAC,"3# scheduled_response transmitted,%d, %d\n", frame_tx, slot_tx); LOG_D(NR_MAC,"3# scheduled_response transmitted,%d, %d\n", frame_tx, slot_tx);
mac->if_module->scheduled_response(&scheduled_response); mac->if_module->scheduled_response(&scheduled_response);
...@@ -2190,7 +2194,7 @@ void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, vo ...@@ -2190,7 +2194,7 @@ void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, vo
&pucch[j], &pucch[j],
pucch_pdu); pucch_pdu);
nr_scheduled_response_t scheduled_response; nr_scheduled_response_t scheduled_response;
fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, module_idP, 0 /*TBR fix*/, frameP, slotP, phy_data); fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, NULL, NULL,module_idP, 0 /*TBR fix*/, frameP, slotP, phy_data);
if (mac->if_module != NULL && mac->if_module->scheduled_response != NULL) if (mac->if_module != NULL && mac->if_module->scheduled_response != NULL)
mac->if_module->scheduled_response(&scheduled_response); mac->if_module->scheduled_response(&scheduled_response);
if (mac->state == UE_WAIT_TX_ACK_MSG4) if (mac->state == UE_WAIT_TX_ACK_MSG4)
...@@ -2639,7 +2643,7 @@ static void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_fr ...@@ -2639,7 +2643,7 @@ static void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_fr
prach_config_pdu->prach_tx_power = get_prach_tx_power(module_idP); prach_config_pdu->prach_tx_power = get_prach_tx_power(module_idP);
set_ra_rnti(mac, prach_config_pdu); set_ra_rnti(mac, prach_config_pdu);
fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, module_idP, 0 /*TBR fix*/, frameP, slotP, NULL); fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, NULL, NULL,module_idP, 0 /*TBR fix*/, frameP, slotP, NULL);
if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL)
mac->if_module->scheduled_response(&scheduled_response); mac->if_module->scheduled_response(&scheduled_response);
...@@ -3116,3 +3120,298 @@ void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UL_TIME_ALIG ...@@ -3116,3 +3120,298 @@ void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UL_TIME_ALIG
dl_config->number_pdus += 1; dl_config->number_pdus += 1;
ul_time_alignment->ta_apply = false; ul_time_alignment->ta_apply = false;
} }
uint16_t sl_adjust_ssb_indices(sl_ssb_timealloc_t *ssb_timealloc,
uint32_t slot_in_16frames,
uint16_t *ssb_slot_ptr) {
uint16_t ssb_slot = ssb_timealloc->sl_TimeOffsetSSB;
uint16_t numssb = 0;
*ssb_slot_ptr = 0;
if (ssb_timealloc->sl_NumSSB_WithinPeriod == 0) {
*ssb_slot_ptr = 0;
return 0;
}
while (slot_in_16frames > ssb_slot) {
numssb = numssb + 1;
if (numssb < ssb_timealloc->sl_NumSSB_WithinPeriod)
ssb_slot = ssb_slot + ssb_timealloc->sl_TimeInterval;
else
break;
}
*ssb_slot_ptr = ssb_slot;
return numssb;
}
/*
* This function calculates the indices based on the new timing (frame,slot)
* acquired by the UE.
* NUM SSB, SLOT_SSB needs to be calculated based on current timing
*/
void sl_adjust_indices_based_on_timing(uint32_t frame, uint32_t slot,
uint32_t frame_tx, uint32_t slot_tx,
uint16_t mod_id, uint16_t slots_per_frame)
{
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
uint16_t frame_16 = frame % SL_NR_SSB_REPETITION_IN_FRAMES;
uint32_t slot_in_16frames = (frame_16 * slots_per_frame) + slot;
uint16_t frame_tx_16 = frame_tx % SL_NR_SSB_REPETITION_IN_FRAMES;
uint32_t slot_tx_in_16frames = (frame_tx_16 * slots_per_frame) + slot_tx;
LOG_I(NR_MAC,"[UE%d]PSBCH params adjusted based on RX current timing %d:%d. frame_16:%d, slot_in_16frames:%d\n",
mod_id, frame, slot, frame_16, slot_in_16frames);
LOG_I(NR_MAC,"[UE%d]PSBCH params adjusted based on TX current timing %d:%d. frame_16:%d, slot_in_16frames:%d\n",
mod_id, frame_tx, slot_tx, frame_tx_16, slot_tx_in_16frames);
//Adjust PSBCH Indices based on current RX timing
sl_ssb_timealloc_t *ssb_timealloc = &sl_mac->rx_sl_bch.ssb_time_alloc;
sl_mac->rx_sl_bch.num_ssb = sl_adjust_ssb_indices(ssb_timealloc, slot_in_16frames, &sl_mac->rx_sl_bch.ssb_slot);
//Adjust PSBCH Indices based on current TX timing
ssb_timealloc = &sl_mac->tx_sl_bch.ssb_time_alloc;
sl_mac->tx_sl_bch.num_ssb = sl_adjust_ssb_indices(ssb_timealloc, slot_tx_in_16frames, &sl_mac->tx_sl_bch.ssb_slot);
LOG_I(NR_MAC,"[UE%d]PSBCH params adjusted based on RX current timing %d:%d. NumSSB:%d, ssb_slot:%d\n",
mod_id, frame, slot, sl_mac->rx_sl_bch.num_ssb,
sl_mac->rx_sl_bch.ssb_slot);
LOG_I(NR_MAC,"[UE%d]PSBCH params adjusted based on TX current timing %d:%d. NumSSB:%d, ssb_slot:%d\n",
mod_id, frame_tx, slot_tx, sl_mac->tx_sl_bch.num_ssb,
sl_mac->tx_sl_bch.ssb_slot);
}
/*
DETERMINE IF SLOT IS MARKED AS SSB SLOT
ACCORDING TO THE SSB TIME ALLOCATION PARAMETERS.
sl_numSSB_withinPeriod - NUM SSBS in 16frames
sl_timeoffset_SSB - time offset for first SSB at start of 16 frames cycle
sl_timeinterval - distance in slots between 2 SSBs
*/
uint8_t sl_determine_if_SSB_slot(uint16_t frame, uint16_t slot, uint16_t slots_per_frame,
sl_bch_params_t *sl_bch,
sl_sidelink_slot_type_t slot_type) {
uint16_t frame_16 = frame % SL_NR_SSB_REPETITION_IN_FRAMES;
uint32_t slot_in_16frames = (frame_16 * slots_per_frame) + slot;
uint16_t sl_NumSSB_WithinPeriod = sl_bch->ssb_time_alloc.sl_NumSSB_WithinPeriod;
uint16_t sl_TimeOffsetSSB = sl_bch->ssb_time_alloc.sl_TimeOffsetSSB;
uint16_t sl_TimeInterval = sl_bch->ssb_time_alloc.sl_TimeInterval;
uint16_t num_ssb = sl_bch->num_ssb, ssb_slot = sl_bch->ssb_slot;
LOG_D(NR_MAC, "%d:%d. slot_type:%d, num_ssb:%d,ssb_slot:%d, %d-%d-%d, status:%d\n",
frame, slot, slot_type,
sl_bch->num_ssb,sl_bch->ssb_slot,
sl_NumSSB_WithinPeriod, sl_TimeOffsetSSB, sl_TimeInterval, sl_bch->status);
if (sl_NumSSB_WithinPeriod && sl_bch->status) {
if (slot_in_16frames == sl_TimeOffsetSSB) {
num_ssb = 0;
ssb_slot = sl_TimeOffsetSSB;
}
if (num_ssb < sl_NumSSB_WithinPeriod && slot_in_16frames == ssb_slot) {
num_ssb += 1;
ssb_slot = (num_ssb < sl_NumSSB_WithinPeriod)
? (ssb_slot + sl_TimeInterval) : sl_TimeOffsetSSB;
//Update the time when the same slot with RX SLOT type is called
if (slot_type == SIDELINK_SLOT_TYPE_RX) {
sl_bch->ssb_slot = ssb_slot;
sl_bch->num_ssb = num_ssb;
}
LOG_D(NR_MAC, "%d:%d is a PSBCH SLOT. Slot type:%d Next PSBCH Slot:%d, num_ssb:%d\n",
frame, slot, slot_type,
sl_bch->ssb_slot,sl_bch->num_ssb);
return 1;
}
}
LOG_D(NR_MAC, "%d:%d is NOT a PSBCH SLOT. Next PSBCH Slot:%d, num_ssb:%d\n",
frame, slot, sl_bch->ssb_slot,sl_bch->num_ssb);
return 0;
}
/*
* determine if sidelink slot is a PSBCH slot
* If PSBCH rx slot and sync_source == SYNC_REF_UE
* TTI COMMAND = PSBCH RX
* if PSBCH tx slot and transmit SLSS == true
* TTI_COMMAND = PSBCH TX
* Sidelink UE can rx and tx a SSB however the SSB time
* allocation will be different
*/
uint8_t nr_ue_sl_psbch_scheduler(nr_sidelink_indication_t *sl_ind,
sl_nr_ue_mac_params_t *sl_mac_params,
sl_nr_rx_config_request_t *rx_config,
sl_nr_tx_config_request_t *tx_config,
uint8_t *config_type) {
uint8_t ret_status = 0, is_psbch_rx_slot = 0, is_psbch_tx_slot = 0;
uint16_t slot = sl_ind->slot_rx;
uint16_t frame = sl_ind->frame_rx;
// Schedule TX only if slot type is TX.
if (sl_ind->slot_type == SIDELINK_SLOT_TYPE_TX) {
slot = sl_ind->slot_tx;
frame = sl_ind->frame_tx;
}
sl_nr_phy_config_request_t *sl_cfg = &sl_mac_params->sl_phy_config.sl_config_req;
uint16_t scs = sl_cfg->sl_bwp_config.sl_scs;
uint16_t slots_per_frame = nr_slots_per_frame[scs];
LOG_D(NR_MAC,"[UE%d] SL-PSBCH SCHEDULER: Frame:SLOT %d:%d, slot_type:%d\n",
sl_ind->module_id, frame, slot,sl_ind->slot_type);
is_psbch_rx_slot = sl_determine_if_SSB_slot(frame, slot, slots_per_frame,
&sl_mac_params->rx_sl_bch,
sl_ind->slot_type);
if (is_psbch_rx_slot &&
sl_ind->slot_type == SIDELINK_SLOT_TYPE_RX) {
*config_type = SL_NR_CONFIG_TYPE_RX_PSBCH;
rx_config->number_pdus = 1;
rx_config->sfn = frame;
rx_config->slot = slot;
rx_config->sl_rx_config_list[0].pdu_type = *config_type;
LOG_I(NR_MAC, "[UE%d] TTI-%d:%d RX PSBCH REQ- rx_slss_id:%d, numSSB:%d, next slot_SSB:%d\n",
sl_ind->module_id,frame, slot,
sl_cfg->sl_sync_source.rx_slss_id,
sl_mac_params->rx_sl_bch.num_ssb,
sl_mac_params->rx_sl_bch.ssb_slot);
}
if (!is_psbch_rx_slot) {
is_psbch_tx_slot = sl_determine_if_SSB_slot(frame, slot, slots_per_frame,
&sl_mac_params->tx_sl_bch,
sl_ind->slot_type);
if (is_psbch_tx_slot &&
sl_ind->slot_type == SIDELINK_SLOT_TYPE_TX) {
*config_type = SL_NR_CONFIG_TYPE_TX_PSBCH;
tx_config->number_pdus = 1;
tx_config->sfn = frame;
tx_config->slot = slot;
tx_config->tx_config_list[0].pdu_type = *config_type;
tx_config->tx_config_list[0].tx_psbch_config_pdu.tx_slss_id = sl_mac_params->tx_sl_bch.slss_id;
tx_config->tx_config_list[0].tx_psbch_config_pdu.psbch_tx_power = 0;//TBD...
memcpy(tx_config->tx_config_list[0].tx_psbch_config_pdu.psbch_payload, sl_mac_params->tx_sl_bch.sl_mib, 4);
LOG_I(NR_MAC, "[UE%d] TTI-%d:%d TX PSBCH REQ- tx_slss_id:%d, sl-mib:%x, numSSB:%d, next SSB slot:%d\n",
sl_ind->module_id,frame, slot,
sl_mac_params->tx_sl_bch.slss_id,
(*(uint32_t *)tx_config->tx_config_list[0].tx_psbch_config_pdu.psbch_payload),
sl_mac_params->tx_sl_bch.num_ssb,
sl_mac_params->tx_sl_bch.ssb_slot);
}
}
ret_status = is_psbch_rx_slot | is_psbch_tx_slot;
LOG_D(NR_MAC,"[UE%d] SL-PSBCH SCHEDULER: %d:%d,is psbch slot:%d, config type:%d\n",
sl_ind->module_id,frame, slot, ret_status, *config_type);
return ret_status;
}
/*
// This function will be called only for SIDELINK CAPABLE SLOTS.
// UPLINK SLOT OR MIXED SLOT which is SIDELINK SLOT
//Determine if PSBCH SLOT and if PSBCH RX/TX should be done
// IF NOT PSBCH SLOT continue ahead
// IF RX RES POOL CONFIGURED
// Determine if SLOT is a RX RES POOL RESERVED
// OR RX RES POOL RESOURCE SLOT according to time resource bitmap
// IF resource slot PSCCH RX action should be done
// IF TX RES POOL CONFIGURED
// Determine if SLOT is a TX RES POOL RESERVED
// OR RX RES POOL RESOURCE SLOT according to time resource bitmap
// IF resource slot PSCCH TX action should be done in case TX is scheduled
// ELSE SENSING SHOULD BE DONE
// IF TX/RX ACTION SHOULD BE DONE in this slot
// SEND SIDELINK TX/RX CONFIG REQUEST TO PHY
*/
void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind) {
AssertFatal(sl_ind != NULL, "sl_indication cannot be NULL\n");
module_id_t mod_id = sl_ind->module_id;
frame_t frame = sl_ind->frame_rx;
slot_t slot = sl_ind->slot_rx;
if (sl_ind->slot_type == SIDELINK_SLOT_TYPE_TX) {
frame = sl_ind->frame_tx;
slot = sl_ind->slot_tx;
}
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
sl_nr_phy_config_request_t *sl_cfg = &sl_mac->sl_phy_config.sl_config_req;
uint8_t mu = sl_cfg->sl_bwp_config.sl_scs;
uint8_t slots_per_frame = nr_slots_per_frame[mu];
//Adjust indices as new timing is acquired
if (sl_mac->adjust_timing) {
sl_adjust_indices_based_on_timing(sl_ind->frame_rx, sl_ind->slot_rx,
sl_ind->frame_tx, sl_ind->slot_tx,
mod_id, slots_per_frame);
sl_mac->adjust_timing = 0;
}
sl_nr_rx_config_request_t rx_config;
sl_nr_tx_config_request_t tx_config;
rx_config.number_pdus = 0;
tx_config.number_pdus = 0;
nr_scheduled_response_t scheduled_response;
memset(&scheduled_response,0, sizeof(nr_scheduled_response_t));
uint8_t tti_action = 0, is_psbch_slot = 0;
// Check if PSBCH slot and PSBCH should be transmitted or Received
is_psbch_slot = nr_ue_sl_psbch_scheduler(sl_ind, sl_mac, &rx_config, &tx_config, &tti_action);
if (!is_psbch_slot) {
//Check if reserved slot or a sidelink resource configured in Rx/Tx resource pool timeresource bitmap
}
if (tti_action == SL_NR_CONFIG_TYPE_RX_PSBCH) {
fill_scheduled_response(&scheduled_response, NULL, NULL, NULL, &rx_config, NULL, mod_id, 0,frame, slot, sl_ind->phy_data);
}
if (tti_action == SL_NR_CONFIG_TYPE_TX_PSBCH) {
fill_scheduled_response(&scheduled_response, NULL, NULL, NULL, NULL, &tx_config, mod_id, 0,frame, slot, sl_ind->phy_data);
}
LOG_D(NR_MAC,"[UE%d]SL-SCHEDULER: TTI-RX-%d:%d, TX-%d:%d is_psbch_slot:%d TTIaction:%d\n",
mod_id,sl_ind->frame_rx, sl_ind->slot_rx,
sl_ind->frame_tx, sl_ind->slot_tx,
is_psbch_slot, tti_action);
if (tti_action) {
if ((mac->if_module != NULL) && (mac->if_module->scheduled_response != NULL))
mac->if_module->scheduled_response(&scheduled_response);
}
}
\ No newline at end of file
...@@ -1183,7 +1183,7 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info) ...@@ -1183,7 +1183,7 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info)
AssertFatal( nr_ue_if_module_inst[module_id] != NULL, "IF module is NULL!\n" ); AssertFatal( nr_ue_if_module_inst[module_id] != NULL, "IF module is NULL!\n" );
AssertFatal( nr_ue_if_module_inst[module_id]->scheduled_response != NULL, "scheduled_response is NULL!\n" ); AssertFatal( nr_ue_if_module_inst[module_id]->scheduled_response != NULL, "scheduled_response is NULL!\n" );
fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, dl_info->slot); fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, dl_info->slot);
fill_scheduled_response(&scheduled_response, dl_config, NULL, NULL, dl_info->module_id, dl_info->cc_id, dl_info->frame, dl_info->slot, dl_info->phy_data); fill_scheduled_response(&scheduled_response, dl_config, NULL, NULL, NULL, NULL,dl_info->module_id, dl_info->cc_id, dl_info->frame, dl_info->slot, dl_info->phy_data);
nr_ue_if_module_inst[module_id]->scheduled_response(&scheduled_response); nr_ue_if_module_inst[module_id]->scheduled_response(&scheduled_response);
memset(def_dci_pdu_rel15, 0, sizeof(*def_dci_pdu_rel15)); memset(def_dci_pdu_rel15, 0, sizeof(*def_dci_pdu_rel15));
} }
...@@ -1262,6 +1262,10 @@ nr_ue_if_module_t *nr_ue_if_module_init(uint32_t module_id){ ...@@ -1262,6 +1262,10 @@ nr_ue_if_module_t *nr_ue_if_module_init(uint32_t module_id){
nr_ue_if_module_inst[module_id]->current_slot = 0; nr_ue_if_module_inst[module_id]->current_slot = 0;
nr_ue_if_module_inst[module_id]->phy_config_request = nr_ue_phy_config_request; nr_ue_if_module_inst[module_id]->phy_config_request = nr_ue_phy_config_request;
nr_ue_if_module_inst[module_id]->synch_request = nr_ue_synch_request; nr_ue_if_module_inst[module_id]->synch_request = nr_ue_synch_request;
if (get_softmodem_params()->sl_mode) {
nr_ue_if_module_inst[module_id]->sl_phy_config_request = nr_ue_sl_phy_config_request;
nr_ue_if_module_inst[module_id]->sl_indication = nr_ue_sl_indication;
}
if (get_softmodem_params()->emulate_l1) if (get_softmodem_params()->emulate_l1)
nr_ue_if_module_inst[module_id]->scheduled_response = nr_ue_scheduled_response_stub; nr_ue_if_module_inst[module_id]->scheduled_response = nr_ue_scheduled_response_stub;
else else
...@@ -1324,3 +1328,109 @@ void RCconfig_nr_ue_macrlc(void) { ...@@ -1324,3 +1328,109 @@ void RCconfig_nr_ue_macrlc(void) {
} }
} }
} }
static void handle_sl_bch(module_id_t module_id,uint8_t *const sl_mib,
const uint8_t len, uint16_t frame_rx,
uint16_t slot_rx,
uint16_t rx_slss_id)
{
LOG_D(NR_MAC," decode SL-MIB %d\n",rx_slss_id);
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
uint8_t sl_tdd_config[2] = {0,0};
sl_tdd_config[0] = sl_mib[0];
sl_tdd_config[1] = sl_mib[1] & 0xF0;
uint8_t incov = sl_mib[1] & 0x08;
uint16_t frame_0 = (sl_mib[2] & 0xFE) >> 1;
uint16_t frame_1 = sl_mib[1] & 0x07;
frame_0 |= (frame_1 & 0x01) << 7;
frame_1 = ((frame_1 & 0x06) >> 1) << 8;
uint16_t frame = frame_1 | frame_0;
uint8_t slot = ((sl_mib[2] & 0x01) << 6) | ((sl_mib[3] & 0xFC) >> 2);
LOG_I(NR_MAC, "[UE%d]In %d:%d Received SL-MIB:%x .Contents- SL-TDD config:%x, Incov:%d, FN:%d, Slot:%d\n",
module_id, frame_rx, slot_rx,*((uint32_t *)sl_mib),
*((uint16_t *)sl_tdd_config), incov,frame, slot);
sl_mac->decoded_DFN = frame;
sl_mac->decoded_slot = slot;
#define NR_SBCCH_SL_BCH 5
nr_mac_rrc_sl_mib_ind(module_id,0,0,frame_rx, slot_rx, NR_SBCCH_SL_BCH, sl_mib, len, rx_slss_id);
return ;
}
/*
if PSBCH rx - handle_psbch()
- Extract FN, Slot
- Extract TDD configuration from the 12 bits
- SEND THE SL-MIB to RRC
if PSSCH DATa rx - handle slsch()
*/
void sl_nr_process_rx_ind(uint16_t mod_id,
uint32_t frame, uint32_t slot,
sl_nr_ue_mac_params_t *sl_mac,
sl_nr_rx_indication_t *rx_ind)
{
uint8_t num_pdus = rx_ind->number_pdus;
uint8_t pdu_type = rx_ind->rx_indication_body[num_pdus-1].pdu_type;
switch (pdu_type){
case SL_NR_RX_PDU_TYPE_SSB:
if (rx_ind->rx_indication_body[num_pdus - 1].ssb_pdu.decode_status) {
LOG_I(NR_MAC, "[UE%d]SL-MAC Received SL-SSB: RSRP:%d dBm/RE, rx_psbch_payload:%x, rx_slss_id:%d\n",
mod_id,rx_ind->rx_indication_body[num_pdus - 1].ssb_pdu.rsrp_dbm,
*((uint32_t *)rx_ind->rx_indication_body[num_pdus - 1].ssb_pdu.psbch_payload),
rx_ind->rx_indication_body[num_pdus - 1].ssb_pdu.rx_slss_id);
handle_sl_bch(mod_id, rx_ind->rx_indication_body[num_pdus - 1].ssb_pdu.psbch_payload, 4, frame, slot,
rx_ind->rx_indication_body[num_pdus - 1].ssb_pdu.rx_slss_id);
sl_mac->ssb_rsrp_dBm = rx_ind->rx_indication_body[num_pdus - 1].ssb_pdu.rsrp_dbm;
} else {
LOG_I(NR_MAC, "[UE%d]SL-MAC - NO SL-SSB Received\n",mod_id);
}
break;
case SL_NR_RX_PDU_TYPE_SLSCH:
break;
default :
AssertFatal(1==0, "Incorrect type received. %s\n", __FUNCTION__);
break;
}
}
/*
* Sidelink indication is sent from PHY->MAC.
* This interface function handles these
* - rx_ind (SSB on PSBCH/SLSCH on PSSCH).
* - sci_ind (received scis during rxpool reception/txpool sensing)
*/
int nr_ue_sl_indication(nr_sidelink_indication_t *sl_indication)
{
//NR_UE_L2_STATE_t ret;
module_id_t module_id = sl_indication->module_id;
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
uint16_t slot = sl_indication->slot_rx;
uint16_t frame = sl_indication->frame_rx;
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
if (sl_indication->rx_ind) {
sl_nr_process_rx_ind(module_id, frame, slot, sl_mac, sl_indication->rx_ind);
} else {
nr_ue_sidelink_scheduler(sl_indication);
}
return 0;
}
...@@ -42,6 +42,16 @@ ...@@ -42,6 +42,16 @@
#include "NR_Packet_Drop.h" #include "NR_Packet_Drop.h"
#include "nfapi/open-nFAPI/nfapi/public_inc/sidelink_nr_ue_interface.h" #include "nfapi/open-nFAPI/nfapi/public_inc/sidelink_nr_ue_interface.h"
typedef enum sl_sidelink_slot_type {
SIDELINK_SLOT_TYPE_NONE = 0,
SIDELINK_SLOT_TYPE_RX,
SIDELINK_SLOT_TYPE_TX,
SIDELINK_SLOT_TYPE_BOTH
} sl_sidelink_slot_type_t;
extern slot_rnti_mcs_s slot_rnti_mcs[NUM_NFAPI_SLOT]; extern slot_rnti_mcs_s slot_rnti_mcs[NUM_NFAPI_SLOT];
typedef struct NR_UL_TIME_ALIGNMENT NR_UL_TIME_ALIGNMENT_t; typedef struct NR_UL_TIME_ALIGNMENT NR_UL_TIME_ALIGNMENT_t;
...@@ -126,6 +136,8 @@ typedef struct { ...@@ -126,6 +136,8 @@ typedef struct {
frame_t frame_tx; frame_t frame_tx;
/// slot tx /// slot tx
uint32_t slot_tx; uint32_t slot_tx;
//slot type rx or tx
sl_sidelink_slot_type_t slot_type;
/// NR UE FAPI-like P7 message, direction: L1 to L2 /// NR UE FAPI-like P7 message, direction: L1 to L2
/// data reception indication structure /// data reception indication structure
...@@ -244,7 +256,7 @@ typedef int8_t (nr_ue_phy_config_request_f)(nr_phy_config_t *phy_config); ...@@ -244,7 +256,7 @@ typedef int8_t (nr_ue_phy_config_request_f)(nr_phy_config_t *phy_config);
* -1: Failed to consume bytes. Abort the mission. * -1: Failed to consume bytes. Abort the mission.
* Non-negative return values indicate success, and ignored. * Non-negative return values indicate success, and ignored.
*/ */
typedef int8_t (nr_sl_ue_phy_config_request_f)(nr_sl_phy_config_t *sl_phy_config); typedef int8_t (nr_ue_sl_phy_config_request_f)(nr_sl_phy_config_t *sl_phy_config);
/* /*
* Generic type of an application-defined callback to return various * Generic type of an application-defined callback to return various
...@@ -285,6 +297,7 @@ typedef int (nr_ue_sl_indication_f)(nr_sidelink_indication_t *sl_info); ...@@ -285,6 +297,7 @@ typedef int (nr_ue_sl_indication_f)(nr_sidelink_indication_t *sl_info);
typedef struct nr_ue_if_module_s { typedef struct nr_ue_if_module_s {
nr_ue_scheduled_response_f *scheduled_response; nr_ue_scheduled_response_f *scheduled_response;
nr_ue_phy_config_request_f *phy_config_request; nr_ue_phy_config_request_f *phy_config_request;
nr_ue_sl_phy_config_request_f *sl_phy_config_request;
nr_ue_synch_request_f *synch_request; nr_ue_synch_request_f *synch_request;
nr_ue_dl_indication_f *dl_indication; nr_ue_dl_indication_f *dl_indication;
nr_ue_ul_indication_f *ul_indication; nr_ue_ul_indication_f *ul_indication;
...@@ -333,6 +346,8 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info); ...@@ -333,6 +346,8 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info);
int nr_ue_ul_indication(nr_uplink_indication_t *ul_info); int nr_ue_ul_indication(nr_uplink_indication_t *ul_info);
int nr_ue_sl_indication(nr_sidelink_indication_t *sl_indication);
int nr_ue_dcireq(nr_dcireq_t *dcireq); int nr_ue_dcireq(nr_dcireq_t *dcireq);
// TODO check // TODO check
......
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