diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpb200.sc-fdma.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpb200.sc-fdma.conf index 824c0a8cc2..c2960b3aa7 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpb200.sc-fdma.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpb200.sc-fdma.conf @@ -66,7 +66,7 @@ gNBs = initialULBWPsubcarrierSpacing = 1; #rach-ConfigCommon #rach-ConfigGeneric - prach_ConfigurationIndex = 98; + prach_ConfigurationIndex = 154; #prach_msg1_FDM #0 = one, 1=two, 2=four, 3=eight prach_msg1_FDM = 0; @@ -133,11 +133,21 @@ gNBs = # pattern1 # dl_UL_TransmissionPeriodicity # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 - dl_UL_TransmissionPeriodicity = 6; - nrofDownlinkSlots = 7; - nrofDownlinkSymbols = 6; - nrofUplinkSlots = 2; - nrofUplinkSymbols = 4; + # ext: 8=ms3, 9=ms4 + dl_UL_TransmissionPeriodicity = 8; + nrofDownlinkSlots = 3; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + # pattern2 + pattern2: { + dl_UL_TransmissionPeriodicity2 = 4; + nrofDownlinkSlots2 = 4; + nrofDownlinkSymbols2 = 0; + nrofUplinkSlots2 = 0; + nrofUplinkSymbols2 = 0; + }; ssPBCH_BlockPower = -25; } diff --git a/ci-scripts/xml_files/container_sa_sc_b200_quectel.xml b/ci-scripts/xml_files/container_sa_sc_b200_quectel.xml index a8515f3ec0..0c76a17eb9 100644 --- a/ci-scripts/xml_files/container_sa_sc_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_sc_b200_quectel.xml @@ -21,8 +21,8 @@ --> - TEST-SA-FR1-SC-FDMA-B200 - 40 MHz TDD SA with SC-FDMA + TEST-SA-FR1-SC-PATTERN2-FDMA-B200 + 40 MHz TDD (pattern2) SA with SC-FDMA tasks 300000 @@ -101,7 +101,7 @@ Deploy_Object - Deploy gNB (TDD/Band78/40MHz/B200) with SC-FDMA in a container + Deploy gNB (TDD/pattern2/Band78/40MHz/B200) with SC-FDMA in a container ci-scripts/yaml_files/sa_sc_b200_gnb 0 0 diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 1bac7e6da7..9b029657ad 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -704,9 +704,12 @@ uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t nrarfcn) return frequency; } -int get_first_ul_slot(int nrofDownlinkSlots, int nrofDownlinkSymbols, int nrofUplinkSymbols) +/** + * @brief Get the slot index within the period + */ +int get_slot_idx_in_period(const int slot, const frame_structure_t *fs) { - return (nrofDownlinkSlots + (nrofDownlinkSymbols != 0 && nrofUplinkSymbols == 0)); + return slot % fs->numb_slots_period; } int get_dmrs_port(int nl, uint16_t dmrs_ports) diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 7e7b15d13f..bdd10e7896 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -122,6 +122,29 @@ typedef enum frequency_range_e { FR2 } frequency_range_t; +#define MAX_NUM_SLOTS_ALLOWED 80 // up to numerology 3 (120 KHz SCS) is supported +enum slot_type { TDD_NR_DOWNLINK_SLOT, TDD_NR_UPLINK_SLOT, TDD_NR_MIXED_SLOT }; + +typedef struct tdd_bitmap { + enum slot_type slot_type; + uint8_t num_dl_symbols; + uint8_t num_ul_symbols; +} tdd_bitmap_t; + +typedef struct tdd_period_config_s { + tdd_bitmap_t tdd_slot_bitmap[MAX_NUM_SLOTS_ALLOWED]; + uint8_t num_dl_slots; + uint8_t num_ul_slots; +} tdd_period_config_t; + +typedef struct frame_structure_s { + tdd_period_config_t period_cfg; + int8_t numb_slots_frame; + int8_t numb_slots_period; + int8_t numb_period_frame; + bool is_tdd; +} frame_structure_t; + typedef struct { /// Time shift in number of samples estimated based on DMRS-PDSCH/PUSCH int est_delay; @@ -219,7 +242,6 @@ void reverse_bits_u8(uint8_t const* in, size_t sz, uint8_t* out); uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t dl_nrarfcn); uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, uint32_t bw); -int get_first_ul_slot(int nrofDownlinkSlots, int nrofDownlinkSymbols, int nrofUplinkSymbols); int cce_to_reg_interleaving(const int R, int k, int n_shift, const int C, int L, const int N_regs); int get_SLIV(uint8_t S, uint8_t L); void get_coreset_rballoc(uint8_t *FreqDomainResource,int *n_rb,int *rb_offset); @@ -265,6 +287,8 @@ int get_smallest_supported_bandwidth_index(int scs, frequency_range_t frequency_ unsigned short get_m_srs(int c_srs, int b_srs); unsigned short get_N_b_srs(int c_srs, int b_srs); +int get_slot_idx_in_period(const int slot, const frame_structure_t *fs); + #define CEILIDIV(a,b) ((a+b-1)/b) #define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1)) diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index 454faf1a1e..567187ac60 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -24,7 +24,9 @@ The following features are valid for the gNB and the 5G-NR UE. -* Static TDD, FDD +* Static TDD + - Multi TDD pattern supported refer [TDD Configuration](NR_SA_Multi_TDD_Pattern.md) +* Static FDD * Normal CP * Subcarrier spacings: 15 and 30kHz (FR1), 120kHz (FR2) * Bandwidths: 10, 20, 40, 60, 80, 100MHz diff --git a/doc/MAC/TDD_Frame_Structure.png b/doc/MAC/TDD_Frame_Structure.png new file mode 100644 index 0000000000..611be183d7 Binary files /dev/null and b/doc/MAC/TDD_Frame_Structure.png differ diff --git a/doc/MAC/mac-usage.md b/doc/MAC/mac-usage.md index c3dbd6f199..f96f94d522 100644 --- a/doc/MAC/mac-usage.md +++ b/doc/MAC/mac-usage.md @@ -240,3 +240,115 @@ here, *also they pertain to the DU*, i.e., the scheduler. options are 2, 4, 6, 8, 10, 12, 32; **32 is a Rel-17 features**) * `num_ulharq` (default 16): as `num_dlharq` for UL (other valid option is 32; **32 is i Rel-17 feature**) + +## ServingCellConfigCommon parameters + +The `gNBs` configuration section has a big structure `servingCellConfigCommon` +that has an influence on the overall behavior of MAC and L1. As the name says, +this structure is a flat representation of the ServingCellConfigCommon +structure, specified by 3GPP. Describing all of these parameters would be too +exhaustive; more information about the individual fields can be found in 3GPP +TS 38.331, section 6.3.2 "Radio resource control information elements". + +Below is a description of some of these parameters. + +### Frequency configuration + +There are many parameters, such as `absoluteFrequencySSB`, etc., that have an +impact on the frequency used by the gNB. For more information, please check the +[corresponding document](../gNB_frequency_setup.md). + +### TDD pattern configuration + +The TDD configuration parameters allow to use one or two TDD patterns. + +#### Single TDD pattern + +Configure the TDD pattern through these options: +- `dl_UL_TransmissionPeriodicity`: Refers to the UL/DL slots periodicity for + the TDD pattern. See below for valid numbers. +- `nrofDownlinkSlots`: Refers to the number of consecutive DL slots in the TDD + pattern. The number of DL slots depends on the TDD period. +- `nrofDownlinkSymbols`: Indicates the number of consecutive DL symbols within + the special slot that follows the downlink slots in the TDD pattern. The + special slot is needed only to switch from DL to UL. The maximum number of + symbols in this slot is 14. +- `nrofUplinkSlots`: Refers to the number of consecutive UL slots in the TDD + pattern, depending on the desired TDD period. +- `nrofUplinkSymbols`: Indicates the number of consecutive UL symbols within + the special slot that follows the downlink slots in the TDD pattern. The sum + of downlink and uplink symbols should not exceed 14. +- `prach_ConfigurationIndex`: index for PRACH according to tables 6.3.3.2-2 to + 6.3.3.2-4 in TS 38.211. + +As an example, the below figure shows a single TDD pattern, consisting of 3 DL +slots, 1 mixed slots (with 10 DL, 2 guard, 2 UL symbols), and 1 UL slot. + +![TDD Frame Structure](TDD_Frame_Structure.png) + +To configure this pattern in the configuration file, use + +```plaintext +#dl_UL_TransmissionPeriodicity 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10, 8=ms3, 9=ms4 + +dl_UL_TransmissionPeriodicity = 5; +nrofDownlinkSlots = 3; +nrofDownlinkSymbols = 10; +nrofUplinkSlots = 1; +nrofUplinkSymbols = 2; +``` + +The `dl_UL_TransmissionPeriodicity` is set to `5` (2.5ms). The above figure +shows two TDD periods over 5ms. The 10 ms frame period must be strictly +divisible by the sum of the TDD pattern periods. + +#### Two TDD patterns + +An optional `pattern2` structure is used to signal a TDD pattern 2. +In this case, the TDD pattern may have two extended values of 3 ms and 4 ms. +These values are standardized as `dl-UL-TransmissionPeriodicity-v1530`. For the +sake of simplicity of the gNB configuration file, we have extended the set of +`dl-UL-TransmissionPeriodicity` values to support the new TDD periods, as +explained in the table below. However, these values will later be encoded as +`dl-UL-TransmissionPeriodicity-v1530` to match the specifications. + +| `dl_UL_TransmissionPeriodicity` | TDD period | +|---------------------------------|------------| +| 0 | 0.5 ms | +| 1 | 0.625 ms | +| 2 | 1 ms | +| 3 | 1.25 ms | +| 4 | 2 ms | +| 5 | 2.5 ms | +| 6 | 5 ms | +| 7 | 10 ms | +| 8 | 3 ms | +| 9 | 4 ms | + +The 10 ms frame period must be strictly divisible by the sum of the TDD pattern +periods. For example, the 3 ms TDD pattern should be used with a second TDD +pattern of 2 ms. Additionally, the 4 ms TDD pattern should be used with a +second TDD pattern of 1 ms. + +As an example, this configuration might be used, where the first TDD pattern is +followed by a second, consisting of 4 DL slots. +``` +# pattern1 +# dl_UL_TransmissionPeriodicity +# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 +# ext: 8=ms3, 9=ms4 +dl_UL_TransmissionPeriodicity = 8; +nrofDownlinkSlots = 3; +nrofDownlinkSymbols = 6; +nrofUplinkSlots = 2; +nrofUplinkSymbols = 4; + +# pattern2 +pattern2: { + dl_UL_TransmissionPeriodicity2 = 4; + nrofDownlinkSlots2 = 4; + nrofDownlinkSymbols2 = 0; + nrofUplinkSlots2 = 0; + nrofUplinkSymbols2 = 0; +}; +``` diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index f82c6c414a..a34796eeb3 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -25,6 +25,7 @@ #define NFAPI_MAX_NUM_CB 8 #define NFAPI_MAX_NUM_PRGS 1 #define NFAPI_MAX_NUM_BG_IF 1 +#define NFAPI_MAX_NUM_PERIODS 8 // Extension to the generic structures for single tlv values @@ -436,7 +437,10 @@ typedef struct typedef struct { - nfapi_uint8_tlv_t tdd_period;//DL UL Transmission Periodicity. Value:0: ms0p5 1: ms0p625 2: ms1 3: ms1p25 4: ms2 5: ms2p5 6: ms5 7: ms10 8: ms3 9: ms4 + /**DL UL Transmission Periodicity: for multiple TDD pattern, + * the value corresponds to the sum periodicity (3GPP TS 38.213, 11.1) + * Values: 0:ms0p5 1:ms0p625 2:ms1 3:ms1p25 4:ms2 5:ms2p5 6:ms5 7:ms10 8:ms20 */ + nfapi_uint8_tlv_t tdd_period; nfapi_nr_max_tdd_periodicity_t* max_tdd_periodicity_list; } nfapi_nr_tdd_table_t; diff --git a/nfapi/open-nFAPI/pnf/src/pnf.c b/nfapi/open-nFAPI/pnf/src/pnf.c index f3e44663f8..3880e53c6c 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf.c +++ b/nfapi/open-nFAPI/pnf/src/pnf.c @@ -669,10 +669,6 @@ void pnf_nr_handle_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) { nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id); -#if 0 // emulate set_config TLV reception (hard-code) - int tdd_return = set_tdd_config_nr(&req, 1, 7, 6, 2, 4); -#endif - if(phy) { if(phy->state != NFAPI_PNF_PHY_RUNNING) diff --git a/openair1/SCHED_NR/phy_frame_config_nr.c b/openair1/SCHED_NR/phy_frame_config_nr.c index ad672bccb8..bff35ce4ff 100644 --- a/openair1/SCHED_NR/phy_frame_config_nr.c +++ b/openair1/SCHED_NR/phy_frame_config_nr.c @@ -44,108 +44,112 @@ #define NR_TST_PHY_PRINTF(...) #endif -/******************************************************************* -* -* NAME : set_tdd_configuration -* -* PARAMETERS : pointer to frame configuration -* -* OUTPUT: table of uplink symbol for each slot for 2 frames -* -* RETURN : nb_periods_per_frame if tdd has been properly configurated -* -1 tdd configuration can not be done -* -* DESCRIPTION : generate bit map for uplink symbol for each slot for several frames -* see TS 38.213 11.1 Slot configuration -* -*********************************************************************/ - -int set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, - int mu, - int nrofDownlinkSlots, - int nrofDownlinkSymbols, - int nrofUplinkSlots, - int nrofUplinkSymbols) +/** @brief This function processes TDD dedicated configuration for NR + * by processing the tdd_slot_bitmap and period_cfg, and + * allocates memory and fills max_num_of_symbol_per_slot_list + * in the nfapi config request (cfg) + * @ref see TS 38.213 11.1 Slot configuration + * @param cfg NR config request structure pointer + * @param fs TDD configuration pointer + * @returns void + */ +void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs) { + AssertFatal(fs != NULL, "frame_structure must be non-NULL"); + int slot_number = 0; - int nb_periods_per_frame = get_nb_periods_per_frame(cfg->tdd_table.tdd_period.value); - int nb_slots_to_set = (1 << mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME; + int nb_slots_to_set = fs->numb_slots_frame; + int slot_index = 0; + tdd_period_config_t *pc = &fs->period_cfg; + tdd_bitmap_t *tdd_slot_bitmap = pc->tdd_slot_bitmap; - int nb_slots_per_period = ((1 << mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME) / nb_periods_per_frame; - - if ((nrofDownlinkSymbols + nrofUplinkSymbols) == 0) - AssertFatal(nb_slots_per_period == (nrofDownlinkSlots + nrofUplinkSlots), - "set_tdd_configuration_nr: given period is inconsistent with current tdd configuration, nrofDownlinkSlots %d, " - "nrofUplinkSlots %d, nb_slots_per_period %d \n", - nrofDownlinkSlots, - nrofUplinkSlots, - nb_slots_per_period); - else { - AssertFatal(nrofDownlinkSymbols + nrofUplinkSymbols < 14, - "illegal symbol configuration DL %d, UL %d\n", - nrofDownlinkSymbols, - nrofUplinkSymbols); - AssertFatal(nb_slots_per_period == (nrofDownlinkSlots + nrofUplinkSlots + 1), - "set_tdd_configuration_nr: given period is inconsistent with current tdd configuration, nrofDownlinkSlots %d, " - "nrofUplinkSlots %d, nrofMixed slots 1, nb_slots_per_period %d \n", - nrofDownlinkSlots, - nrofUplinkSlots, - nb_slots_per_period); - } - - cfg->tdd_table.max_tdd_periodicity_list = calloc(nb_slots_to_set, sizeof(nfapi_nr_max_tdd_periodicity_t)); + LOG_I(NR_PHY, + "Set TDD Period Configuration: %d periods per frame, %d slots to be configured (%d DL, %d UL)\n", + fs->numb_period_frame, + nb_slots_to_set, + pc->num_dl_slots, + pc->num_ul_slots); + // Allocate memory formax_num_of_symbol_per_slot_list items + cfg->tdd_table.max_tdd_periodicity_list = calloc_or_fail(nb_slots_to_set, sizeof(nfapi_nr_max_tdd_periodicity_t)); for (int slot = 0; slot < nb_slots_to_set; slot++) { nfapi_nr_max_tdd_periodicity_t *p_list = &cfg->tdd_table.max_tdd_periodicity_list[slot]; p_list->max_num_of_symbol_per_slot_list = - calloc(NR_NUMBER_OF_SYMBOLS_PER_SLOT, sizeof(*p_list->max_num_of_symbol_per_slot_list)); + calloc_or_fail(NR_NUMBER_OF_SYMBOLS_PER_SLOT, sizeof(*p_list->max_num_of_symbol_per_slot_list)); for (int sym = 0; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { // for each symbol, assign the TLV tag for usage when packing p_list->max_num_of_symbol_per_slot_list[sym].slot_config.tl.tag = NFAPI_NR_CONFIG_SLOT_CONFIG_TAG; } } + // Loop through all periods to be configured while (slot_number != nb_slots_to_set) { - if (nrofDownlinkSlots != 0) { - for (int sym = 0; sym < nrofDownlinkSlots * NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { - cfg->tdd_table.max_tdd_periodicity_list[slot_number] - .max_num_of_symbol_per_slot_list[sym % NR_NUMBER_OF_SYMBOLS_PER_SLOT] - .slot_config.value = 0; - - if ((sym + 1) % NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0) + slot_index = get_slot_idx_in_period(slot_number, fs); + /* Fill max_tdd_periodicity_list */ + nfapi_nr_max_tdd_periodicity_t *list = &cfg->tdd_table.max_tdd_periodicity_list[slot_number]; + // FULL DOWNLINK SLOTS + if (tdd_slot_bitmap[slot_index].slot_type == TDD_NR_DOWNLINK_SLOT) { + for (int sym = 0; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { + list->max_num_of_symbol_per_slot_list[sym % NR_NUMBER_OF_SYMBOLS_PER_SLOT].slot_config.value = 0; + if ((sym + 1) % NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0) { slot_number++; + list += 1; + } } } - - if (nrofDownlinkSymbols != 0 || nrofUplinkSymbols != 0) { - for (int sym = 0; sym < nrofDownlinkSymbols; sym++) { - cfg->tdd_table.max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[sym].slot_config.value = 0; + // FLEXIBLE SLOTS + if (tdd_slot_bitmap[slot_index].slot_type == TDD_NR_MIXED_SLOT) { + int nrofDLSymbolsInSlot = tdd_slot_bitmap[slot_index].num_dl_symbols; + int nrofULSymbolsInSlot = tdd_slot_bitmap[slot_index].num_ul_symbols; + AssertFatal(nrofDLSymbolsInSlot + nrofULSymbolsInSlot < NR_NUMBER_OF_SYMBOLS_PER_SLOT, + "illegal symbol configuration DL %d, UL %d\n", + nrofDLSymbolsInSlot, + nrofULSymbolsInSlot); + // DL Symbols + for (int sym = 0; sym < nrofDLSymbolsInSlot; sym++) { + list->max_num_of_symbol_per_slot_list[sym].slot_config.value = 0; } - - for (int sym = nrofDownlinkSymbols; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofUplinkSymbols; sym++) { - cfg->tdd_table.max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[sym].slot_config.value = 2; + // Flexible Symbols + for (int sym = nrofDLSymbolsInSlot; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofULSymbolsInSlot; sym++) { + list->max_num_of_symbol_per_slot_list[sym].slot_config.value = 2; } - - for (int sym = NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofUplinkSymbols; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { - cfg->tdd_table.max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[sym].slot_config.value = 1; + // UL Symbols + for (int sym = NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofULSymbolsInSlot; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { + list->max_num_of_symbol_per_slot_list[sym].slot_config.value = 1; } - slot_number++; + list += 1; } - - if (nrofUplinkSlots != 0) { - for (int sym = 0; sym < nrofUplinkSlots * NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { - cfg->tdd_table.max_tdd_periodicity_list[slot_number] - .max_num_of_symbol_per_slot_list[sym % NR_NUMBER_OF_SYMBOLS_PER_SLOT] - .slot_config.value = 1; - - if ((sym + 1) % NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0) + // FULL UPLINK SLOTS + if (tdd_slot_bitmap[slot_index].slot_type == TDD_NR_UPLINK_SLOT) { + for (int sym = 0; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { + list->max_num_of_symbol_per_slot_list[sym % NR_NUMBER_OF_SYMBOLS_PER_SLOT].slot_config.value = 1; + if ((sym + 1) % NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0) { slot_number++; + list += 1; + } } } } - - return (nb_periods_per_frame); + // Dump 1 period on the output + for (int s = 0; s < fs->numb_slots_period; s++) { + if (tdd_slot_bitmap[s].slot_type == TDD_NR_MIXED_SLOT) { + char flexi_slot[NR_NUMBER_OF_SYMBOLS_PER_SLOT + 1]; + memset(flexi_slot, 0, sizeof(flexi_slot)); + for (int symb = 0; symb < NR_NUMBER_OF_SYMBOLS_PER_SLOT; symb++) { + uint8_t val = cfg->tdd_table.max_tdd_periodicity_list[s].max_num_of_symbol_per_slot_list[symb].slot_config.value; + char *symb_type_s[] = {"D", "U", "F"}; + flexi_slot[symb] = *symb_type_s[val]; + } + flexi_slot[NR_NUMBER_OF_SYMBOLS_PER_SLOT] = '\0'; + LOG_I(NR_PHY, "TDD period configuration: slot %d is FLEXIBLE: %s\n", s, flexi_slot); + } else { + LOG_I(NR_PHY, + "TDD period configuration: slot %d is %s\n", + s, + tdd_slot_bitmap[s].slot_type == TDD_NR_DOWNLINK_SLOT ? "DOWNLINK" : "UPLINK"); + } + } } /******************************************************************* @@ -389,3 +393,48 @@ void free_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms) { } } +void do_tdd_config_sim(PHY_VARS_gNB *gNB, int mu) +{ + frame_structure_t fs = {.is_tdd = true}; + fs.numb_slots_frame = (1 << mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME; + fs.numb_period_frame = get_nb_periods_per_frame(gNB->gNB_config.tdd_table.tdd_period.value); + fs.numb_slots_period = fs.numb_slots_frame / fs.numb_period_frame; + tdd_period_config_t *pc = &fs.period_cfg; + // Set DL/UL slots + switch (mu) + { + case 0: + pc->num_dl_slots = 3; + pc->num_ul_slots = 1; + break; + + case 1: + pc->num_dl_slots = 7; + pc->num_ul_slots = 2; + break; + + case 3: + pc->num_dl_slots = 27; + pc->num_ul_slots = 12; + break; + + default: + break; + } + for (int i = 0; i < pc->num_dl_slots; i++) { + pc->tdd_slot_bitmap[i].slot_type = TDD_NR_DOWNLINK_SLOT; + pc->tdd_slot_bitmap[i].num_dl_symbols = 0; + pc->tdd_slot_bitmap[i].num_ul_symbols = 0; + } + for (int i = pc->num_dl_slots; i < fs.numb_slots_period - pc->num_ul_slots; i++) { + pc->tdd_slot_bitmap[i].slot_type = TDD_NR_MIXED_SLOT; + pc->tdd_slot_bitmap[i].num_dl_symbols = 6; + pc->tdd_slot_bitmap[i].num_ul_symbols = 4; + } + for (int i = pc->num_ul_slots; i < fs.numb_slots_period; i++) { + pc->tdd_slot_bitmap[i].slot_type = TDD_NR_UPLINK_SLOT; + pc->tdd_slot_bitmap[i].num_dl_symbols = 0; + pc->tdd_slot_bitmap[i].num_ul_symbols = 0; + } + set_tdd_config_nr(&gNB->gNB_config, &fs); +} diff --git a/openair1/SCHED_NR/phy_frame_config_nr.h b/openair1/SCHED_NR/phy_frame_config_nr.h index b477b435f1..0caf612f37 100644 --- a/openair1/SCHED_NR/phy_frame_config_nr.h +++ b/openair1/SCHED_NR/phy_frame_config_nr.h @@ -36,18 +36,16 @@ /*************** FUNCTIONS *****************************************/ -/** \brief This function processes tdd dedicated configuration for nr - * @param frame_parms NR DL Frame parameters - * @param dl_UL_TransmissionPeriodicity periodicity - * @param nrofDownlinkSlots number of downlink slots - * @param nrofDownlinkSymbols number of downlink symbols - * @param nrofUplinkSlots number of uplink slots - * @param nrofUplinkSymbols number of uplink symbols - @returns 0 if tdd dedicated configuration has been properly set or -1 on error with message */ - -int set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, int mu, - int nrofDownlinkSlots, int nrofDownlinkSymbols, - int nrofUplinkSlots, int nrofUplinkSymbols); +/** @brief This function processes TDD dedicated configuration for NR + * by processing the tdd_slot_bitmap and period_cfg, and + * allocates memory and fills max_num_of_symbol_per_slot_list + * in the nfapi config request (cfg) + * @param cfg NR config request structure pointer + * @param fs frame structure pointer + * @returns nb_periods_per_frame if TDD has been properly configurated + * -1 tdd configuration can not be done + */ +void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs); /** \brief This function adds a slot configuration to current dedicated configuration for nr * @param frame_parms NR DL Frame parameters @@ -92,5 +90,7 @@ void free_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms); int get_next_downlink_slot(PHY_VARS_gNB *gNB, nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot); +void do_tdd_config_sim(PHY_VARS_gNB *gNB, int mu); + #endif /* PHY_FRAME_CONFIG_NR_H */ diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index b302faf3db..de5c598015 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -388,8 +388,9 @@ int main(int argc, char **argv) frame_parms->Ncp = extended_prefix_flag ? EXTENDED : NORMAL; crcTableInit(); nr_phy_config_request_sim(gNB, N_RB_DL, N_RB_DL, mu, Nid_cell,SSB_positions); - gNB->gNB_config.tdd_table.tdd_period.value = 6; - set_tdd_config_nr(&gNB->gNB_config, mu, 7, 6, 2, 4); + // TDD configuration + gNB->gNB_config.tdd_table.tdd_period.value = 6; + do_tdd_config_sim(gNB, mu); phy_init_nr_gNB(gNB); //init_eNB_afterRU(); frame_length_complex_samples = frame_parms->samples_per_subframe; diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 236913d3f8..fc09f23bd6 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -189,7 +189,7 @@ void nr_dlsim_preprocessor(module_id_t module_id, /* the following might override the table that is mandated by RRC * configuration */ current_BWP->mcsTableIdx = g_mcsTableIdx; - sched_pdsch->time_domain_allocation = get_dl_tda(RC.nrmac[module_id], scc, slot); + sched_pdsch->time_domain_allocation = get_dl_tda(RC.nrmac[module_id], slot); AssertFatal(sched_pdsch->time_domain_allocation >= 0,"Unable to find PDSCH time domain allocation in list\n"); sched_pdsch->tda_info = get_dl_tda_info(current_BWP, diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index b77b4ad786..b8ebf2bb30 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -448,13 +448,10 @@ int main(int argc, char **argv) frame_parms->freq_range = mu<2 ? FR1 : FR2; nr_phy_config_request_sim(gNB, N_RB_DL, N_RB_DL, mu, Nid_cell, SSB_positions); + // TDD configuration gNB->gNB_config.tdd_table.tdd_period.value = 6; - if (mu == 0) - set_tdd_config_nr(&gNB->gNB_config, mu, 3, 6, 1, 4); - else if (mu == 1) - set_tdd_config_nr(&gNB->gNB_config, mu, 7, 6, 2, 4); - else if (mu == 3) - set_tdd_config_nr(&gNB->gNB_config, mu, 27, 6, 12, 4); + do_tdd_config_sim(gNB, mu); + phy_init_nr_gNB(gNB); frame_parms->ssb_start_subcarrier = 12 * gNB->gNB_config.ssb_table.ssb_offset_point_a.value + ssb_subcarrier_offset; initFloatingCoresTpool(ssb_scan_threads, &nrUE_params.Tpool, false, "UE-tpool"); diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 8f644bf4c5..fd2c1bcf77 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -568,7 +568,10 @@ int main(int argc, char **argv){ memcpy((void*)&ru->config,(void*)&RC.gNB[0]->gNB_config,sizeof(ru->config)); RC.nb_nr_L1_inst=1; - set_tdd_config_nr(&gNB->gNB_config, mu, 7, 6, 2, 4); + // TDD configuration + gNB->gNB_config.tdd_table.tdd_period.value = 6; + do_tdd_config_sim(gNB, mu); + phy_init_nr_gNB(gNB); nr_phy_init_RU(ru); diff --git a/openair1/SIMULATION/NR_PHY/pucchsim.c b/openair1/SIMULATION/NR_PHY/pucchsim.c index 62aa21f5f7..bc022d5bc1 100644 --- a/openair1/SIMULATION/NR_PHY/pucchsim.c +++ b/openair1/SIMULATION/NR_PHY/pucchsim.c @@ -433,8 +433,10 @@ int main(int argc, char **argv) cfg->carrier_config.num_tx_ant.value = n_tx; cfg->carrier_config.num_rx_ant.value = n_rx; nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions); + // TDD configuration gNB->gNB_config.tdd_table.tdd_period.value = 6; - set_tdd_config_nr(&gNB->gNB_config, mu, 7, 6, 2, 4); + do_tdd_config_sim(gNB, mu); + phy_init_nr_gNB(gNB); /* RU handles rxdataF, and gNB just has a pointer. Here, we don't have an RU, * so we need to allocate that memory as well. */ diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index 19f48c5d3c..fcc986e92c 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -406,8 +406,10 @@ int main(int argc, char **argv) gNB->frame_parms.nb_antennas_rx = n_rx; nr_phy_config_request_sim(gNB, N_RB_UL, N_RB_UL, mu, Nid_cell, SSB_positions); + // TDD configuration gNB->gNB_config.tdd_table.tdd_period.value = 6; - set_tdd_config_nr(&gNB->gNB_config, mu, 7, 6, 2, 4); + do_tdd_config_sim(gNB, mu); + phy_init_nr_gNB(gNB); //configure UE diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c index 3e3caac9fe..854ef57d15 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c @@ -60,11 +60,11 @@ bool read_mac_sm(void* data) rd->dl_aggr_tbs = UE->mac_stats.dl.total_bytes; rd->ul_aggr_tbs = UE->mac_stats.ul.total_bytes; - if (is_xlsch_in_slot(RC.nrmac[mod_id]->dlsch_slot_bitmap[rd->slot / 64], rd->slot)) { + if (is_dl_slot(rd->slot, &RC.nrmac[mod_id]->frame_structure)) { rd->dl_curr_tbs = UE->mac_stats.dl.current_bytes; rd->dl_sched_rb = UE->mac_stats.dl.current_rbs; } - if (is_xlsch_in_slot(RC.nrmac[mod_id]->ulsch_slot_bitmap[rd->slot / 64], rd->slot)) { + if (is_ul_slot(rd->slot, &RC.nrmac[mod_id]->frame_structure)) { rd->ul_curr_tbs = UE->mac_stats.ul.current_bytes; rd->ul_sched_rb = sched_ctrl->sched_pusch.rbSize; } diff --git a/openair2/GNB_APP/RRC_nr_paramsvalues.h b/openair2/GNB_APP/RRC_nr_paramsvalues.h index 5b77da80b4..be2fd03542 100644 --- a/openair2/GNB_APP/RRC_nr_paramsvalues.h +++ b/openair2/GNB_APP/RRC_nr_paramsvalues.h @@ -116,6 +116,7 @@ #define GNB_CONFIG_STRING_NROFDOWNLINKSYMBOLS "nrofDownlinkSymbols" #define GNB_CONFIG_STRING_NROFUPLINKSLOTS "nrofUplinkSlots" #define GNB_CONFIG_STRING_NROFUPLINKSYMBOLS "nrofUplinkSymbols" +#define GNB_CONFIG_STRING_PATTERN2 "pattern2" #define GNB_CONFIG_STRING_DLULTRANSMISSIONPERIODICITY2 "dl_UL_TransmissionPeriodicity2" #define GNB_CONFIG_STRING_NROFDOWNLINKSLOTS2 "nrofDownlinkSlots2" #define GNB_CONFIG_STRING_NROFDOWNLINKSYMBOLS2 "nrofDownlinkSymbols2" @@ -247,11 +248,6 @@ {GNB_CONFIG_STRING_NROFDOWNLINKSYMBOLS,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols,.defint64val=6,TYPE_INT64,0},\ {GNB_CONFIG_STRING_NROFUPLINKSLOTS,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots,.defint64val=2,TYPE_INT64,0},\ {GNB_CONFIG_STRING_NROFUPLINKSYMBOLS,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols,.defint64val=4,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_DLULTRANSMISSIONPERIODICITY2,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity,.defintval=-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_NROFDOWNLINKSLOTS2,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots,.defint64val=-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_NROFDOWNLINKSYMBOLS2,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols,.defint64val=-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_NROFUPLINKSLOTS2,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofUplinkSlots,.defint64val=-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_NROFUPLINKSYMBOLS2,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofUplinkSymbols,.defint64val=-1,TYPE_INT64,0},\ {GNB_CONFIG_STRING_SSPBCHBLOCKPOWER,NULL,0,.i64ptr=&scc->ss_PBCH_BlockPower,.defint64val=20,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_CELLSPECIFICKOFFSET,NULL,0,.i64ptr=scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17,.defint64val=0,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_EPHEMERIS_POSITION_X,NULL,0,.i64ptr=&scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->positionX_r17,.defint64val=LONG_MAX,TYPE_INT64,0}, \ @@ -263,6 +259,15 @@ {GNB_CONFIG_STRING_TA_COMMON,NULL,0,.i64ptr=&scc->ext2->ntn_Config_r17->ta_Info_r17->ta_Common_r17,.defint64val=-1,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_MSG1SUBCARRIERSPACING,NULL,0,.i64ptr=scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing,.defintval=-1,TYPE_INT64,0}} +#define SCC_PATTERN2_STRING_CONFIG "pattern2" + +#define SCC_PATTERN2_PARAMS_DESC(pattern2) { \ +{GNB_CONFIG_STRING_DLULTRANSMISSIONPERIODICITY2, NULL,0,.i64ptr=&pattern2.dl_UL_TransmissionPeriodicity,.defint64val=-1,TYPE_INT64,0},\ +{GNB_CONFIG_STRING_NROFDOWNLINKSLOTS2, NULL,0,.i64ptr=&pattern2.nrofDownlinkSlots,.defint64val=-1,TYPE_INT64,0},\ +{GNB_CONFIG_STRING_NROFDOWNLINKSYMBOLS2, NULL,0,.i64ptr=&pattern2.nrofDownlinkSymbols,.defint64val=-1,TYPE_INT64,0},\ +{GNB_CONFIG_STRING_NROFUPLINKSLOTS2,NULL, 0,.i64ptr=&pattern2.nrofUplinkSlots,.defint64val=-1,TYPE_INT64,0},\ +{GNB_CONFIG_STRING_NROFUPLINKSYMBOLS2,NULL, 0,.i64ptr=&pattern2.nrofUplinkSymbols,.defint64val=-1,TYPE_INT64,0}} + /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* Serving Cell Config Dedicated configuration parameters */ /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 39c8014adc..a57d2e0287 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -113,7 +113,10 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc) scc->ssb_periodicityServingCell = calloc_or_fail(1, sizeof(*scc->ssb_periodicityServingCell)); scc->ssbSubcarrierSpacing = calloc_or_fail(1, sizeof(*scc->ssbSubcarrierSpacing)); scc->tdd_UL_DL_ConfigurationCommon = calloc_or_fail(1, sizeof(*scc->tdd_UL_DL_ConfigurationCommon)); - scc->tdd_UL_DL_ConfigurationCommon->pattern2 = calloc_or_fail(1, sizeof(*scc->tdd_UL_DL_ConfigurationCommon->pattern2)); + struct NR_TDD_UL_DL_ConfigCommon *tdd = scc->tdd_UL_DL_ConfigurationCommon; + tdd->pattern1.ext1 = calloc_or_fail(1, sizeof(*tdd->pattern1.ext1)); + tdd->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 = + calloc_or_fail(1, sizeof(*tdd->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530)); scc->downlinkConfigCommon = calloc_or_fail(1, sizeof(*scc->downlinkConfigCommon)); scc->downlinkConfigCommon->frequencyInfoDL = calloc_or_fail(1, sizeof(*scc->downlinkConfigCommon->frequencyInfoDL)); scc->downlinkConfigCommon->initialDownlinkBWP = calloc_or_fail(1, sizeof(*scc->downlinkConfigCommon->initialDownlinkBWP)); @@ -357,15 +360,52 @@ void fill_scc_sim(NR_ServingCellConfigCommon_t *scc, uint64_t *ssb_bitmap, int N p1->nrofUplinkSymbols = 4; struct NR_TDD_UL_DL_Pattern *p2 = tdd_UL_DL_ConfigurationCommon->pattern2; - p2->dl_UL_TransmissionPeriodicity = 321; - p2->nrofDownlinkSlots = -1; - p2->nrofDownlinkSymbols = -1; - p2->nrofUplinkSlots = -1; - p2->nrofUplinkSymbols = -1; + if (p2) { + p2->dl_UL_TransmissionPeriodicity = 321; + p2->nrofDownlinkSlots = -1; + p2->nrofDownlinkSymbols = -1; + p2->nrofUplinkSlots = -1; + p2->nrofUplinkSymbols = -1; + } scc->ss_PBCH_BlockPower = 20; } +static void fix_tdd_pattern(NR_ServingCellConfigCommon_t *scc) +{ + NR_TDD_UL_DL_Pattern_t *pattern1 = &scc->tdd_UL_DL_ConfigurationCommon->pattern1; + int pattern_ext = pattern1->dl_UL_TransmissionPeriodicity - 8; + // Check if the pattern1 extension is configured and set the value accordingly + if (pattern_ext >= 0) { + pattern1->ext1 = calloc_or_fail(1, sizeof(struct NR_TDD_UL_DL_Pattern__ext1)); + pattern1->ext1->dl_UL_TransmissionPeriodicity_v1530 = + calloc_or_fail(1, sizeof(*pattern1->ext1->dl_UL_TransmissionPeriodicity_v1530)); + *pattern1->ext1->dl_UL_TransmissionPeriodicity_v1530 = pattern_ext; + pattern1->dl_UL_TransmissionPeriodicity = 5; + } else { + pattern1->ext1 = NULL; + } + struct NR_TDD_UL_DL_Pattern *pattern2 = scc->tdd_UL_DL_ConfigurationCommon->pattern2; + if (pattern2 != NULL) { + /* The pattern2 is not configured free the memory these shall not be encoded with default values in SIB1 */ + if (pattern2->dl_UL_TransmissionPeriodicity == -1) { + free(pattern2); + pattern2 = NULL; + } else { + // Check if the pattern2 extension is configured and set the value accordingly + pattern_ext = pattern2->dl_UL_TransmissionPeriodicity - 8; + if (pattern_ext >= 0) { + pattern2->ext1 = calloc_or_fail(1, sizeof(*pattern2->ext1)); + pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530 = + CALLOC(1, sizeof(*pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530)); + *pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530 = pattern_ext; + pattern2->dl_UL_TransmissionPeriodicity = 5; + } else { + pattern2->ext1 = NULL; + } + } + } +} void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap) { @@ -436,11 +476,7 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap) ASN_STRUCT_FREE(asn_DEF_NR_TDD_UL_DL_ConfigCommon, scc->tdd_UL_DL_ConfigurationCommon); scc->tdd_UL_DL_ConfigurationCommon = NULL; } else { // TDD - if (scc->tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity > 320 ) { - free(scc->tdd_UL_DL_ConfigurationCommon->pattern2); - scc->tdd_UL_DL_ConfigurationCommon->pattern2 = NULL; - } - + fix_tdd_pattern(scc); } if ((int)*scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing == -1) { @@ -982,6 +1018,16 @@ void RCconfig_NR_L1(void) } } +/** + * @brief Returns true when pattern2 is filled in + */ +bool is_pattern2_config(paramdef_t *param) +{ + if (param == NULL || param->i64ptr == NULL || *(param->i64ptr) == -1) + return false; + return true; +} + static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cfg, int minRXTXTIME) { NR_ServingCellConfigCommon_t *scc = calloc_or_fail(1, sizeof(*scc)); @@ -1002,6 +1048,33 @@ static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cf sprintf(aprefix, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, 0); config_get(cfg, SCCsParams, sizeofArray(SCCsParams), aprefix); config_get(cfg, MsgASCCsParams, sizeofArray(MsgASCCsParams), aprefix); + // NR_TDD-UL-DL-ConfigCommon pattern2 (optional IE) + // fetch params + struct NR_TDD_UL_DL_Pattern p2; + paramdef_t pattern2Params[] = SCC_PATTERN2_PARAMS_DESC(p2); + char aprefix[MAX_OPTNAME_SIZE * 2 + 8]; + sprintf(aprefix, "%s.[%i].%s.[%i].%s", GNB_CONFIG_STRING_GNB_LIST, 0, GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, 0, SCC_PATTERN2_STRING_CONFIG); + config_get(config_get_if(), pattern2Params, sizeofArray(pattern2Params), aprefix); + // check validity + bool is_pattern2 = false; + for (int i = 0; i < sizeofArray(pattern2Params); i++) { + is_pattern2 |= is_pattern2_config(pattern2Params); + } + + if (is_pattern2) { + LOG_I(GNB_APP, "tdd->pattern2 present\n"); + // allocate memory + struct NR_TDD_UL_DL_ConfigCommon *tdd = scc->tdd_UL_DL_ConfigurationCommon; + tdd->pattern2 = calloc_or_fail(1, sizeof(*tdd->pattern2)); + tdd->pattern2->ext1 = calloc_or_fail(1, sizeof(struct NR_TDD_UL_DL_Pattern__ext1)); + tdd->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530 = calloc_or_fail(1, sizeof(*tdd->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530)); + // fill in scc + *scc->tdd_UL_DL_ConfigurationCommon->pattern2 = p2; + AssertFatal(p2.nrofUplinkSlots ^ scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots, + "UL slots in pattern1 (%ld) and pattern2 (%ld) are mutually exclusive (e.g. DDDFUU DDDD, DDDD DDDFUU)\n", + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots, + p2.nrofUplinkSlots); + } struct NR_FrequencyInfoDL *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; LOG_I(RRC, "Read in ServingCellConfigCommon (PhysCellId %d, ABSFREQSSB %d, DLBand %d, ABSFREQPOINTA %d, DLBW " diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index c8aa0b2ac1..fda1dc6c11 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -279,6 +279,257 @@ nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPort return mat; } +/** + * @brief Configures the TDD period, including bitmap, in the frame structure + * + * This function sets the TDD period configuration for DL, UL, and mixed slots in + * the specified frame structure instance, according to the given pattern, and + * updates the bitmap. + * + * @param pattern NR_TDD_UL_DL_Pattern_t configuration containing TDD slots and symbols configuration + * @param fs frame_structure_t pointer + * @param curr_total_slot current position in the slot bitmap to start from + * + * @return Number of slots in the configured TDD period + */ +static uint8_t set_tdd_bmap_period(NR_TDD_UL_DL_Pattern_t *pattern, tdd_period_config_t *pc, int8_t curr_total_slot) +{ + int8_t n_dl_slot = pattern->nrofDownlinkSlots; + int8_t n_ul_slot = pattern->nrofUplinkSlots; + int8_t n_dl_symbols = pattern->nrofDownlinkSymbols; + int8_t n_ul_symbols = pattern->nrofUplinkSymbols; + + // Total slots in the period: if DL/UL symbols are present, is mixed slot + const bool has_mixed_slot = (n_ul_symbols + n_dl_symbols) > 0; + int8_t total_slot = has_mixed_slot ? n_dl_slot + n_ul_slot + 1 : n_dl_slot + n_ul_slot; + + /** Update TDD period configuration: + * mixed slots with DL symbols are counted as DL slots + * mixed slots with UL symbols are counted as UL slots */ + pc->num_dl_slots += (n_dl_slot + (n_dl_symbols > 0)); + pc->num_ul_slots += (n_ul_slot + (n_ul_symbols > 0)); + + // Populate the slot bitmap for each slot in the TDD period + for (int i = 0; i < total_slot; i++) { + tdd_bitmap_t *bitmap = &pc->tdd_slot_bitmap[i + curr_total_slot]; + if (i < n_dl_slot) + bitmap->slot_type = TDD_NR_DOWNLINK_SLOT; + else if ((i == n_dl_slot) && has_mixed_slot) { + bitmap->slot_type = TDD_NR_MIXED_SLOT; + bitmap->num_dl_symbols = n_dl_symbols; + bitmap->num_ul_symbols = n_ul_symbols; + } else if (n_ul_slot) + bitmap->slot_type = TDD_NR_UPLINK_SLOT; + } + + LOG_I(NR_MAC, + "Set TDD configuration period to: %d DL slots, %d UL slots, %d slots per period (NR_TDD_UL_DL_Pattern is %d DL slots, %d " + "UL slots, %d DL symbols, %d UL symbols)\n", + pc->num_dl_slots, + pc->num_ul_slots, + total_slot, + n_dl_slot, + n_ul_slot, + n_dl_symbols, + n_ul_symbols); + + return total_slot; +} + +/** + * @brief Configures TDD patterns (1 or 2) in the frame structure + * + * This function sets up the TDD configuration in the frame structure by applying + * DL and UL patterns as defined in NR_TDD_UL_DL_ConfigCommon. + * It handles both TDD pattern1 and pattern2. + * + * @param tdd NR_TDD_UL_DL_ConfigCommon_t pointer containing pattern1 and pattern2 + * @param fs Pointer to the frame structure to update with the configured TDD patterns. + * + * @return void + */ +static void config_tdd_patterns(NR_TDD_UL_DL_ConfigCommon_t *tdd, frame_structure_t *fs) +{ + int num_of_patterns = 1; + uint8_t nb_slots_p2 = 0; + // Reset num dl/ul slots + tdd_period_config_t *pc = &fs->period_cfg; + pc->num_dl_slots = 0; + pc->num_ul_slots = 0; + // Pattern1 + uint8_t nb_slots_p1 = set_tdd_bmap_period(&tdd->pattern1, pc, 0); + // Pattern2 + if (tdd->pattern2) { + num_of_patterns++; + nb_slots_p2 = set_tdd_bmap_period(tdd->pattern2, pc, nb_slots_p1); + } + LOG_I(NR_MAC, + "Configured %d TDD patterns (total slots: pattern1 = %d, pattern2 = %d)\n", + num_of_patterns, + nb_slots_p1, + nb_slots_p2); +} + +/** + * @brief Get the first UL slot index in period + * @param fs frame structure + * @param mixed indicates whether to include in the count also mixed slot with UL symbols or only full UL slot + * @return slot index + */ +int get_first_ul_slot(const frame_structure_t *fs, bool mixed) +{ + DevAssert(fs); + + if (fs->is_tdd) { + for (int i = 0; i < fs->numb_slots_period; i++) { + if ((mixed && is_ul_slot(i, fs)) || fs->period_cfg.tdd_slot_bitmap[i].slot_type == TDD_NR_UPLINK_SLOT) { + return i; + } + } + } + + return 0; // FDD +} + +/** + * @brief Get number of DL slots per period (full DL slots + mixed slots with DL symbols) + */ +int get_dl_slots_per_period(const frame_structure_t *fs) +{ + return fs->is_tdd ? fs->period_cfg.num_dl_slots : fs->numb_slots_frame; +} + +/** + * @brief Get number of UL slots per period (full UL slots + mixed slots with UL symbols) + */ +int get_ul_slots_per_period(const frame_structure_t *fs) +{ + return fs->is_tdd ? fs->period_cfg.num_ul_slots : fs->numb_slots_frame; +} + +/** + * @brief Get number of full UL slots per period + * @param fs Pointer to the frame structure + * @return Number of full UL slots + */ +int get_full_ul_slots_per_period(const frame_structure_t *fs) +{ + DevAssert(fs); + + if (!fs->is_tdd) + return fs->numb_slots_frame; + + int count = 0; + + for (int i = 0; i < fs->numb_slots_period; i++) + if (fs->period_cfg.tdd_slot_bitmap[i].slot_type == TDD_NR_UPLINK_SLOT) + count++; + + LOG_D(NR_MAC, "Full UL slots in TDD period: %d\n", count); + return count; +} + +/** + * @brief Get number of full DL slots per period + * @param fs Pointer to the frame structure + * @return Number of full DL slots + */ +int get_full_dl_slots_per_period(const frame_structure_t *fs) +{ + DevAssert(fs); + + if (!fs->is_tdd) + return fs->numb_slots_frame; + + int count = 0; + + for (int i = 0; i < fs->numb_slots_period; i++) + if (fs->period_cfg.tdd_slot_bitmap[i].slot_type == TDD_NR_DOWNLINK_SLOT) + count++; + + LOG_D(NR_MAC, "Full DL slots in TDD period: %d\n", count); + return count; +} + +/** + * @brief Get number of UL slots per frame + */ +int get_ul_slots_per_frame(const frame_structure_t *fs) +{ + return fs->is_tdd ? fs->numb_period_frame * get_ul_slots_per_period(fs) : fs->numb_slots_frame; +} + +/** + * @brief Get the nth UL slot offset for UE index idx in a TDD period using the frame structure bitmap + * @param fs frame structure + * @param idx UE index + * @param count_mixed indicates whether counting mixed slot with UL symbols (e.g. for SRS) or only full UL slots + * @return slot index offset + */ +int get_ul_slot_offset(const frame_structure_t *fs, int idx, bool count_mixed) +{ + DevAssert(fs); + + // FDD + if (!fs->is_tdd) + return idx; + + // UL slots indexes in period + int ul_slot_idxs[fs->numb_slots_period]; + int ul_slot_count = 0; + + /* Populate the indices of UL slots in the TDD period from the bitmap + count also mixed slots with UL symbols if flag count_mixed is present */ + for (int i = 0; i < fs->numb_slots_period; i++) { + if ((count_mixed && is_ul_slot(i, fs)) || fs->period_cfg.tdd_slot_bitmap[i].slot_type == TDD_NR_UPLINK_SLOT) { + ul_slot_idxs[ul_slot_count++] = i; + } + } + + // Compute slot index offset + int period_idx = idx / ul_slot_count; // wrap up the count of complete TDD periods spanned by the index + int ul_slot_idx_in_period = idx % ul_slot_count; // wrap up the UL slot index within the current TDD period + + return ul_slot_idxs[ul_slot_idx_in_period] + period_idx * fs->numb_slots_period; +} + +/** + * @brief Configures the frame structure and the NFAPI config request + * depending on the duplex mode. If TDD, does the TDD patterns + * and TDD periods configuration. + * + * @param mu numerology + * @param scc pointer to scc + * @param cfg pointer to NFAPI config request + * @param fs pointer to the frame structure to update + * + * @return Number of periods in frame + */ +static int config_frame_structure(int mu, + NR_ServingCellConfigCommon_t *scc, + nfapi_nr_config_request_scf_t *cfg, + frame_structure_t *fs) +{ + fs->numb_slots_frame = nr_slots_per_frame[mu]; + if (cfg->cell_config.frame_duplex_type.value == TDD) { + cfg->tdd_table.tdd_period.tl.tag = NFAPI_NR_CONFIG_TDD_PERIOD_TAG; + cfg->num_tlv++; + cfg->tdd_table.tdd_period.value = get_tdd_period_idx(scc->tdd_UL_DL_ConfigurationCommon); + LOG_D(NR_MAC, "Setting TDD configuration period to %d\n", cfg->tdd_table.tdd_period.value); + fs->numb_period_frame = get_nb_periods_per_frame(cfg->tdd_table.tdd_period.value); + fs->numb_slots_period = fs->numb_slots_frame / fs->numb_period_frame; + fs->is_tdd = true; + config_tdd_patterns(scc->tdd_UL_DL_ConfigurationCommon, fs); + set_tdd_config_nr(cfg, fs); + } else { // FDD + fs->is_tdd = false; + fs->numb_period_frame = 1; + fs->numb_slots_period = nr_slots_per_frame[mu]; + } + AssertFatal(fs->numb_period_frame > 0, "Frame configuration cannot be configured!\n"); + return fs->numb_period_frame; +} + static void config_common(gNB_MAC_INST *nrmac, const nr_mac_config_t *config, NR_ServingCellConfigCommon_t *scc) @@ -317,10 +568,10 @@ static void config_common(gNB_MAC_INST *nrmac, } } struct NR_FrequencyInfoUL *frequencyInfoUL = scc->uplinkConfigCommon->frequencyInfoUL; + int scs = frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; frequency_range = *frequencyInfoUL->frequencyBandList->list.array[0] > 256 ? FR2 : FR1; - bw_index = get_supported_band_index(frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - frequency_range, - frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); + bw_index = + get_supported_band_index(scs, frequency_range, frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); cfg->carrier_config.uplink_bandwidth.value = get_supported_bw_mhz(frequency_range, bw_index); cfg->carrier_config.uplink_bandwidth.tl.tag = NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG; // temporary cfg->num_tlv++; @@ -339,7 +590,7 @@ static void config_common(gNB_MAC_INST *nrmac, cfg->num_tlv++; for (int i = 0; i < 5; i++) { - if (i == frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) { + if (i == scs) { cfg->carrier_config.ul_grid_size[i].value = frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; cfg->carrier_config.ul_k0[i].value = frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier; cfg->carrier_config.ul_grid_size[i].tl.tag = NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG; @@ -438,21 +689,15 @@ static void config_common(gNB_MAC_INST *nrmac, prach_fd_occasion->k1.value = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE) + rach_ConfigCommon->rach_ConfigGeneric.msg1_FrequencyStart - + (get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, - frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) - * i); + + (get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, scs) * i); if (IS_SA_MODE(get_softmodem_params())) { prach_fd_occasion->k1.value = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE) + rach_ConfigCommon->rach_ConfigGeneric.msg1_FrequencyStart - + (get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, - frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) - * i); + + (get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, scs) * i); } else { prach_fd_occasion->k1.value = rach_ConfigCommon->rach_ConfigGeneric.msg1_FrequencyStart - + (get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, - frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) - * i); + + (get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, scs) * i); } prach_fd_occasion->k1.tl.tag = NFAPI_NR_CONFIG_K1_TAG; cfg->num_tlv++; @@ -572,28 +817,9 @@ static void config_common(gNB_MAC_INST *nrmac, cfg->num_tlv++; cfg->num_tlv++; - // TDD Table Configuration - if (cfg->cell_config.frame_duplex_type.value == TDD) { - cfg->tdd_table.tdd_period.tl.tag = NFAPI_NR_CONFIG_TDD_PERIOD_TAG; - cfg->num_tlv++; - if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1 == NULL) { - cfg->tdd_table.tdd_period.value = scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity; - } else { - AssertFatal(scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL, - "In %s: scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 is null\n", - __FUNCTION__); - cfg->tdd_table.tdd_period.value = *scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530; - } - LOG_D(NR_MAC, "Setting TDD configuration period to %d\n", cfg->tdd_table.tdd_period.value); - int periods_per_frame = set_tdd_config_nr(cfg, - frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots, - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols, - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots, - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols); - - AssertFatal(periods_per_frame > 0, "TDD configuration cannot be configured\n"); - } + // Frame structure configuration + uint8_t mu = frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + config_frame_structure(mu, scc, cfg, &nrmac->frame_structure); int nb_tx = config->nb_bfw[0]; // number of tx antennas int nb_beams = config->nb_bfw[1]; // number of beams @@ -691,31 +917,6 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c find_SSB_and_RO_available(nrmac); - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - - int nr_slots_period = n; - int nr_dl_slots = n; - int nr_ulstart_slot = 0; - if (tdd) { - nr_dl_slots = tdd->nrofDownlinkSlots + (tdd->nrofDownlinkSymbols != 0); - nr_ulstart_slot = get_first_ul_slot(tdd->nrofDownlinkSlots, tdd->nrofDownlinkSymbols, tdd->nrofUplinkSymbols); - nr_slots_period /= get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity); - } else { - // if TDD configuration is not present and the band is not FDD, it means it is a dynamic TDD configuration - AssertFatal(nrmac->common_channels[0].frame_type == FDD,"Dynamic TDD not handled yet\n"); - } - - for (int slot = 0; slot < n; ++slot) { - nrmac->dlsch_slot_bitmap[slot / 64] |= (uint64_t)((slot % nr_slots_period) < nr_dl_slots) << (slot % 64); - nrmac->ulsch_slot_bitmap[slot / 64] |= (uint64_t)((slot % nr_slots_period) >= nr_ulstart_slot) << (slot % 64); - - LOG_D(NR_MAC, - "slot %d DL %d UL %d\n", - slot, - (nrmac->dlsch_slot_bitmap[slot / 64] & ((uint64_t)1 << (slot % 64))) != 0, - (nrmac->ulsch_slot_bitmap[slot / 64] & ((uint64_t)1 << (slot % 64))) != 0); - } - NR_COMMON_channels_t *cc = &nrmac->common_channels[0]; NR_SCHED_LOCK(&nrmac->sched_lock); for (int n = 0; n < NR_NB_RA_PROC_MAX; n++) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 80bb00cfac..f8b8953920 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -122,8 +122,49 @@ void clear_beam_information(NR_beam_info_t *beam_info, int frame, int slot, int } } -bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) { - return (bitmap >> (slot % 64)) & 0x01; +/** + * @brief Returns true for: + * (1) FDD + * (2) Mixed slot with UL symbols + * (3) Full UL slot + */ +bool is_ul_slot(const slot_t slot, const frame_structure_t *fs) +{ + if (!fs->is_tdd) + return true; + const tdd_period_config_t *pc = &fs->period_cfg; + slot_t s = get_slot_idx_in_period(slot, fs); + return ((is_mixed_slot(s, fs) && pc->tdd_slot_bitmap[s].num_ul_symbols) + || (pc->tdd_slot_bitmap[s].slot_type == TDD_NR_UPLINK_SLOT)); +} + +/** + * @brief Returns true for: + * (1) FDD + * (2) Mixed slot with DL symbols + * (3) Full DL slot + */ +bool is_dl_slot(const slot_t slot, const frame_structure_t *fs) +{ + if (!fs->is_tdd) + return true; + const tdd_period_config_t *pc = &fs->period_cfg; + slot_t s = get_slot_idx_in_period(slot, fs); + return ((is_mixed_slot(s, fs) && pc->tdd_slot_bitmap[s].num_dl_symbols) + || (pc->tdd_slot_bitmap[s].slot_type == TDD_NR_DOWNLINK_SLOT)); +} + +/** + * @brief Returns true for: + * (1) Mixed slot with DL and/or UL symbols + */ +bool is_mixed_slot(const slot_t slot, const frame_structure_t *fs) +{ + if (!fs->is_tdd) + return false; + slot_t s = get_slot_idx_in_period(slot, fs); + const tdd_period_config_t *pc = &fs->period_cfg; + return pc->tdd_slot_bitmap[s].slot_type == TDD_NR_MIXED_SLOT; } /* the structure nfapi_nr_ul_tti_request_t is very big, let's copy only what is necessary */ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index f0581cf58e..3f3cbbad12 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -276,7 +276,7 @@ static void schedule_nr_MsgA_pusch(NR_UplinkConfigCommon_t *uplinkConfigCommon, UL_tti_req->SFN = msgA_pusch_frame; UL_tti_req->Slot = msgA_pusch_slot; - AssertFatal(is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[msgA_pusch_slot / 64], msgA_pusch_slot), + AssertFatal(is_ul_slot(msgA_pusch_slot, &nr_mac->frame_structure), "Slot %d is not an Uplink slot, invalid msgA_PUSCH_TimeDomainOffset_r16 %ld\n", msgA_pusch_slot, msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16); @@ -374,7 +374,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[0][index]; nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0]; - if (is_nr_UL_slot(scc->tdd_UL_DL_ConfigurationCommon, slotP, cc->frame_type)) { + if (is_ul_slot(slotP, &RC.nrmac[module_idP]->frame_structure)) { const NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &rach_ConfigCommon->rach_ConfigGeneric; uint8_t config_index = rach_ConfigGeneric->prach_ConfigurationIndex; uint8_t N_dur, N_t_slot, start_symbol = 0, N_RA_slot; @@ -785,7 +785,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, const int sched_frame = (frame + (slot + K2) / nr_slots_per_frame[mu]) % MAX_FRAME_NUMBER; const int sched_slot = (slot + K2) % nr_slots_per_frame[mu]; - if (is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot)) { + if (is_ul_slot(sched_slot, &nr_mac->frame_structure)) { const int n_slots_frame = nr_slots_per_frame[mu]; NR_beam_alloc_t beam_ul = beam_allocation_procedure(&nr_mac->beam_info, sched_frame, sched_slot, ra->beam_id, n_slots_frame); if (beam_ul.idx < 0) @@ -950,47 +950,44 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, ra->ra_state = nrRA_WAIT_Msg3; ra->Msg3_frame = sched_frame; ra->Msg3_slot = sched_slot; - } } -static bool get_feasible_msg3_tda(frame_type_t frame_type, - const NR_ServingCellConfigCommon_t *scc, +static bool get_feasible_msg3_tda(const NR_ServingCellConfigCommon_t *scc, int mu_delta, - uint64_t ulsch_slot_bitmap[3], const NR_PUSCH_TimeDomainResourceAllocationList_t *tda_list, - int slots_per_frame, int frame, int slot, NR_RA_t *ra, NR_beam_info_t *beam_info, - const NR_TDD_UL_DL_Pattern_t *tdd) + const frame_structure_t *fs) { DevAssert(tda_list != NULL); const int NTN_gNB_Koffset = get_NTN_Koffset(scc); - int tdd_period_slot = tdd ? slots_per_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : slots_per_frame; + int slots_per_frame = fs->numb_slots_frame; for (int i = 0; i < tda_list->list.count; i++) { // check if it is UL long k2 = *tda_list->list.array[i]->k2 + NTN_gNB_Koffset; int abs_slot = slot + k2 + mu_delta; int temp_frame = (frame + (abs_slot / slots_per_frame)) & 1023; int temp_slot = abs_slot % slots_per_frame; // msg3 slot according to 8.3 in 38.213 - if ((frame_type == TDD) && !is_xlsch_in_slot(ulsch_slot_bitmap[temp_slot / 64], temp_slot)) + if (fs->is_tdd && !is_ul_slot(temp_slot, fs)) continue; + const tdd_bitmap_t *tdd_slot_bitmap = fs->period_cfg.tdd_slot_bitmap; + int s = get_slot_idx_in_period(temp_slot, fs); // check if enough symbols in case of mixed slot - bool is_mixed = false; - if (frame_type == TDD) { - bool has_mixed = tdd->nrofUplinkSymbols != 0 || tdd->nrofDownlinkSymbols != 0; - is_mixed = has_mixed && ((temp_slot % tdd_period_slot) == tdd->nrofDownlinkSlots); - } + bool is_mixed = is_mixed_slot(s, fs); // if the mixed slot has not enough symbols, skip - if (is_mixed && tdd->nrofUplinkSymbols < 3) + if (is_mixed && tdd_slot_bitmap[s].num_ul_symbols < 3) continue; - uint16_t slot_mask = is_mixed ? SL_to_bitmap(14 - tdd->nrofUplinkSymbols, tdd->nrofUplinkSymbols) : 0x3fff; + uint16_t slot_mask = + is_mixed ? SL_to_bitmap(NR_NUMBER_OF_SYMBOLS_PER_SLOT - tdd_slot_bitmap[s].num_ul_symbols, + tdd_slot_bitmap[s].num_ul_symbols) + : 0x3fff; long startSymbolAndLength = tda_list->list.array[i]->startSymbolAndLength; int start, nr; SLIV2SL(startSymbolAndLength, &start, &nr); @@ -1385,7 +1382,7 @@ static void nr_generate_Msg2(module_id_t module_idP, gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; // no DL -> cannot send Msg2 - if (!is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slotP / 64], slotP)) { + if (!is_dl_slot(slotP, &nr_mac->frame_structure)) { return; } @@ -1413,18 +1410,14 @@ static void nr_generate_Msg2(module_id_t module_idP, return; const NR_UE_UL_BWP_t *ul_bwp = &ra->UL_BWP; - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - bool ret = get_feasible_msg3_tda(cc->frame_type, - scc, + bool ret = get_feasible_msg3_tda(scc, DELTA[ul_bwp->scs], - nr_mac->ulsch_slot_bitmap, ul_bwp->tdaList_Common, - nr_slots_per_frame[ul_bwp->scs], frameP, slotP, ra, &nr_mac->beam_info, - tdd); + &nr_mac->frame_structure); if (!ret || ra->Msg3_tda_id > 15) { LOG_D(NR_MAC, "UE RNTI %04x %d.%d: infeasible Msg3 TDA\n", ra->rnti, frameP, slotP); reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); @@ -1453,7 +1446,7 @@ static void nr_generate_Msg2(module_id_t module_idP, AssertFatal(coreset, "Coreset cannot be null for RA-Msg2\n"); const int coresetid = coreset->controlResourceSetId; // Calculate number of symbols - int time_domain_assignment = get_dl_tda(nr_mac, scc, slotP); + int time_domain_assignment = get_dl_tda(nr_mac, slotP); int mux_pattern = type0_PDCCH_CSS_config ? type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern : 1; NR_tda_info_t tda_info = get_dl_tda_info(dl_bwp, ss->searchSpaceType->present, @@ -1949,8 +1942,8 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_UE_DL_BWP_t *dl_bwp = &ra->DL_BWP; - // if it is a DL slot, if the RA is in MSG4 state - if (is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slotP / 64], slotP)) { + // if it is a DL slot, if the RA is in MSG4 state + if (is_dl_slot(slotP, &nr_mac->frame_structure)) { NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; NR_SearchSpace_t *ss = ra->ra_ss; const char *ra_type_str = ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4"; @@ -2029,7 +2022,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, return; } - uint8_t time_domain_assignment = get_dl_tda(nr_mac, scc, slotP); + uint8_t time_domain_assignment = get_dl_tda(nr_mac, slotP); int mux_pattern = type0_PDCCH_CSS_config ? type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern : 1; NR_tda_info_t msg4_tda = get_dl_tda_info(dl_bwp, ss->searchSpaceType->present, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 48a72b527b..8b6639a3e7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -52,20 +52,22 @@ #define WORD 32 //#define SIZE_OF_POINTER sizeof (void *) -int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot) +int get_dl_tda(const gNB_MAC_INST *nrmac, int slot) { /* we assume that this function is mutex-protected from outside */ - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - AssertFatal(tdd || nrmac->common_channels->frame_type == FDD, "Dynamic TDD not handled yet\n"); + const frame_structure_t *fs = &nrmac->frame_structure; // Use special TDA in case of CSI-RS - if(nrmac->UE_info.sched_csirs > 0) + if (nrmac->UE_info.sched_csirs > 0) return 1; - if (tdd && tdd->nrofDownlinkSymbols > 1) { // if there is a mixed slot where we can transmit DL - const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + 1; - if ((slot % nr_slots_period) == tdd->nrofDownlinkSlots) + if (fs->is_tdd) { + int s = get_slot_idx_in_period(slot, fs); + // if there is a mixed slot where we can transmit DL + const tdd_bitmap_t *tdd_slot_bitmap = fs->period_cfg.tdd_slot_bitmap; + if (tdd_slot_bitmap[s].num_dl_symbols > 1 && is_mixed_slot(s, fs)) { return 2; + } } return 0; // if FDD or not mixed slot in TDD, for now use default TDA } @@ -447,7 +449,7 @@ static bool allocate_dl_retransmission(module_id_t module_id, int pm_index = (curInfo->nrOfLayers < retInfo->nrOfLayers) ? curInfo->pm_index : retInfo->pm_index; const int coresetid = sched_ctrl->coreset->controlResourceSetId; - const int tda = get_dl_tda(nr_mac, scc, slot); + const int tda = get_dl_tda(nr_mac, slot); AssertFatal(tda >= 0,"Unable to find PDSCH time domain allocation in list\n"); /* Check first whether the old TDA can be reused @@ -761,7 +763,7 @@ static void pf_dl(module_id_t module_id, sched_pdsch->dl_harq_pid = sched_ctrl->available_dl_harq.head; /* MCS has been set above */ - sched_pdsch->time_domain_allocation = get_dl_tda(mac, scc, slot); + sched_pdsch->time_domain_allocation = get_dl_tda(mac, slot); AssertFatal(sched_pdsch->time_domain_allocation>=0,"Unable to find PDSCH time domain allocation in list\n"); const int coresetid = sched_ctrl->coreset->controlResourceSetId; @@ -955,7 +957,7 @@ void nr_schedule_ue_spec(module_id_t module_id, AssertFatal(pthread_mutex_trylock(&gNB_mac->sched_lock) == EBUSY, "this function should be called with the scheduler mutex locked\n"); - if (!is_xlsch_in_slot(gNB_mac->dlsch_slot_bitmap[slot / 64], slot)) + if (!is_dl_slot(slot, &gNB_mac->frame_structure)) return; /* PREPROCESSOR */ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 026f93fd43..f2c014a65f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -40,6 +40,14 @@ // #define UL_HARQ_PRINT // #define ENABLE_MAC_PAYLOAD_DEBUG 1 +/* This function checks whether the given Dl/UL slot is set + in the input bitmap, which is a mask indicating in which + slot to transmit (among those available in the TDD configuration) */ +static bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) +{ + return (bitmap >> (slot % 64)) & 0x01; +} + uint32_t target_dl_mcs = 9; uint32_t target_dl_Nl = 1; uint32_t target_dl_bw = 50; @@ -64,7 +72,7 @@ void nr_preprocessor_phytest(module_id_t module_id, return; } - const int tda = get_dl_tda(RC.nrmac[module_id], scc, slot); + const int tda = get_dl_tda(RC.nrmac[module_id], slot); NR_tda_info_t tda_info = get_dl_tda_info(dl_bwp, sched_ctrl->search_space->searchSpaceType->present, tda, @@ -242,7 +250,7 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_ sched_ctrl->coreset->controlResourceSetId, sched_ctrl->search_space->searchSpaceType->present, TYPE_C_RNTI_); - const int temp_tda = get_ul_tda(nr_mac, scc, frame, slot); + const int temp_tda = get_ul_tda(nr_mac, frame, slot); if (temp_tda < 0) return false; AssertFatal(temp_tda < tdaList->list.count, @@ -252,7 +260,7 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_ int K2 = get_K2(tdaList, temp_tda, mu, scc); const int sched_frame = (frame + (slot + K2) / nr_slots_per_frame[mu]) % MAX_FRAME_NUMBER; const int sched_slot = (slot + K2) % nr_slots_per_frame[mu]; - const int tda = get_ul_tda(nr_mac, scc, sched_frame, sched_slot); + const int tda = get_ul_tda(nr_mac, sched_frame, sched_slot); if (tda < 0) return false; AssertFatal(tda < tdaList->list.count, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 1ca064b101..d6f63d46d1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2160,6 +2160,31 @@ int get_ulbw_tbslbrm(int scc_bwpsize, const NR_ServingCellConfig_t *servingCellC return bw; } +static void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl, + const NR_UE_UL_BWP_t *ul_bwp, + const NR_ServingCellConfigCommon_t *scc, + const frame_structure_t *fs) +{ + const int NTN_gNB_Koffset = get_NTN_Koffset(scc); + const int n_ul_slots_period = get_ul_slots_per_period(fs); + + // PUCCH list size is given by the number of UL slots in the PUCCH period + // the length PUCCH period is determined by max_fb_time since we may need to prepare PUCCH for ACK/NACK max_fb_time slots ahead + const int list_size = n_ul_slots_period << (int)ceil(log2((ul_bwp->max_fb_time + NTN_gNB_Koffset) / fs->numb_slots_period + 1)); + + if (!sched_ctrl->sched_pucch) { + sched_ctrl->sched_pucch = calloc_or_fail(list_size, sizeof(*sched_ctrl->sched_pucch)); + sched_ctrl->sched_pucch_size = list_size; + } else if (list_size > sched_ctrl->sched_pucch_size) { + sched_ctrl->sched_pucch = realloc(sched_ctrl->sched_pucch, list_size * sizeof(*sched_ctrl->sched_pucch)); + for (int i = sched_ctrl->sched_pucch_size; i < list_size; i++) { + NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[i]; + memset(curr_pucch, 0, sizeof(*curr_pucch)); + } + sched_ctrl->sched_pucch_size = list_size; + } +} + // main function to configure parameters of current BWP void configure_UE_BWP(gNB_MAC_INST *nr_mac, NR_ServingCellConfigCommon_t *scc, @@ -2405,7 +2430,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, NR_UL_DCI_FORMAT_0_0; set_max_fb_time(UL_BWP, DL_BWP); - set_sched_pucch_list(sched_ctrl, UL_BWP, scc); + set_sched_pucch_list(sched_ctrl, UL_BWP, scc, &nr_mac->frame_structure); } if(ra) { @@ -2537,32 +2562,6 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf return (UE); } -void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl, - const NR_UE_UL_BWP_t *ul_bwp, - const NR_ServingCellConfigCommon_t *scc) -{ - const int NTN_gNB_Koffset = get_NTN_Koffset(scc); - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs]; - const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; - const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : n_slots_frame; - // PUCCH list size is given by the number of UL slots in the PUCCH period - // the length PUCCH period is determined by max_fb_time since we may need to prepare PUCCH for ACK/NACK max_fb_time slots ahead - const int list_size = n_ul_slots_period << (int)ceil(log2((ul_bwp->max_fb_time + NTN_gNB_Koffset) / nr_slots_period + 1)); - if(!sched_ctrl->sched_pucch) { - sched_ctrl->sched_pucch = calloc(list_size, sizeof(*sched_ctrl->sched_pucch)); - sched_ctrl->sched_pucch_size = list_size; - } - else if (list_size > sched_ctrl->sched_pucch_size) { - sched_ctrl->sched_pucch = realloc(sched_ctrl->sched_pucch, list_size * sizeof(*sched_ctrl->sched_pucch)); - for(int i=sched_ctrl->sched_pucch_size; isched_pucch[i]; - memset(curr_pucch, 0, sizeof(*curr_pucch)); - } - sched_ctrl->sched_pucch_size = list_size; - } -} - void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl) { free(sched_ctrl->sched_pucch); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 7a14dc7124..853a4a5ff8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -133,23 +133,35 @@ static const int diff_rsrp_ssb_csi_meas_10_1_6_1_2[16] = { -30 // 10 - 15 }; -static int get_pucch_index(int frame, int slot, int n_slots_frame, const NR_TDD_UL_DL_Pattern_t *tdd, int sched_pucch_size) +static int get_pucch_index(int frame, int slot, const frame_structure_t *fs, int sched_pucch_size) { // PUCCH structures are indexed by slot in the PUCCH period determined by sched_pucch_size number of UL slots // this functions return the index to the structure for slot passed to the function - const int first_ul_slot_period = tdd ? get_first_ul_slot(tdd->nrofDownlinkSlots, tdd->nrofDownlinkSymbols, tdd->nrofUplinkSymbols) : 0; - const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : n_slots_frame; - const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; - const int n_ul_slots_frame = n_slots_frame / nr_slots_period * n_ul_slots_period; + const int n_ul_slots_period = get_ul_slots_per_period(fs); + const int n_ul_slots_frame = get_ul_slots_per_frame(fs); // (frame * n_ul_slots_frame) adds up the number of UL slots in the previous frames const int frame_start = frame * n_ul_slots_frame; // ((slot / nr_slots_period) * n_ul_slots_period) adds up the number of UL slots in the previous TDD periods of this frame - const int ul_period_start = (slot / nr_slots_period) * n_ul_slots_period; + const int ul_period_start = (slot / fs->numb_slots_period) * n_ul_slots_period; // ((slot % nr_slots_period) - first_ul_slot_period) gives the progressive number of the slot in this TDD period - const int ul_period_slot = (slot % nr_slots_period) - first_ul_slot_period; + int ul_period_slot = -1; + for (int i = 0; i <= slot % fs->numb_slots_period; i++) { + if (is_ul_slot(i, fs)) { + ul_period_slot++; + } + } + LOG_D(NR_MAC, + "PUCCH frame/slot: request %4d.%2d:frame_start %d,ul_period_start %d, ul_period_slot %d pucch_index %d pucch_size %d " + "scheduling PUCCH\n", + frame, + slot, + frame_start, + ul_period_start, + ul_period_slot, + ((frame_start + ul_period_start + ul_period_slot) % sched_pucch_size), + sched_pucch_size); // the sum gives the index of current UL slot in the frame which is normalized wrt sched_pucch_size return (frame_start + ul_period_start + ul_period_slot) % sched_pucch_size; - } void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP) @@ -157,17 +169,12 @@ void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP) /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); - if (!is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[slotP / 64], slotP)) + if (!is_ul_slot(slotP, &nrmac->frame_structure)) return; UE_iterator(nrmac->UE_info.list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; - const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs]; - const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[0].ServingCellConfigCommon; - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - AssertFatal(tdd || nrmac->common_channels[0].frame_type == FDD, "Dynamic TDD not handled yet\n"); - const int pucch_index = get_pucch_index(frameP, slotP, n_slots_frame, tdd, sched_ctrl->sched_pucch_size); + const int pucch_index = get_pucch_index(frameP, slotP, &nrmac->frame_structure, sched_ctrl->sched_pucch_size); NR_sched_pucch_t *curr_pucch = &UE->UE_sched_ctrl.sched_pucch[pucch_index]; if (!curr_pucch->active) continue; @@ -236,7 +243,7 @@ void nr_csi_meas_reporting(int Mod_idP,frame_t frame, sub_frame_t slot) if ((sched_frame * n_slots_frame + sched_slot - offset) % period != 0) continue; - AssertFatal(is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[sched_slot / 64], sched_slot), "CSI reporting slot %d is not set for an uplink slot\n", sched_slot); + AssertFatal(is_ul_slot(sched_slot, &nrmac->frame_structure), "CSI reporting slot %d is not set for an uplink slot\n", sched_slot); LOG_D(NR_MAC, "CSI reporting in frame %d slot %d CSI report ID %ld\n", sched_frame, sched_slot, csirep->reportConfigId); const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1 @@ -248,9 +255,7 @@ void nr_csi_meas_reporting(int Mod_idP,frame_t frame, sub_frame_t slot) AssertFatal(res_index < n, "CSI pucch resource %ld not found among PUCCH resources\n", pucchcsires->pucch_Resource); - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - AssertFatal(tdd || nrmac->common_channels[0].frame_type == FDD, "Dynamic TDD not handled yet\n"); - const int pucch_index = get_pucch_index(sched_frame, sched_slot, n_slots_frame, tdd, sched_ctrl->sched_pucch_size); + const int pucch_index = get_pucch_index(sched_frame, sched_slot, &nrmac->frame_structure, sched_ctrl->sched_pucch_size); NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index]; AssertFatal(curr_pucch->active == false, "CSI structure is scheduled in advance. It should be free!\n"); curr_pucch->r_pucch = -1; @@ -998,10 +1003,7 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac, const int minfbtime = mac->radio_config.minRXTXTIME + NTN_gNB_Koffset; const NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs]; - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - AssertFatal(tdd || mac->common_channels[CC_id].frame_type == FDD, "Dynamic TDD not handled yet\n"); - const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; - const int first_ul_slot_period = tdd ? get_first_ul_slot(tdd->nrofDownlinkSlots, tdd->nrofDownlinkSymbols, tdd->nrofUplinkSymbols) : 0; + const frame_structure_t *fs = &mac->frame_structure; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_PUCCH_Config_t *pucch_Config = ul_bwp->pucch_Config; @@ -1022,11 +1024,14 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac, continue; const int pucch_slot = (slot + pdsch_to_harq_feedback[f] + NTN_gNB_Koffset) % n_slots_frame; // check if the slot is UL - if(pucch_slot%nr_slots_period < first_ul_slot_period) - continue; + if (fs->is_tdd) { + int mod_slot = pucch_slot % fs->numb_slots_period; + if (!is_ul_slot(mod_slot, fs)) + continue; + } const int pucch_frame = (frame + ((slot + pdsch_to_harq_feedback[f] + NTN_gNB_Koffset) / n_slots_frame)) % MAX_FRAME_NUMBER; // we store PUCCH resources according to slot, TDD configuration and size of the vector containing PUCCH structures - const int pucch_index = get_pucch_index(pucch_frame, pucch_slot, n_slots_frame, tdd, sched_ctrl->sched_pucch_size); + const int pucch_index = get_pucch_index(pucch_frame, pucch_slot, &mac->frame_structure, sched_ctrl->sched_pucch_size); NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index]; if (curr_pucch->active && curr_pucch->frame == pucch_frame && @@ -1125,7 +1130,7 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot) /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); - if (!is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[slot / 64], slot)) + if (!is_ul_slot(slot, &nrmac->frame_structure)) return; const int CC_id = 0; UE_iterator(nrmac->UE_info.list, UE) { @@ -1164,10 +1169,7 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot) } AssertFatal(idx > -1, "SR resource not found among PUCCH resources"); - const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon; - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - AssertFatal(tdd || nrmac->common_channels[CC_id].frame_type == FDD, "Dynamic TDD not handled yet\n"); - const int pucch_index = get_pucch_index(SFN, slot, n_slots_frame, tdd, sched_ctrl->sched_pucch_size); + const int pucch_index = get_pucch_index(SFN, slot, &nrmac->frame_structure, sched_ctrl->sched_pucch_size); NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index]; if (curr_pucch->active && curr_pucch->frame == SFN && curr_pucch->ul_slot == slot && curr_pucch->resource_indicator == idx) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 898b345495..52e045c848 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -40,19 +40,21 @@ //#define SRS_IND_DEBUG -int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int frame, int slot) +int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot) { /* we assume that this function is mutex-protected from outside */ NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); /* there is a mixed slot only when in TDD */ - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - AssertFatal(tdd || nrmac->common_channels->frame_type == FDD, "Dynamic TDD not handled yet\n"); + frame_structure_t *fs = &nrmac->frame_structure; - if (tdd && tdd->nrofUplinkSymbols > 1) { // if there is uplink symbols in mixed slot - const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + 1; - if ((slot % nr_slots_period) == tdd->nrofDownlinkSlots) + if (fs->is_tdd) { + // if there is uplink symbols in mixed slot + int s = get_slot_idx_in_period(slot, fs); + tdd_bitmap_t *tdd_slot_bitmap = fs->period_cfg.tdd_slot_bitmap; + if ((tdd_slot_bitmap[s].num_ul_symbols > 1) && is_mixed_slot(s, fs)) { return 2; + } } // Avoid slots with the SRS @@ -1519,25 +1521,21 @@ long get_K2(NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList, return 3 + NTN_gNB_Koffset; } -static bool nr_UE_is_to_be_scheduled(const NR_ServingCellConfigCommon_t *scc, int CC_id, NR_UE_info_t* UE, frame_t frame, sub_frame_t slot, uint32_t ulsch_max_frame_inactivity) +static bool nr_UE_is_to_be_scheduled(const frame_structure_t *fs, + NR_UE_info_t *UE, + frame_t frame, + sub_frame_t slot, + uint32_t ulsch_max_frame_inactivity) { - const int n = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; + const int n = fs->numb_slots_frame; const int now = frame * n + slot; const NR_UE_sched_ctrl_t *sched_ctrl =&UE->UE_sched_ctrl; - - const NR_TDD_UL_DL_Pattern_t *tdd = - scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - int num_slots_per_period; - int last_ul_slot; - if (tdd) { // Force the default transmission in a full slot as early as possible in the UL portion of TDD period (last_ul_slot) - num_slots_per_period = n / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity); - last_ul_slot = 1 + tdd->nrofDownlinkSlots; - } else { - num_slots_per_period = n; - last_ul_slot = sched_ctrl->last_ul_slot; - } - + /** + * Force the default transmission in a full slot as early + * as possible in the UL portion of TDD period (last_ul_slot) */ + int num_slots_per_period = fs->numb_slots_period; + int last_ul_slot = fs->is_tdd ? get_first_ul_slot(fs, false) : sched_ctrl->last_ul_slot; const int last_ul_sched = sched_ctrl->last_ul_frame * n + last_ul_slot; const int diff = (now - last_ul_sched + 1024 * n) % (1024 * n); /* UE is to be scheduled if @@ -1856,7 +1854,7 @@ static void pf_ul(module_id_t module_id, LOG_D(NR_MAC,"pf_ul: UE %04x harq_pid %d\n", UE->rnti, sched_pusch->ul_harq_pid); if (sched_pusch->ul_harq_pid >= 0) { /* Allocate retransmission*/ - const int tda = get_ul_tda(nrmac, scc, sched_frame, sched_slot); + const int tda = get_ul_tda(nrmac, sched_frame, sched_slot); bool r = allocate_ul_retransmission(nrmac, frame, slot, @@ -1893,7 +1891,11 @@ static void pf_ul(module_id_t module_id, const int B = max(0, sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes); /* preprocessor computed sched_frame/sched_slot */ - const bool do_sched = nr_UE_is_to_be_scheduled(scc, 0, UE, sched_frame, sched_slot, nrmac->ulsch_max_frame_inactivity); + const bool do_sched = nr_UE_is_to_be_scheduled(&nrmac->frame_structure, + UE, + sched_frame, + sched_slot, + nrmac->ulsch_max_frame_inactivity); LOG_D(NR_MAC,"pf_ul: do_sched UE %04x => %s\n", UE->rnti, do_sched ? "yes" : "no"); if ((B == 0 && !do_sched) || nr_timer_is_active(&sched_ctrl->transm_interrupt)) { @@ -1933,7 +1935,7 @@ static void pf_ul(module_id_t module_id, } sched_pusch->nrOfLayers = sched_ctrl->srs_feedback.ul_ri + 1; - sched_pusch->time_domain_allocation = get_ul_tda(nrmac, scc, sched_frame, sched_slot); + sched_pusch->time_domain_allocation = get_ul_tda(nrmac, sched_frame, sched_slot); sched_pusch->tda_info = get_ul_tda_info(current_BWP, sched_ctrl->coreset->controlResourceSetId, sched_ctrl->search_space->searchSpaceType->present, @@ -2086,7 +2088,7 @@ static void pf_ul(module_id_t module_id, sched_pusch->nrOfLayers = sched_ctrl->srs_feedback.ul_ri + 1; - sched_pusch->time_domain_allocation = get_ul_tda(nrmac, scc, sched_frame, sched_slot); + sched_pusch->time_domain_allocation = get_ul_tda(nrmac, sched_frame, sched_slot); sched_pusch->tda_info = get_ul_tda_info(current_BWP, sched_ctrl->coreset->controlResourceSetId, sched_ctrl->search_space->searchSpaceType->present, @@ -2215,7 +2217,7 @@ static bool nr_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_fram const int K2 = nr_mac->radio_config.minRXTXTIME + get_NTN_Koffset(scc); const int sched_frame = (frame + (slot + K2) / slots_frame) % MAX_FRAME_NUMBER; const int sched_slot = (slot + K2) % slots_frame; - if (!is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot)) + if (!is_ul_slot(sched_slot, &nr_mac->frame_structure)) return false; int num_beams = nr_mac->beam_info.beam_allocation ? nr_mac->beam_info.beams_per_period : 1; @@ -2274,7 +2276,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, n /* Uplink data ONLY can be scheduled when the current slot is downlink slot, * because we have to schedule the DCI0 first before schedule uplink data */ - if (!is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slot / 64], slot)) { + if (!is_dl_slot(slot, &nr_mac->frame_structure)) { LOG_D(NR_MAC, "Current slot %d is NOT DL slot, cannot schedule DCI0 for UL data\n", slot); return; } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 46deef46e8..4cd5563200 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -39,6 +39,14 @@ void set_cset_offset(uint16_t); void get_K1_K2(int N1, int N2, int *K1, int *K2, int layers); int get_NTN_Koffset(const NR_ServingCellConfigCommon_t *scc); +int get_first_ul_slot(const frame_structure_t *fs, bool mixed); +int get_ul_slots_per_period(const frame_structure_t *fs); +int get_ul_slots_per_frame(const frame_structure_t *fs); +int get_dl_slots_per_period(const frame_structure_t *fs); +int get_full_ul_slots_per_period(const frame_structure_t *fs); +int get_full_dl_slots_per_period(const frame_structure_t *fs); +int get_ul_slot_offset(const frame_structure_t *fs, int idx, bool count_mixed); + void mac_top_init_gNB(ngran_node_t node_type, NR_ServingCellConfigCommon_t *scc, NR_ServingCellConfig_t *scd, @@ -344,7 +352,9 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP, int binomial(int n, int k); -bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot); +bool is_ul_slot(const slot_t slot, const frame_structure_t *fs); +bool is_dl_slot(const slot_t slot, const frame_structure_t *fs); +bool is_mixed_slot(const slot_t slot, const frame_structure_t *fs); /* \brief Function to indicate a received SDU on ULSCH. @param Mod_id Instance ID of gNB @@ -406,13 +416,10 @@ uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx); uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format); -void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl, - const NR_UE_UL_BWP_t *ul_bwp, - const NR_ServingCellConfigCommon_t *scc); void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl); -int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot); -int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int frame, int slot); +int get_dl_tda(const gNB_MAC_INST *nrmac, int slot); +int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot); int get_cce_index(const gNB_MAC_INST *nrmac, const int CC_id, diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index bb1fba0fe8..c8604c431f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -905,13 +905,10 @@ typedef struct gNB_MAC_INST_s { NR_beam_info_t beam_info; - /// bitmap of DLSCH slots, can hold up to 160 slots - uint64_t dlsch_slot_bitmap[3]; - /// bitmap of ULSCH slots, can hold up to 160 slots - uint64_t ulsch_slot_bitmap[3]; - /// maximum number of slots before a UE will be scheduled ULSCH automatically uint32_t ulsch_max_frame_inactivity; + /// instance of the frame structure configuration + frame_structure_t frame_structure; /// DL preprocessor for differentiated scheduling nr_pp_impl_dl pre_processor_dl; diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index f6e7c15e8b..18487e9657 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -49,7 +49,9 @@ #include "constr_TYPE.h" #include "executables/softmodem-common.h" #include "oai_asn1.h" +#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" #include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h" +#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" #include "openair3/UTILS/conversions.h" #include "uper_decoder.h" #include "uper_encoder.h" @@ -312,9 +314,13 @@ static uint64_t get_ssb_bitmap(const NR_ServingCellConfigCommon_t *scc) return bitmap; } -static int set_ideal_period(const int n_slots_period, const int n_ul_slots_period) +static int set_ideal_period(bool is_csi) { - return MAX_MOBILES_PER_GNB * 2 * n_slots_period / n_ul_slots_period; // 2 reports per UE (RSRP and RI-PMI-CQI) + const frame_structure_t *fs = &RC.nrmac[0]->frame_structure; + const int nb_slots_per_period = fs->numb_slots_period; + const int n_ul_slots_per_period = get_ul_slots_per_period(fs); // full UL + mixed with UL symbols + // 2 reports per UE (RSRP and RI-PMI-CQI) + return is_csi ? MAX_MOBILES_PER_GNB * 2 * nb_slots_per_period / n_ul_slots_per_period : nb_slots_per_period * MAX_MOBILES_PER_GNB; } static void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0, @@ -389,16 +395,6 @@ static void config_csirs(const NR_ServingCellConfigCommon_t *servingcellconfigco nzpcsirs0->aperiodicTriggeringOffset = NULL; nzpcsirs0->trs_Info = NULL; asn1cSeqAdd(&csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list,nzpcsirs0); - - const NR_TDD_UL_DL_Pattern_t *tdd = servingcellconfigcommon->tdd_UL_DL_ConfigurationCommon ? - &servingcellconfigcommon->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - - const int n_slots_frame = slotsperframe[*servingcellconfigcommon->ssbSubcarrierSpacing]; - const int nb_slots_per_period = tdd ? n_slots_frame/get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity): n_slots_frame; - const int nb_dl_slots_period = tdd ? tdd->nrofDownlinkSlots : n_slots_frame; - const int n_ul_slots_period = tdd ? (tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0)) : n_slots_frame; - const int ideal_period = set_ideal_period(nb_slots_per_period, n_ul_slots_period); // same periodicity as CSI measurement report - if(!csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList) csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList = calloc(1,sizeof(*csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList)); NR_NZP_CSI_RS_Resource_t *nzpcsi0 = calloc(1,sizeof(*nzpcsi0)); @@ -447,7 +443,12 @@ static void config_csirs(const NR_ServingCellConfigCommon_t *servingcellconfigco nzpcsi0->powerControlOffsetSS = calloc(1,sizeof(*nzpcsi0->powerControlOffsetSS)); *nzpcsi0->powerControlOffsetSS = NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; nzpcsi0->scramblingID = *servingcellconfigcommon->physCellId; - set_csirs_periodicity(nzpcsi0, id, ideal_period, nb_slots_per_period, nb_dl_slots_period); + + const int ideal_period = set_ideal_period(true); // same periodicity as CSI measurement report + const frame_structure_t *fs = &(RC.nrmac[0]->frame_structure); + const int nb_dl_slots_period = get_full_dl_slots_per_period(fs); // full DL slots + set_csirs_periodicity(nzpcsi0, id, ideal_period, fs->numb_slots_period, nb_dl_slots_period); + nzpcsi0->qcl_InfoPeriodicCSI_RS = calloc(1,sizeof(*nzpcsi0->qcl_InfoPeriodicCSI_RS)); *nzpcsi0->qcl_InfoPeriodicCSI_RS = 0; asn1cSeqAdd(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpcsi0); @@ -628,15 +629,12 @@ long rrc_get_max_nr_csrs(const int max_rbs, const long b_SRS) { static struct NR_SRS_Resource__resourceType__periodic *configure_periodic_srs(const NR_ServingCellConfigCommon_t *scc, const int uid) { + frame_structure_t *fs = &RC.nrmac[0]->frame_structure; + int offset = get_ul_slot_offset(fs, uid, false); // only full UL slots for SRS - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - const int n_slots_frame = slotsperframe[*scc->ssbSubcarrierSpacing]; - const int ul_slots_period = tdd ? tdd->nrofUplinkSlots : n_slots_frame; - const int n_slots_period = tdd ? n_slots_frame/get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; - const int first_full_ul_slot = n_slots_period - ul_slots_period; - const int ideal_period = n_slots_period * MAX_MOBILES_PER_GNB; - const int offset = first_full_ul_slot + (uid % ul_slots_period) + (n_slots_period * (uid / ul_slots_period)); AssertFatal(offset < 2560, "Cannot allocate SRS configuration for uid %d, not enough resources\n", uid); + const int ideal_period = set_ideal_period(false); + struct NR_SRS_Resource__resourceType__periodic *periodic_srs = calloc(1,sizeof(*periodic_srs)); if (ideal_period < 5) { periodic_srs->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl4; @@ -907,7 +905,17 @@ void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsc if(frame_type==TDD) { // TDD if(tdd_UL_DL_ConfigurationCommon) { - int dl_symb = tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols; + int dl_symb = 0; + if (tdd_UL_DL_ConfigurationCommon->pattern2 && tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols) + AssertFatal(tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols == tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols, + "nrofDownlinkSymbols in pattern1 %ld and pattern2 %ld must be the same in current implementation\n", + tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols, + tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols); + if (tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols != 0) { + dl_symb = tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols; + } else if (tdd_UL_DL_ConfigurationCommon->pattern2) { + dl_symb = tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols; + } if(dl_symb > 1) { // mixed slot TDA with TDA index 2 struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation2 = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t)); @@ -919,6 +927,94 @@ void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsc } } +const float tdd_ms_period_pattern[] = {0.5, 0.625, 1.0, 1.25, 2.0, 2.5, 5.0, 10.0}; +const float tdd_ms_period_ext[] = {3.0, 4.0}; + +/** + * @brief Retrieves the periodicity in milliseconds for the given TDD pattern + * depending on the presence of the extension + * @param pattern Pointer to the NR_TDD_UL_DL_Pattern_t pattern structure + * @return Periodicity value in milliseconds. + */ +static float get_tdd_periodicity(NR_TDD_UL_DL_Pattern_t *pattern) { + if (!pattern->ext1) { + LOG_D(NR_MAC, "Setting TDD configuration period to dl_UL_TransmissionPeriodicity %ld\n", pattern->dl_UL_TransmissionPeriodicity); + return tdd_ms_period_pattern[pattern->dl_UL_TransmissionPeriodicity]; + } else { + DevAssert(pattern->ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL); + LOG_D(NR_MAC, + "Setting TDD configuration period to dl_UL_TransmissionPeriodicity_v1530 %ld\n", + *pattern->ext1->dl_UL_TransmissionPeriodicity_v1530); + return tdd_ms_period_ext[*pattern->ext1->dl_UL_TransmissionPeriodicity_v1530]; + } +} + +/** + * @brief Determines the TDD period index based on pattern periodicities + * @note Not applicabile to pattern extension + * @param tdd Pointer to the NR_TDD_UL_DL_ConfigCommon_t containing patterns + * @return Index of the TDD period in tdd_ms_period_pattern + */ +int get_tdd_period_idx(NR_TDD_UL_DL_ConfigCommon_t *tdd) +{ + int tdd_period_idx = 0; + float pattern1_ms = get_tdd_periodicity(&tdd->pattern1); + float pattern2_ms = tdd->pattern2 ? get_tdd_periodicity(tdd->pattern2) : 0.0; + bool found_match = false; + // Find matching TDD period in the predefined list of periodicities + for (int i = 0; i < NFAPI_MAX_NUM_PERIODS; i++) { + if ((pattern1_ms + pattern2_ms) == tdd_ms_period_pattern[i]) { + tdd_period_idx = i; + LOG_I(NR_MAC, + "TDD period index = %d, based on the sum of dl_UL_TransmissionPeriodicity " + "from Pattern1 (%f ms) and Pattern2 (%f ms): Total = %f ms\n", + tdd_period_idx, + pattern1_ms, + pattern2_ms, + pattern1_ms + pattern2_ms); + found_match = true; + break; + } + } + // Assert if no match was found + AssertFatal(found_match, "The sum of pattern1_ms and pattern2_ms does not match any value in tdd_ms_period_pattern"); + return tdd_period_idx; +} + +static struct NR_PUSCH_TimeDomainResourceAllocation *set_TimeDomainResourceAllocation(const int k2, uint8_t index, int ul_symb) +{ + struct NR_PUSCH_TimeDomainResourceAllocation *puschTdrAlloc = calloc_or_fail(1, sizeof(*puschTdrAlloc)); + puschTdrAlloc->k2 = calloc_or_fail(1, sizeof(*puschTdrAlloc->k2)); + *puschTdrAlloc->k2 = k2; + puschTdrAlloc->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; + switch (index) { + case 0: + puschTdrAlloc->startSymbolAndLength = get_SLIV(0, 13); + break; + case 1: + puschTdrAlloc->startSymbolAndLength = get_SLIV(0, 12); + break; + case 2: + // UL TDA index 2 for mixed slot (TDD) + puschTdrAlloc->startSymbolAndLength = + get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); // starting in fist ul symbol til the last but one + break; + case 3: { + // UL TDA index 3 for msg3 in the mixed slot (TDD) + int no_mix_slot = ul_symb < 3 ? 1 : 0; // we need at least 2 symbols for scheduling Msg3 + *puschTdrAlloc->k2 += no_mix_slot; + if (no_mix_slot) + puschTdrAlloc->startSymbolAndLength = get_SLIV(0, 13); // full allocation if there is no mixed slot + else + puschTdrAlloc->startSymbolAndLength = + get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); // starting in fist ul symbol til the last but one + } + break; + default: + break; + } + return puschTdrAlloc; +} void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay) { @@ -928,58 +1024,48 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay) scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; AssertFatal(tda->list.count == 0, "already have pusch_TimeDomainAllocationList members\n"); - frame_type_t frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing); const int k2 = min_fb_delay; - uint8_t DELTA[4]= {2,3,4,6}; // Delta parameter for Msg3 int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; + struct NR_SetupRelease_PUSCH_ConfigCommon *pusch_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon; // UL TDA index 0 is basic slot configuration starting in symbol 0 til the last but one symbol - struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); - pusch_timedomainresourceallocation->k2 = CALLOC(1,sizeof(long)); - *pusch_timedomainresourceallocation->k2 = k2; - pusch_timedomainresourceallocation->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - pusch_timedomainresourceallocation->startSymbolAndLength = get_SLIV(0, 13); - asn1cSeqAdd(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation); + asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, set_TimeDomainResourceAllocation(k2, 0, 0)); // UL TDA index 1 in case of SRS - struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation1 = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); - pusch_timedomainresourceallocation1->k2 = CALLOC(1,sizeof(long)); - *pusch_timedomainresourceallocation1->k2 = k2; - pusch_timedomainresourceallocation1->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - pusch_timedomainresourceallocation1->startSymbolAndLength = get_SLIV(0, 12); - asn1cSeqAdd(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation1); + asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, set_TimeDomainResourceAllocation(k2, 1, 0)); - if(frame_type==TDD) { - if(scc->tdd_UL_DL_ConfigurationCommon) { - int ul_symb = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols; - if (ul_symb>1) { - // UL TDA index 2 for mixed slot (TDD) - pusch_timedomainresourceallocation = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); - pusch_timedomainresourceallocation->k2 = CALLOC(1,sizeof(long)); - *pusch_timedomainresourceallocation->k2 = k2; - pusch_timedomainresourceallocation->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - pusch_timedomainresourceallocation->startSymbolAndLength = get_SLIV(14 - ul_symb, ul_symb - 1); // starting in fist ul symbol til the last but one - asn1cSeqAdd(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation); - } - // UL TDA index 3 for msg3 in the mixed slot (TDD) - int nb_periods_per_frame = get_nb_periods_per_frame(scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity); - int nb_slots_per_period = ((1 << mu) * 10) / nb_periods_per_frame; - struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation_msg3 = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); - pusch_timedomainresourceallocation_msg3->k2 = CALLOC(1,sizeof(long)); - int no_mix_slot = ul_symb < 3 ? 1 : 0; // we need at least 2 symbols for scheduling Msg3 - *pusch_timedomainresourceallocation_msg3->k2 = nb_slots_per_period - DELTA[mu] + no_mix_slot; - if(*pusch_timedomainresourceallocation_msg3->k2 < min_fb_delay) - *pusch_timedomainresourceallocation_msg3->k2 += nb_slots_per_period; - AssertFatal(*pusch_timedomainresourceallocation_msg3->k2 < 33,"Computed k2 for msg3 %ld is larger than the range allowed by RRC (0..32)\n", - *pusch_timedomainresourceallocation_msg3->k2); - pusch_timedomainresourceallocation_msg3->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - if(no_mix_slot) - pusch_timedomainresourceallocation_msg3->startSymbolAndLength = get_SLIV(0, 13); // full allocation if there is no mixed slot - else - pusch_timedomainresourceallocation_msg3->startSymbolAndLength = get_SLIV(14 - ul_symb, ul_symb - 1); // starting in fist ul symbol til the last but one - asn1cSeqAdd(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation_msg3); + if (scc->tdd_UL_DL_ConfigurationCommon) { + int ul_symb = 0; + NR_TDD_UL_DL_Pattern_t *p1 = &scc->tdd_UL_DL_ConfigurationCommon->pattern1; + NR_TDD_UL_DL_Pattern_t *p2 = scc->tdd_UL_DL_ConfigurationCommon->pattern2; + if (p2 && p2->nrofUplinkSymbols) + AssertFatal(p2->nrofUplinkSymbols == p1->nrofUplinkSymbols, + "nrofDownlinkSymbols in pattern1 %ld and pattern2 %ld must be the same in current implementation\n", + p1->nrofUplinkSymbols, + p2->nrofUplinkSymbols); + if (p1->nrofUplinkSymbols) { + ul_symb = p1->nrofUplinkSymbols; + } else if (p2) { + ul_symb = p1->nrofUplinkSymbols; } + if (ul_symb>1) { + // UL TDA index 2 for mixed slot (TDD) + asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, + set_TimeDomainResourceAllocation(k2, 2, ul_symb)); + } + // UL TDA index 3 for msg3 in the mixed slot (TDD) + int tdd_period_idx = get_tdd_period_idx(scc->tdd_UL_DL_ConfigurationCommon); + int nb_periods_per_frame = get_nb_periods_per_frame(tdd_period_idx); + int nb_slots_per_period = ((1 << mu) * 10) / nb_periods_per_frame; + int k2_msg3 = nb_slots_per_period - DELTA[mu]; + struct NR_PUSCH_TimeDomainResourceAllocation *puschTdrAllocMsg3 = set_TimeDomainResourceAllocation(k2_msg3, 3, ul_symb); + if (*puschTdrAllocMsg3->k2 < min_fb_delay) + *puschTdrAllocMsg3->k2 += nb_slots_per_period; + AssertFatal(*puschTdrAllocMsg3->k2 < 33, + "Computed k2 for msg3 %ld is larger than the range allowed by RRC (0..32)\n", + *puschTdrAllocMsg3->k2); + asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, puschTdrAllocMsg3); } } @@ -1118,10 +1204,10 @@ void set_pucch_power_config(NR_PUCCH_Config_t *pucch_Config, int do_csirs) { static void set_SR_periodandoffset(NR_SchedulingRequestResourceConfig_t *schedulingRequestResourceConfig, const NR_ServingCellConfigCommon_t *scc, int scs) { - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; + const frame_structure_t *fs = &RC.nrmac[0]->frame_structure; int sr_slot = 1; // in FDD SR in slot 1 - if(tdd) - sr_slot = get_first_ul_slot(tdd->nrofDownlinkSlots, tdd->nrofDownlinkSymbols, tdd->nrofUplinkSymbols); + if (fs->is_tdd) + sr_slot = get_first_ul_slot(fs, true); schedulingRequestResourceConfig->periodicityAndOffset = calloc(1,sizeof(*schedulingRequestResourceConfig->periodicityAndOffset)); @@ -1581,15 +1667,14 @@ static void set_csi_meas_periodicity(const NR_ServingCellConfigCommon_t *scc, int curr_bwp, bool is_rsrp) { - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - const int n_slots_frame = slotsperframe[*scc->ssbSubcarrierSpacing]; - const int n_ul_slots_period = tdd ? (tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0)) : n_slots_frame; - const int n_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; - const int ideal_period = set_ideal_period(n_slots_period, n_ul_slots_period); - const int first_ul_slot_period = tdd ? get_first_ul_slot(tdd->nrofDownlinkSlots, tdd->nrofDownlinkSymbols, tdd->nrofUplinkSymbols) : 0; + const int ideal_period = set_ideal_period(true); const int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp); const int idx = (uid * 2 / num_pucch2) + is_rsrp; - const int offset = first_ul_slot_period + idx % n_ul_slots_period + (idx / n_ul_slots_period) * n_slots_period; + + frame_structure_t *fs = &RC.nrmac[0]->frame_structure; + int offset = get_ul_slot_offset(fs, idx, true); + + LOG_D(NR_MAC, "set_csi_meas_periodicity: uid = %d, offset = %d, ideal_period = %d", uid, offset, ideal_period); AssertFatal(offset < 320, "Not enough UL slots to accomodate all possible UEs. Need to rework the implementation\n"); if (ideal_period < 5) { @@ -2499,7 +2584,10 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, AssertFatal(ServCellCom->tdd_UL_DL_ConfigurationCommon != NULL, "out of memory\n"); ServCellCom->tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing = scc->tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing; ServCellCom->tdd_UL_DL_ConfigurationCommon->pattern1 = scc->tdd_UL_DL_ConfigurationCommon->pattern1; - ServCellCom->tdd_UL_DL_ConfigurationCommon->pattern2 = scc->tdd_UL_DL_ConfigurationCommon->pattern2; + if (scc->tdd_UL_DL_ConfigurationCommon->pattern2) { + ServCellCom->tdd_UL_DL_ConfigurationCommon->pattern2 = calloc_or_fail(1, sizeof(struct NR_TDD_UL_DL_Pattern)); + *ServCellCom->tdd_UL_DL_ConfigurationCommon->pattern2 = *scc->tdd_UL_DL_ConfigurationCommon->pattern2; + } } ServCellCom->ss_PBCH_BlockPower = scc->ss_PBCH_BlockPower; diff --git a/openair2/RRC/NR/nr_rrc_config.h b/openair2/RRC/NR/nr_rrc_config.h index b9f030e897..3076b09f62 100644 --- a/openair2/RRC/NR/nr_rrc_config.h +++ b/openair2/RRC/NR/nr_rrc_config.h @@ -112,5 +112,6 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC int uid); NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t uid, const NR_ServingCellConfigCommon_t *scc); +int get_tdd_period_idx(NR_TDD_UL_DL_ConfigCommon_t *tdd); #endif diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.2pattern.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.2pattern.conf new file mode 100644 index 0000000000..89a1bb23c6 --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.2pattern.conf @@ -0,0 +1,247 @@ +Active_gNBs = ( "gNB-OAI" ); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( +{ + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1; sd = 1; }) }); + + nr_cellid = 12345678L; + + ////////// Physical parameters: + do_CSIRS = 1; + do_SRS = 1; + + servingCellConfigCommon = ( + { + # spCellConfigCommon + physCellId = 0; + + # downlinkConfigCommon + # frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641280; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640008; + # scs-SpecificCarrierList + dl_offstToCarrier = 0; + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + # initialDownlinkBWP + # genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + # pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + # uplinkConfigCommon + # frequencyInfoUL + ul_frequencyBand = 78; + # scs-SpecificCarrierList + ul_offstToCarrier = 0; + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + # initialUplinkBWP + # genericParameters + initialULBWPlocationAndBandwidth = 28875; + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + # rach-ConfigCommon + # rach-ConfigGeneric + prach_ConfigurationIndex = 154; + # prach_msg1_FDM + # 0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -96; + # preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; + # powerRampingStep + # 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; + # ra_ReponseWindow + # 1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; + # ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR + # 1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; + # one (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; + # ra_ContentionResolutionTimer + # (0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; + # prach-RootSequenceIndex_PR + # 1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precedence over the one derived from prach-ConfigIndex + msg1_SubcarrierSpacing = 1; + # restrictedSetConfig + # 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0; + msg3_DeltaPreamble = 1; + p0_NominalWithGrant = -90; + + # pucch-ConfigCommon setup : + # pucchGroupHopping + # 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; + + # ssb_PositionsInBurs_BitmapPR + # 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + + # ssb_periodicityServingCell + # 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + + # dmrs_TypeA_position + # 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + # tdd-UL-DL-ConfigurationCommon + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + # ext: 8=ms3, 9=ms4 + dl_UL_TransmissionPeriodicity = 8; + nrofDownlinkSlots = 3; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + # pattern2 + pattern2: { + dl_UL_TransmissionPeriodicity2 = 4; + nrofDownlinkSlots2 = 4; + nrofDownlinkSymbols2 = 0; + nrofUplinkSlots2 = 0; + nrofUplinkSymbols2 = 0; + }; + + ssPBCH_BlockPower = -25; + }); + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "192.168.70.132"; }); + + NETWORK_INTERFACES: { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; +} +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 150; + pucch_TargetSNRx10 = 200; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; + pucch0_dtx_threshold = 100; + ofdm_offset_divisor = 8; # set this to UINT_MAX for offset 0 +} +); + +RUs = ( +{ + local_rf = "yes"; + nb_tx = 1; + nb_rx = 1; + att_tx = 12; + att_rx = 12; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + clock_src = "internal"; +} +); + +rfsimulator : +{ + serveraddr = "server"; + serverport = 4043; + options = (); # ("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; + +security = { + # preferred ciphering algorithms + # the first one of the list that a UE supports is chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that a UE supports is chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level = "info"; + hw_log_level = "info"; + phy_log_level = "info"; + mac_log_level = "info"; + rlc_log_level = "info"; + pdcp_log_level = "info"; + rrc_log_level = "info"; + ngap_log_level = "info"; + f1ap_log_level = "info"; +};