amarisoft_enb: add NR support

this patch adds the ability to configure NR cells with
Amarisoft eNB. It adds the new DRB-NR template and updates
the normal enb.cfg template to allow using it as LTE only
or with NR cells (5G NSA).

Change-Id: Ia27bbc6db5920ce14bacabe8043601aa2adaa5fe
diff --git a/src/osmo_gsm_tester/templates/amarisoft_enb.cfg.tmpl b/src/osmo_gsm_tester/templates/amarisoft_enb.cfg.tmpl
index 2c6fcc0..89b531c 100644
--- a/src/osmo_gsm_tester/templates/amarisoft_enb.cfg.tmpl
+++ b/src/osmo_gsm_tester/templates/amarisoft_enb.cfg.tmpl
@@ -1,6 +1,5 @@
-/* lteenb configuration file version 2018-10-18
- * Copyright (C) 2015-2018 Amarisoft
- */
+/* OGT templated version of the lteenb configuration file for 4G and 5G NSA */
+
 {
 
 %if enb.license_server_addr != '0.0.0.0':
@@ -64,10 +63,15 @@
   /* high 20 bits of SIB1.cellIdentifier */
   enb_id: ${enb.id},
 
+% if int(enb.num_nr_cells) > 0:
+  nr_support: true,
+% endif
+
   /* list of cells */
   cell_list: [
 
 %for cell in enb.cell_list:
+%if loop.index == 0:
   {
     dl_earfcn: ${cell.dl_earfcn},
     rf_port: ${cell.rf_port},
@@ -87,10 +91,36 @@
       { cell_id: ${scell_id}, cross_carrier_scheduling: false, scheduling_cell_id: ${cell.cell_id}, ul_allowed: true},
 %endfor
     ],
+
+    nr_scell_list: [
+%for nr_scell_id in cell.nr_scell_list:
+      { cell_id: ${nr_scell_id} },
+%endfor
+    ],
   },
+%endif
 %endfor
   ], /* cell_list */
 
+% if int(enb.num_nr_cells) > 0:
+
+  nr_cell_list: [
+
+%for nr_cell in enb.nr_cell_list:
+  %if loop.index == 0:
+    {
+      rf_port: ${nr_cell.rf_port},
+      cell_id: ${nr_cell.cell_id},
+      band: ${nr_cell.band},
+      dl_nr_arfcn: ${nr_cell.dl_nr_arfcn},
+    },
+  %endif
+%endfor
+
+  ], /* nr_cell_list */
+
+% endif
+
   /* default cell parameters */
   cell_default: {
     /* Broadcasted PLMN identities */
@@ -123,7 +153,11 @@
     /* other SIBs, in same order as the scheduling list in SIB 1 */
     sib_sched_list: [ "amarisoft_sib23.asn" ],
 
+% if int(enb.num_prb) == 6:
     si_coderate: 0.30,   /* maximum code rate for SI/RA/P-RNTI messages */
+% else:
+    si_coderate: 0.20,   /* maximum code rate for SI/RA/P-RNTI messages */
+% endif
     si_pdcch_format: 2, /* 2 or 3. Log2 of the number of CCEs for PDCCH
                            for SI/RA/P-RNTI */
 
@@ -154,7 +188,11 @@
     pusch_msg3_mcs: 0,
 
     /* this CQI value is assumed when none is received from the UE */
+% if int(enb.num_prb) == 6:
     initial_cqi: 5,
+% else:
+    initial_cqi: 3,
+% endif
 
     /* if defined, force the PUSCH MCS for all UEs. Otherwise it is
        computed from the last received SRS/PUSCH. */
@@ -162,6 +200,9 @@
 
     transmission_mode: ${enb.transmission_mode},
 
+    dl_256qam: true,
+    ul_64qam: true,
+
     /* Scheduling request period (ms). Must be >= 40 for HD-FDD */
     sr_period: 20,
 
@@ -188,6 +229,9 @@
         // tdd_ack_nack_feedback_mode_r10: "cs",
 % endif
 
+        n1_pucch_sr_count: 11, /* increase if more UEs are needed */
+        cqi_pucch_n_rb: 1, /* increase if more UEs are needed */
+
         /* number of PUCCH 1b CS resources. It determines
            the maximum number of UEs that can be scheduled in one TTI
            using carrier aggregation with PUCCH 1b CS ack/nack feedback. */
@@ -266,6 +310,14 @@
         a3_offset: ${enb.a3_report_value},
         a3_hysteresis: ${enb.a3_hysteresis},
         a3_time_to_trigger: ${enb.a3_time_to_trigger},
+% if int(enb.num_nr_cells) > 0:
+        // NR events hard-coded
+        nr_b1_report_type: "rsrp",
+        nr_b1_rsrp: -100,
+        nr_b1_hysteresis: 0,
+        nr_b1_time_to_trigger: 100,
+        nr_rsrp_filter_coeff: 3
+% endif
     },
 
     /* measurement gap configuration */
@@ -276,4 +328,357 @@
     ho_from_meas: true,
 % endif
   },
-}
+
+% if int(enb.num_nr_cells) > 0:
+   nr_cell_default: {
+    subcarrier_spacing: 15, /* kHz */
+    ssb_subcarrier_spacing: 30,
+    bandwidth: ${enb.nr_bandwidth}, /* MHz */
+    n_antenna_dl: 1,
+    n_antenna_ul: 1,
+
+    /* force the timing TA offset (optional) */
+    n_timing_advance_offset: 0,
+
+    tdd_ul_dl_config: {
+      pattern1: {
+        period: 10,
+        dl_slots: 6,
+        dl_symbols: 0,
+        ul_slots: 3,
+        ul_symbols: 0,
+      },
+    },
+    ssb_pos_bitmap: "10000000",
+    ssb_period: 20, /* in ms */
+    n_id_cell: 500,
+
+    root_sequence_index: 1, /* PRACH root sequence index */
+
+    /* Scheduling request period (slots). */
+    sr_period: 40,
+
+    dmrs_type_a_pos: 2,
+
+    /* to limit the number of HARQ feedback in UL, use pdsch_harq_ack_max;
+       allows to workaround issues with SM-G977N for example */
+    //pdsch_harq_ack_max: 2,
+
+    prach: {
+      prach_config_index: 0,
+      msg1_subcarrier_spacing: 15, /* kHz */
+      msg1_fdm: 1,
+% if int(enb.nr_bandwidth) == 10:
+      msg1_frequency_start: 1,
+% else:
+      msg1_frequency_start: 3,
+% endif
+      zero_correlation_zone_config: 0,
+      preamble_received_target_power: -110, /* in dBm */
+      preamble_trans_max: 7,
+      power_ramping_step: 4, /* in dB */
+      ra_response_window: 10, /* in slots */
+      restricted_set_config: "unrestricted_set",
+      ra_contention_resolution_timer: 64, /* in ms */
+      ssb_per_prach_occasion: 1,
+      cb_preambles_per_ssb: 8,
+    },
+
+    pdcch: {
+      common_coreset: {
+        rb_start: -1, /* -1 to have the maximum bandwidth */
+        l_crb: -1, /* -1 means all the bandwidth */
+        duration: 1,
+        precoder_granularity: "sameAsREG_bundle",
+        //dmrs_scid: 0,
+      },
+
+      dedicated_coreset: {
+        rb_start: -1, /* -1 to have the maximum bandwidth */
+        l_crb: -1, /* -1 means all the bandwidth */
+        duration: 1,
+        precoder_granularity: "sameAsREG_bundle",
+        //dmrs_scid: 0,
+      },
+
+      css: {
+        n_candidates: [ 1, 1, 1, 0, 0 ],
+      },
+      rar_al_index: 2,
+
+      uss: {
+        n_candidates: [ 0, 2, 1, 0, 0 ],
+        dci_0_1_and_1_1: false,
+        force_dci_0_0: true, // Forces DCI format 0_0 for Uplink
+        force_dci_1_0: true, // Forces DCI format 1_0 for Downlink
+      },
+      al_index: 1,
+    },
+
+    pdsch: {
+      mapping_type: "typeA",
+      start_symb: 1,
+      n_symb: 13,
+      dmrs_add_pos: 1,
+      dmrs_type: 1,
+      dmrs_max_len: 1,
+      k0: 0, /* delay in slots from DCI to PDSCH */
+      /* delay in slots from PDSCH to PUCCH/PUSCH ACK/NACK */
+      k1: [ 8, 7, 6, 6, 5, 4],
+      mcs_table: "qam64",
+
+      rar_mcs: 2,
+      /* If defined, force the PDSCH MCS for all UEs. Otherwise it is computed
+       * based on DL channel quality estimation */
+      /* mcs: 24, */
+    },
+
+    csi_rs: {
+      nzp_csi_rs_resource: [
+        {
+          csi_rs_id: 0,
+          n_ports: 1,
+          frequency_domain_allocation: "row2",
+          bitmap: "100000000000",
+          cdm_type: "no_cdm",
+          density: 1,
+          first_symb: 4,
+          rb_start: 0,
+          l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
+          power_control_offset: 0, /* dB */
+          power_control_offset_ss: 0, /* dB */
+          scrambling_id: 0,
+          period: 80,
+          offset: 1, /* != 0 to avoid collision with SSB */
+          qcl_info_periodic_csi_rs: 0,
+        },
+#define USE_TRS        
+#ifdef USE_TRS
+        /* TRS : period of 40 ms, slots 1 & 2, symbols 4 and 8 */
+        {
+          csi_rs_id: 1,
+          n_ports: 1,
+          frequency_domain_allocation: "row1",
+          bitmap: "0001",
+          cdm_type: "no_cdm",
+          density: 3,
+          first_symb: 4,
+          rb_start: 0,
+          l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
+          power_control_offset: 0, /* dB */
+          power_control_offset_ss: 0, /* dB */
+          scrambling_id: 0,
+          period: 40,
+          offset: 11,
+          qcl_info_periodic_csi_rs: 0,
+        },
+        {
+          csi_rs_id: 2,
+          n_ports: 1,
+          frequency_domain_allocation: "row1",
+          bitmap: "0001",
+          cdm_type: "no_cdm",
+          density: 3,
+          first_symb: 8,
+          rb_start: 0,
+          l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
+          power_control_offset: 0, /* dB */
+          power_control_offset_ss: 0, /* dB */
+          scrambling_id: 0,
+          period: 40,
+          offset: 11,
+          qcl_info_periodic_csi_rs: 0,
+        },
+        {
+          csi_rs_id: 3,
+          n_ports: 1,
+          frequency_domain_allocation: "row1",
+          bitmap: "0001",
+          cdm_type: "no_cdm",
+          density: 3,
+          first_symb: 4,
+          rb_start: 0,
+          l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
+          power_control_offset: 0, /* dB */
+          power_control_offset_ss: 0, /* dB */
+          scrambling_id: 0,
+          period: 40,
+          offset: 12,
+          qcl_info_periodic_csi_rs: 0,
+        },
+        {
+          csi_rs_id: 4,
+          n_ports: 1,
+          frequency_domain_allocation: "row1",
+          bitmap: "0001",
+          cdm_type: "no_cdm",
+          density: 3,
+          first_symb: 8,
+          rb_start: 0,
+          l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
+          power_control_offset: 0, /* dB */
+          power_control_offset_ss: 0, /* dB */
+          scrambling_id: 0,
+          period: 40,
+          offset: 12,
+          qcl_info_periodic_csi_rs: 0,
+        },
+#endif
+      ],
+      nzp_csi_rs_resource_set: [
+        {
+          csi_rs_set_id: 0,
+          nzp_csi_rs_resources: [ 0 ],
+          repetition: false,
+        },
+#ifdef USE_TRS
+        {
+          csi_rs_set_id: 1,
+          nzp_csi_rs_resources: [ 1, 2, 3, 4 ],
+          repetition: false,
+          trs_info: true,
+        },
+#endif
+      ],
+      
+     csi_im_resource: [
+        {
+          csi_im_id: 0,
+          pattern: 1,
+          subcarrier_location: 8,
+          symbol_location: 8,
+          rb_start: 0,
+          l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
+          period: 80,
+          offset: 1, /* != 0 to avoid collision with SSB */
+        },
+      ],
+      csi_im_resource_set: [
+        {
+          csi_im_set_id: 0,
+          csi_im_resources: [ 0 ],
+        }
+      ],
+      /* ZP CSI-RS to set the CSI-IM REs to zero */
+      zp_csi_rs_resource: [
+        {
+          csi_rs_id: 0,
+          frequency_domain_allocation: "row4",
+          bitmap: "100",
+          n_ports: 4,
+          cdm_type: "fd_cdm2",
+          first_symb: 8,
+          density: 1,
+          rb_start: 0,
+          l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
+          period: 80,
+          offset: 1,
+        },
+      ],
+      p_zp_csi_rs_resource_set: [
+        {
+          zp_csi_rs_resources: [ 0 ],
+        },
+      ],
+
+      csi_resource_config: [
+        {
+          csi_rsc_config_id: 0,
+          nzp_csi_rs_resource_set_list: [ 0 ],
+          resource_type: "periodic",
+        },
+        {
+          csi_rsc_config_id: 1,
+          csi_im_resource_set_list: [ 0 ],
+          resource_type: "periodic",
+        },
+#ifdef USE_TRS
+        {
+          csi_rsc_config_id: 2,
+          nzp_csi_rs_resource_set_list: [ 1 ],
+          resource_type: "periodic",
+        },
+#endif
+      ],
+      csi_report_config: [
+        {
+          resources_for_channel_measurement: 0,
+          csi_im_resources_for_interference: 1,
+          report_config_type: "periodic",
+          period: 80,
+          report_quantity: "CRI_RI_PMI_CQI",
+          cqi_table: 2,
+          subband_size: "value1",
+        },
+      ],
+    },
+    
+    pucch: {
+      pucch_group_hopping: "neither",
+      hopping_id: -1, /* -1 = n_cell_id */
+      p0_nominal: -90,
+        pucch1: {
+          n_cs: 3,
+          n_occ: 3,
+          freq_hopping: false,
+        },
+        pucch2: {
+          n_symb: 2,
+          n_prb: 1,
+          freq_hopping: false,
+          simultaneous_harq_ack_csi: false, 
+          max_code_rate: 0.25,
+        },
+    },
+
+    pusch: {
+      mapping_type: "typeA",
+      n_symb: 14,
+      dmrs_add_pos: 1,
+      dmrs_type: 1,
+      dmrs_max_len: 1,
+      tf_precoding: false,
+      mcs_table: "qam64", /* without transform precoding */
+      mcs_table_tp: "qam64", /* with transform precoding */
+      ldpc_max_its: 5,
+      k2: 4, /* delay in slots from DCI to PUSCH */
+      p0_nominal_with_grant: -90,
+      msg3_k2: 5,
+      msg3_mcs: 4,
+      msg3_delta_power: 0, /* in dB */
+      beta_offset_ack_index: 9,
+
+      /* hardcoded scheduling parameters */
+      n_dmrs_cdm_groups: 1,
+      n_layer: 1,
+      /* if defined, force the PUSCH MCS for all UEs. Otherwise it is
+       computed from the last received PUSCH. */
+      //mcs: 16,
+      //max_mcs: 16,
+    },
+
+    /* MAC configuration */
+    mac_config: {
+      msg3_max_harq_tx: 5,
+      ul_max_harq_tx: 5, /* max number of HARQ transmissions for uplink */
+      dl_max_harq_tx: 5, /* max number of HARQ transmissions for downlink */
+      ul_max_consecutive_retx: 30, /* disconnect UE if reached */
+      dl_max_consecutive_retx: 30, /* disconnect UE if reached */
+      periodic_bsr_timer: 20,
+      retx_bsr_timer: 320,
+      periodic_phr_timer: 500,
+      prohibit_phr_timer: 200,
+      phr_tx_power_factor_change: "dB3",
+      sr_prohibit_timer: 0, /* in ms, 0 to disable the timer */
+      sr_trans_max: 64,
+    },
+
+    cipher_algo_pref: [${', '.join(list(dict.fromkeys(enb.cipher_list))).split("eea")[1] if len(list(dict.fromkeys(enb.cipher_list))) > 0 else ''}],
+    integ_algo_pref: [${', '.join(list(dict.fromkeys(enb.integrity_list))).split("eia")[1]}],
+
+    inactivity_timer: ${enb.inactivity_timer},
+
+    drb_config: "amarisoft_drb_nr.cfg",
+  },
+% endif
+}
\ No newline at end of file