{%- import 'slaplte.jinja2' as slaplte  with context %}
{%- set B               = slaplte.B %}
{%- set J               = slaplte.J %}
{%- set jcell_ru_ref    = slaplte.jcell_ru_ref %}
{%- set ierror          = slaplte.ierror %}
{%- set bug             = slaplte.bug %}

{#- for standalone testing via slapos-render-config.py
    NOTE: keep in sync with instance-enb.jinja2.cfg and ru/libinstance.jinja2.cfg   #}
{%- if _standalone is defined %}
{%-   set iru_dict   = {} %}
{%-   set icell_dict = {} %}
{%-   set ipeer_dict = {} %}
{%-   set ipeercell_dict = {} %}
{%-   do slaplte.load_iru_and_icell(iru_dict, icell_dict, icell_kind='enb') %}
{%-   do slaplte.load_ipeer(ipeer_dict) %}
{%-   do slaplte.load_ipeercell(ipeercell_dict) %}
{%-   do slaplte.check_loaded_everything()  %}
{%- endif %}


{#- do_lte/do_nr indicate whether we have LTE and/or NR cells
    icell_dict_lte/icell_dict_nr keep LTE/NR parts of icell_dict registry #}
{%- set icell_dict_lte = dict(icell_dict|dictsort | selectattr('1._.cell_type', '==', 'lte')) %}
{%- set icell_dict_nr  = dict(icell_dict|dictsort | selectattr('1._.cell_type', '==', 'nr' )) %}
{%- set do_lte = len(icell_dict_lte) > 0 %}
{%- set do_nr  = len(icell_dict_nr)  > 0 %}


{#- handover_config emits handover configuration for specified cell #}
{%- macro handover_config(cell_ref)  %}
      ncell_list: [
            // Intra-ENB HO
{%-       for cell2_ref, icell2 in icell_dict|dictsort %}
{%-         set cell2 = icell2['_'] %}
{%-         if cell2_ref != cell_ref %} {#- NOTE: HO to both LTE and NR #}
{%-           set ru2_ref = J(jcell_ru_ref(icell2, icell_dict)) %}
{%-           set iru2 = iru_dict[ru2_ref]  %}
{%-           set ru2 = iru2['_'] %}
            {
{%-           if cell2.cell_type == 'lte' %}
              rat:        "eutra",
              cell_id:    {{ slapparameter_dict.enb_id }}{{ cell2.cell_id.removeprefix('0x') }}, // -> {{ B(cell2_ref) }}
              n_id_cell:  {{ cell2.pci }},
              dl_earfcn:  {{ cell2.dl_earfcn }},
              tac:        {{ cell2.tac }},
              allowed_meas_bandwidth: {{ jlte_n_rb_dl(cell2.bandwidth) }},
              antenna_port_1: {{ (ru2.n_antenna_dl > 1)  | tojson }},
{%-           elif cell2.cell_type == 'nr' %}
              rat:        "nr",
              cell_id:    {{ cell2.cell_id }},  // -> {{ B(cell2_ref) }}
{%-           else  %}
{%-             do bug('unreachable') %}
{%-           endif %}
            },
{%-         endif %}
{%-       endfor %}

        // Inter-ENB HO
{#- TODO: add info about peers as shared instances - one instance per peer *ENB*.
          then query SlapOS Master about cells configured on that peer ENB and
          put them as peers here #}
{%-   for peercell_ref, ipeercell in ipeercell_dict|dictsort %}
{%-     set ncell = ipeercell['_']  %}
        {
{%-     if ncell.cell_type == 'lte' %}
          rat:          "eutra",
          cell_id:      {{ ncell.e_cell_id }},  // -> {{ B(peercell_ref) }}
          n_id_cell:    {{ ncell.pci }},
          dl_earfcn:    {{ ncell.dl_earfcn }},
          tac:          {{ ncell.tac }},
{#-       TODO: consider extending peer/cell/lte with
          .allowed_meas_bandwidth and .antenna_port_1 #}
          allowed_meas_bandwidth: {{ jlte_n_rb_dl(1.4) }},  // (minimum possible bw)
          antenna_port_1: false,      // (conservative stub)
{%-     elif ncell.cell_type == 'nr' %}
          rat:          "nr",
          nr_cell_id:   {{ ncell.nr_cell_id }}, // -> {{ B(peercell_ref) }}
          gnb_id_bits:  {{ ncell.gnb_id_bits }},
          n_id_cell:    {{ ncell.pci }},
          dl_nr_arfcn:  {{ ncell.dl_nr_arfcn }},
          band:         {{ ncell.nr_band }},
          ssb_nr_arfcn: {{ ncell.ssb_nr_arfcn }},
          ul_nr_arfcn:  {{ ncell.ul_nr_arfcn }},
          tac:          {{ ncell.tac }},
          ssb_subcarrier_spacing: 30,
          ssb_period: 20,
          ssb_offset: 0,
          ssb_duration: 1,
{%-   else  %}
{%-     do bug('unreachable') %}
{%-   endif %}
        },
{%- endfor %}
      ],
{%- endmacro %}

{#- jlte_n_rb_dl returns n_rb_dl for an LTE bandwidth. #}
{%- macro jlte_n_rb_dl(bandwidth) %}
{%-   set _ = {1.4:  6,
               3:   15,
               5:   25,
               10:  50,
               15:  75,
               20: 100} %}
{{-   _[bandwidth] | tojson }}
{%- endmacro %}

{#- jhostport splits address into (host,port) pair. #}
{%- macro jhostport(addr) %}
{%-   set _ = namespace() %}
{%-   if ':' not in addr  %}
{%-     set _.host = addr %}
{%-     set _.port = None %}
{%-   else  %}
{%-     set head, tail = addr.rsplit(':', 1) %}
{%-     if ':' not in head  %}
{%-       set _.host = head %}
{%-       set _.port = tail %}
{%-     else  %}
{%-       if addr.startswith('[')  %}
{%-         set _.host = addr[1:addr.index(']')]  %}
{%-         set _.port = tail  %}
{%-       else  %}
{%-         set _.host = addr %}
{%-         set _.port = None %}
{%-       endif %}
{%-     endif %}
{%-   endif %}
{{- (_.host, _.port) | tojson }}
{%- endmacro -%}


{#- start of the config -#}
{
  log_options: "all.level=error,all.max_size=0,nas.level=debug,nas.max_size=1,s1ap.level=debug,s1ap.max_size=1,x2ap.level=debug,x2ap.max_size=1,rrc.level=debug,rrc.max_size=1,ngap.level=debug,ngap.max_size=1,xnap.level=debug,xnap.max_size=1,
{%- if slapparameter_dict.get('log_phy_debug', False) -%}
    phy.level=debug
{%- else -%}
    phy.level=info
{%- endif -%}
    ,file.rotate=200M",
  log_filename: "{{ directory['log'] }}/enb.log",

{# instantiate radio units #}
{{ slaplte.ru_config(iru_dict, slapparameter_dict, True) }}

  com_addr: "{{ slapparameter_dict.com_addr }}:{{ slapparameter_dict.com_ws_port }}",
  com_auth: {
    password: "{{ websocket_password }}",
    unsecure: false,
  },

{%- if slapparameter_dict.get('mbmsgw_addr', '') %}
  mbmsgw_addr: "{{ slapparameter_dict.mbmsgw_addr }}",
{%- endif %}

{%  if do_lte %}
  // LTE core network
  mme_list: [
{%-   for _, mme in slapparameter_dict.mme_list |dictsort %}
    {
      mme_addr: "{{ mme['mme_addr'] }}",
{%-     if mme.get('s1ap_bind_addr', '') %}
      s1ap_bind_addr: "{{ mme['s1ap_bind_addr'] }}",
{%-     endif %}
    },
{%-   endfor %}
  ],
{%- endif %}

{%  if do_nr %}
  // NR core network
  amf_list: [
{%-   for _, amf in slapparameter_dict.amf_list |dictsort %}
    {
      amf_addr: "{{ amf['amf_addr'] }}",
{%-     if amf.get('ngap_bind_addr', '') %}
      ngap_bind_addr: "{{ amf['ngap_bind_addr'] }}",
{%-     endif %}
    },
{%-   endfor %}
  ],
{%- endif %}

{#- listen-address for GTP-U - either explicitly given, or autodetect #}
{%- if slapparameter_dict.get('gtp_addr') %}
  gtp_addr: "{{ slapparameter_dict.gtp_addr }}",
{%- else %}
{#-   use loopback if address of core network is on loopback as well #}
{%-   set vcore = []  %}
{%-   if do_lte %}
{%-     do vcore.extend(slapparameter_dict.mme_list |dictsort |map(attribute='1.mme_addr')) %}
{%-   endif %}
{%-   if do_nr %}
{%-     do vcore.extend(slapparameter_dict.amf_list |dictsort |map(attribute='1.amf_addr')) %}
{%-   endif %}
{#-   remove optional :port from addresses and see if they are on loopback #}
{%-   set vip = []  %}
{%-   for a in vcore  %}
{%-     set _ = namespace() %}
{%-     set _.ip   = J(jhostport(a))[0]  %}
{%-     set _.islo = netaddr.IPAddress(_.ip).is_loopback() %}
{%-     do vip.append(_)  %}
{%-   endfor  %}
{%-   if len(vip) > 0  and  all(vip |map(attribute='islo')) %}
  gtp_addr: "{{ gtp_addr_lo }}",
{%-   else  %}
{#-     core is external - use external ipv4/ipv6 #}
{%-     if slapparameter_dict.use_ipv4  %}
  gtp_addr: "{{ gtp_addr_v4 }}",
{%-     else %}
  gtp_addr: "{{ gtp_addr_v6 }}",
{%-     endif %}
{%-   endif %}
{%- endif %}

{#- X2/Xn peers
    TODO: add info about peers as shared instances - one instance per peer *ENB*.
          then query SlapOS Master about cells configured on that peer ENB and
          depending on whether LTE and/or NR cells are there add X2 and/or Xn peers #}
{%- if do_lte %}
  x2_peers: {{ ipeer_dict|dictsort | selectattr('1._.peer_type', '==', 'lte')
               | map(attribute='1._.x2_addr')
               | list | tojson }},
{%- endif %}
{%- if do_nr  %}
  xn_peers: {{ ipeer_dict|dictsort | selectattr('1._.peer_type', '==', 'nr')
               | map(attribute='1._.xn_addr')
               | list | tojson }},
{%- endif %}


{%- if do_lte %}
  enb_id: {{ slapparameter_dict.enb_id }},
{%- endif %}
{%- if do_nr %}
  gnb_id_bits: {{ slapparameter_dict.gnb_id_bits }},
  gnb_id: {{ slapparameter_dict.gnb_id }},
  en_dc_support: true,
{%- endif %}

  // LTE cells
  cell_list: [
{%- if do_lte %}
{%- for cell_ref, icell in icell_dict_lte|dictsort %}
{%-   set cell = icell['_'] %}
{%-   set ru_ref = J(jcell_ru_ref(icell, icell_dict)) %}
{%-   set iru = iru_dict[ru_ref]  %}
{%-   set ru = iru['_'] %}

    // {{ B(cell_ref) }}  ({{ B(ru_ref) }})
    {
      rf_port:      {{ ru._rf_port }},
      n_antenna_dl: {{ ru.n_antenna_dl }},
      n_antenna_ul: {{ ru.n_antenna_ul }},

      cell_id:    {{ cell.cell_id }},
      tac:        {{ cell.tac }},
      n_id_cell:  {{ cell.pci }},
      dl_earfcn:  {{ cell.dl_earfcn }},
      ul_earfcn:  {{ cell.ul_earfcn }},
      root_sequence_index: {{ cell.root_sequence_index }},
      inactivity_timer: {{ cell.inactivity_timer }},


      // Handover
{{-   handover_config(cell_ref) }}

      // Carrier Aggregation: LTE + LTE
      scell_list: [
{%-   for cell2_ref, icell2 in icell_dict_lte|dictsort %}
{%-     set cell2 = icell2['_'] %}
{%-     if cell2_ref != cell_ref  %}
        {
          cell_id: {{ cell2.cell_id }},  // + {{ B(cell2_ref) }}
          cross_carrier_scheduling: false,
        },
{%-     endif %}
{%-   endfor %}
      ],

{%-   if do_nr  %}
      // Dual Connectivity: LTE + NR
      en_dc_scg_cell_list: [
{%-     for cell2_ref, icell2 in icell_dict_nr|dictsort %}
{%-       set cell2 = icell2['_'] %}
{%-       if cell2_ref != cell_ref %}
          {
            cell_id: {{ cell2.cell_id }}, // + {{ B(cell2_ref) }}
          },
{%-       endif %}
{%-     endfor  %}
      ],
{%-   endif %}


    // tune LTE parameters for the cell
{% if ors %}
    manual_ref_signal_power: true,
{% endif %}

{%- set tdd = (cell.rf_mode == 'tdd') %}
{%- if tdd %}
    uldl_config: {{
        {'[Configuration 2] 5ms 2UL 6DL (default)':        2,
         '[Configuration 6] 5ms 5UL 3DL (maximum uplink)': 6}
        [cell.tdd_ul_dl_config]
    }},
    sp_config: 7,
{%- endif %}

{%- set n_rb_dl = J(jlte_n_rb_dl(cell.bandwidth)) %}
    n_rb_dl: {{ n_rb_dl }},
    si_coderate: {{ 0.60  if n_rb_dl == 6  else 0.20 }},

    pdsch_dedicated: {
      p_a: {{ {4: -6, 2: -3}.get(ru.n_antenna_dl, 0) }},
      p_b: -1,
    },

    pdcch_format:       {{  1  if n_rb_dl == 6  else 2 }},
    prach_config_index: {{  0  if n_rb_dl == 6  else 4 }},
    initial_cqi:        {{  5  if n_rb_dl == 6  else 3 }},

    pucch_dedicated: {
      n1_pucch_sr_count: 11,
      cqi_pucch_n_rb: 1,
{#- for CA with 2 cells it is possible to use PUCCH 1b CS ack/nack #}
{%- if len(icell_dict_lte) == 2  %}
      ack_nack_feedback_mode_ca: "cs",
      n1_pucch_an_cs_count: 8,
{#- starting from 3 cells it is always PUCCH 3 for ack/nack in CA #}
{%- elif len(icell_dict_lte) >= 3  %}
      ack_nack_feedback_mode_ca: "pucch3",
      n3_pucch_an_n_rb: 3,
{%- endif %}
{%- if tdd  %}
      tdd_ack_nack_feedback_mode: "multiplexing", /* TDD only */
{%- endif %}
    },

{%-       if ru.n_antenna_dl >= 2  %}
    m_ri: 8,
    transmission_mode: 3,
{%-       endif %}

    srs_dedicated: {
{%-       if n_rb_dl == 6  %}
      srs_bandwidth_config: 7,
      srs_bandwidth: 3,
{%-       elif n_rb_dl == 15  %}
      srs_bandwidth_config: 6,
      srs_bandwidth: 1,
{%-       elif n_rb_dl == 25  %}
      srs_bandwidth_config: 3,
      srs_bandwidth: 1,
{%-       elif n_rb_dl == 50  %}
      srs_bandwidth_config: 2,
      srs_bandwidth: 2,
{%-       elif n_rb_dl == 75  %}
      srs_bandwidth_config: 2,
      srs_bandwidth: 2,
{%-       else  %}
      srs_bandwidth_config: 2,
      srs_bandwidth: 3,
{%-       endif %}
      srs_subframe_config: 3,
      srs_period: 40,
      srs_hopping_bandwidth: 0,
    },

    drb_config: "{{ B('%s-drb.cfg' % cell_ref) }}",

    sib_sched_list: [
      {
        filename: "{{ B('%s-sib23.asn' % cell_ref) }}",
        si_periodicity: 16,
      },
    ],
    },
    {%- endfor %}
{%- endif %}
  ],

{%- if do_lte %}
  cell_default: {
    plmn_list: [
{%- for _, plmn in slapparameter_dict.plmn_list |dictsort %}
      {
        plmn: "{{ plmn.plmn }}",
        reserved: {{ plmn.get('reserved', false) |tojson }},
        attach_without_pdn: {{ plmn.get('attach_without_pdn', false) |tojson }},
      },
{%- endfor %}
    ],
    cyclic_prefix: "normal",

    phich_duration: "normal",
    phich_resource: "1",

    si_value_tag: 0,
    cell_barred: false,
    intra_freq_reselection: true,
    q_rx_lev_min: -70,
    si_window_length: 40,

    si_pdcch_format: 2,

    n_symb_cch: 0,

    prach_freq_offset: -1,

    pusch_dedicated: {
      beta_offset_ack_index: 9,
      beta_offset_ri_index: 6,
      beta_offset_cqi_index: 6,
    },

    pusch_hopping_offset: -1,

    pusch_msg3_mcs: 0,

    dl_256qam: true,
    ul_64qam: true,

    sr_period: 20,

    cqi_period: 40,
{%-     if ors %}
    mac_config: {
       ul_max_harq_tx: 5,
       dl_max_harq_tx: 5,
    },
    dpc_pucch_snr_target: 25,
{%-     else %}
    mac_config: {
       ul_max_harq_tx: 28,
       dl_max_harq_tx: 28,
    },
    dpc_pucch_snr_target: 20,
{%-     endif %}

    pusch_max_its: 6,

    dpc: true,
    dpc_pusch_snr_target: 25,

    cipher_algo_pref: [],
    integ_algo_pref: [2, 1],

    srb_config: [
      {
        id: 1,
        maxRetxThreshold: 32,
        t_Reordering: 45,
        t_PollRetransmit: 60,
      },
      {
        id: 2 ,
        maxRetxThreshold: 32,
        t_Reordering: 45,
        t_PollRetransmit: 60,
      }
    ],

{#  TODO fully expose lte meas_config_desc in generic SR #}
  meas_config_desc: {
    a1_report_type: "rsrp",
    a1_rsrp: -70,
    a1_hysteresis: 0,
    a1_time_to_trigger: 640,
    a2_report_type: "rsrp",
    a2_rsrp: -80,
    a2_hysteresis: 0,
    a2_time_to_trigger: 640,
    a3_report_type: "rsrp",
    a3_offset: {{ slapparameter_dict.get('lte_handover_a3_offset', 6) }},
    a3_hysteresis: 0,
    a3_time_to_trigger: {{ slapparameter_dict.get('lte_handover_a3_time_to_trigger', 480) }},
  },
  meas_gap_config: "gp0",
  ho_from_meas: true,
  },
{%- endif %}

{%  if do_nr %}
  // NR cells
  nr_cell_list: [
{%- for cell_ref, icell in icell_dict_nr|dictsort  %}
{%-   set cell = icell['_'] %}
{%-   set ru_ref = J(jcell_ru_ref(icell, icell_dict)) %}
{%-   set iru = iru_dict[ru_ref]  %}
{%-   set ru = iru['_'] %}

      // {{ B(cell_ref) }}  ({{ B(ru_ref) }})
      {
        rf_port:      {{ ru._rf_port }},
        n_antenna_dl: {{ ru.n_antenna_dl }},
        n_antenna_ul: {{ ru.n_antenna_ul }},

        cell_id:      {{ cell.cell_id }},
        n_id_cell:    {{ cell.pci }},
        band:         {{ cell.nr_band }},
        dl_nr_arfcn:  {{ cell.dl_nr_arfcn }},
        ul_nr_arfcn:  {{ cell.ul_nr_arfcn }},
        bandwidth:    {{ cell.bandwidth }},

        subcarrier_spacing: {{ cell.subcarrier_spacing }},
        ssb_nr_arfcn:   {{ cell.ssb_nr_arfcn }},
        ssb_pos_bitmap: "{{ cell.ssb_pos_bitmap }}",

        root_sequence_index: {{ cell.root_sequence_index }},
        inactivity_timer: {{ cell.inactivity_timer }},

        // Handover
{{-     handover_config(cell_ref) }}

        // Carrier Aggregation: NR + NR
        scell_list: [
{%-     for cell2_ref, icell2 in icell_dict_nr|dictsort %}
{%-       set cell2 = icell2['_'] %}
{%-       if cell2_ref != cell_ref %}
          {
            cell_id: {{ cell2.cell_id }},  // + {{ B(cell2_ref) }}
          },
{%-       endif %}
{%-     endfor %}
        ],

        {#- NOTE: NR + LTE Dual Connectivity is setup via EN-DC only - via en_dc_scg_cell_list.
                  nr_dc_scg_cell_list sets up NR+NR Dual Connectivity #}

        // tune NR parameters for the cell
{%-     if ors %}
        manual_ref_signal_power: true,
{%-     if ors['one-watt'] %}
        ss_pbch_block_power: {{ ru.tx_gain - 54 }},
{%-     else %}
        ss_pbch_block_power: {{ ru.tx_gain - 35 }},
{%-     endif -%}
{%-     endif %}

{%-     set tdd = (cell.rf_mode == 'tdd') %}
{%-     set tdd_config =
            {'5ms 2UL 7DL 4/6 (default)':                      1,
             '2.5ms 1UL 3DL 2/10':                             2,
             '5ms 8UL 1DL 2/10 (EXPERIMENTAL maximum uplink)': 3,
             '5ms 6UL 3DL 10/2 (high uplink)':                 4}
            [cell.tdd_ul_dl_config]
            if tdd  else None  %}
{%      if tdd_config == 1 %}
         tdd_ul_dl_config: {
           pattern1: {
             period: 5,
             dl_slots: 7,
             dl_symbols: 6,
             ul_slots: 2,
             ul_symbols: 4,
           },
         },
{%      elif tdd_config == 2 %}
         tdd_ul_dl_config: {
           pattern1: {
             period: 2.5,
             dl_slots: 3,
             dl_symbols: 10,
             ul_slots: 1,
             ul_symbols: 2,
           },
         },
{%      elif tdd_config == 3 %}
         tdd_ul_dl_config: {
           pattern1: {
              period: 5, /* in ms */
              dl_slots: 1,
              dl_symbols: 10,
              ul_slots: 8,
              ul_symbols: 2,
           },
         },
{%      elif tdd_config == 4 %}
         tdd_ul_dl_config: {
           pattern1: {
              period: 5, /* in ms */
              dl_slots: 3,
              dl_symbols: 2,
              ul_slots: 6,
              ul_symbols: 10,
           },
         },
{%      endif %}

        prach: {
{%-     if ru.ru_type == "sunwave" %}
          msg1_frequency_start: 0,
{%-     endif %}
          ra_response_window: {{ 20 if tdd else 10 }},
        },

        pdcch: {
{%-     if ru.ru_type == "sunwave" %}
          n_rb_coreset0: 48,
          n_symb_coreset0: 1,
          dedicated_coreset: {
            duration: 1,
          },
{%-     endif %}
{%-     if tdd_config == 3 %}
          uss: {
            n_candidates: [ 0, 8, 1, 0, 0 ],
            dci_0_1_and_1_1: true,
          },
{%-     else %}
          uss: {
            n_candidates: [ 0, 2, 1, 0, 0 ],
            dci_0_1_and_1_1: true,
          },
{%-     endif %}
        },

        pdsch: {
{%-     if ru.ru_type == "sunwave" %}
          k0: 0,
          k1: [ 8, 7, 7, 6, 5, 4, 12, 11 ],
{%-     elif tdd_config == 3 %}
          k1: [4, 11],
{%-     endif %}
        },

        pusch: {
{%-     if ru.ru_type == "sunwave" %}
          k2: 4,
          msg3_k2: 7,
{%-     elif tdd_config == 3 %}
          k2: [11, 12, 4, 5, 6, 7, 7, 8],
          msg3_k2: 7,
{%-     endif %}
        },

        csi_rs: {
          nzp_csi_rs_resource: [
            {
{%-         if ru.n_antenna_dl == 1     %}
              n_ports: 1,
              frequency_domain_allocation: "row2",
              bitmap: "100000000000",
              cdm_type: "no_cdm",
{%-         elif ru.n_antenna_dl == 2   %}
              n_ports: 2,
              frequency_domain_allocation: "other",
              bitmap: "100000",
              cdm_type: "fd_cdm2",
{%-         elif ru.n_antenna_dl == 4   %}
              n_ports: 4,
              frequency_domain_allocation: "row4",
              bitmap: "100",
              cdm_type: "fd_cdm2",
{%-         elif ru.n_antenna_dl == 8   %}
              n_ports: 8,
              frequency_domain_allocation: "other",
              bitmap: "110011",
              cdm_type: "fd_cdm2",
{%-         else  %}
{%-           do ierror(iru, 'n_antenna_dl=%d is not supported' % ru.n_antenna_dl) %}
{%-         endif %}
            },
{%-     if tdd_config != 3 %}
            {
              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,
              power_control_offset: 0,
              power_control_offset_ss: 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,
              power_control_offset: 0,
              power_control_offset_ss: 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,
              power_control_offset: 0,
              power_control_offset_ss: 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,
              power_control_offset: 0,
              power_control_offset_ss: 0,
              period: 40,
              offset: 12,
              qcl_info_periodic_csi_rs: 0,
            },
{%-     endif %}
          ],

          nzp_csi_rs_resource_set: [
            {},
{%-     if tdd_config != 3 %}
            {
              csi_rs_set_id: 1,
              nzp_csi_rs_resources: [ 1, 2, 3, 4 ],
              repetition: false,
              trs_info: true,
            },
{%-     endif %}
          ],

          csi_resource_config: [
            {},
            {},
{%-     if tdd_config != 3 %}
            {
              csi_rsc_config_id: 2,
              nzp_csi_rs_resource_set_list: [ 1 ],
              resource_type: "periodic",
            },
{%-     endif %}
          ],

          csi_report_config: [
            {
{%-         if ru.n_antenna_dl > 1  %}
              codebook_config: {
                codebook_type: "type1",
                sub_type: "typeI_SinglePanel",
{%-           if ru.n_antenna_dl == 2 %}
{%-           elif ru.n_antenna_dl == 4 %}
                n1: 2,
                n2: 1,
                codebook_mode: 1,
{%-           elif ru.n_antenna_dl == 8 %}
                n1: 4,
                n2: 1,
                codebook_mode: 1,
{%-           endif %}
              },
{%-         endif %}
            },
          ],
        },

        drb_config: "{{ B('%s-drb.cfg' % cell_ref) }}",

      },
{%- endfor %}
  ],

  nr_cell_default: {
    ssb_period: 20,

    plmn_list: [
{%- for _, plmn in slapparameter_dict.plmn_list_5g |dictsort %}
      {
        plmn: "{{ plmn.plmn }}",
        tac: {{ plmn.tac }},
{%-   if plmn.get('ranac')  %}
        ranac: {{ plmn.ranac }},
{%-   endif %}
        reserved: {{ plmn.get('reserved', false) |tojson }},
        nssai: [
{%-   for _, nssai in slapparameter_dict.nssai |dictsort  %}
          {
            sst: {{ nssai.sst }},
{%-     if nssai.get('sd') %}
            sd: {{ nssai.sd }},
{%-     endif %}
          },
{%-   endfor  %}
        ],
      },
{%- endfor %}
    ],

    si_window_length: 40,
    cell_barred: false,
    intra_freq_reselection: true,
    q_rx_lev_min: -70,
    q_qual_min: -20,
    sr_period: 40,
    dmrs_type_a_pos: 2,
    prach: {
      prach_config_index: 160,
      msg1_subcarrier_spacing: 30,
      msg1_fdm: 1,
      msg1_frequency_start: -1,
      zero_correlation_zone_config: 15,
      preamble_received_target_power: -110,
      preamble_trans_max: 7,
      power_ramping_step: 4,
      restricted_set_config: "unrestricted_set",
      ra_contention_resolution_timer: 64,
      ssb_per_prach_occasion: 1,
      cb_preambles_per_ssb: 8,
    },
    pdcch: {
      search_space0_index: 0,
      dedicated_coreset: {
        rb_start: -1,
        l_crb: -1,
        duration: 0,
        precoder_granularity: "sameAsREG_bundle",
      },
      css: {
        n_candidates: [ 0, 0, 4, 0, 0 ],
      },
      rar_al_index: 2,
      si_al_index: 2,
      al_index: 1,
    },
    pdsch: {
      mapping_type: "typeA",
      dmrs_add_pos: 1,
      dmrs_type: 1,
      dmrs_max_len: 1,
      mcs_table: "qam256",
      rar_mcs: 2,
      si_mcs: 6,
    },
    csi_rs: {
      nzp_csi_rs_resource: [
        {
          csi_rs_id: 0,
          density: 1,
          first_symb: 4,
          rb_start: 0,
          l_crb: -1,
          power_control_offset: 0,
          power_control_offset_ss: 0,
          period: 80,
          offset: 1,
          qcl_info_periodic_csi_rs: 0,
        },
      ],
      nzp_csi_rs_resource_set: [
        {
          csi_rs_set_id: 0,
          nzp_csi_rs_resources: [ 0 ],
          repetition: false,
        },
      ],
     csi_im_resource: [
        {
          csi_im_id: 0,
          pattern: 1,
          subcarrier_location: 8,
          symbol_location: 8,
          rb_start: 0,
          l_crb: -1,
          period: 80,
          offset: 1,
        },
      ],
      csi_im_resource_set: [
        {
          csi_im_set_id: 0,
          csi_im_resources: [ 0 ],
        }
      ],
      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,
          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",
        },
      ],
      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: {
      dpc_snr_target: 25,
      pucch_group_hopping: "neither",
      hopping_id: -1,
      p0_nominal: -90,
        pucch1: {
          n_cs: 3,
          n_occ: 3,
          freq_hopping: true,
        },
        pucch2: {
          n_symb: 2,
          n_prb: 1,
          freq_hopping: true,
          simultaneous_harq_ack_csi: false,
          max_code_rate: 0.25,
        },
    },
    pusch: {
      dpc_snr_target: 25,
      mapping_type: "typeA",
      n_symb: 14,
      dmrs_add_pos: 1,
      dmrs_type: 1,
      dmrs_max_len: 1,
      tf_precoding: false,
      mcs_table: "qam256",
      mcs_table_tp: "qam256",
      ldpc_max_its: 5,
      p0_nominal_with_grant: -84,
      msg3_mcs: 4,
      msg3_delta_power: 0,
      beta_offset_ack_index: 9,
    },
    mac_config: {
      msg3_max_harq_tx: 5,
      ul_max_harq_tx: 5,
      dl_max_harq_tx: 5,
      ul_max_consecutive_retx: 30,
      dl_max_consecutive_retx: 30,
      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,
      sr_trans_max: 64,
    },
    cipher_algo_pref: [],
    integ_algo_pref: [2, 1],

{#  TODO fully expose nr meas_config_desc in generic SR #}
  meas_config_desc: {
    a1_report_type: "rsrp",
    a1_rsrp: -60,
    a1_hysteresis: 10,
    a1_time_to_trigger: 100,
    a2_report_type: "rsrp",
    a2_rsrp: -70,
    a2_hysteresis: 0,
    a2_time_to_trigger: 100,
    a3_report_type: "rsrp",
    a3_offset: {{ slapparameter_dict.get('nr_handover_a3_offset', 6) }},
    a3_hysteresis: 0,
    a3_time_to_trigger: {{ slapparameter_dict.get('nr_handover_time_to_trigger', 100) }},
    ssb_rsrq_filter_coeff: 3,
    ssb_sinr_filter_coeff: 5
  },
  meas_gap_config: {
    pattern_id: 0
  },


  },
{%- endif %}
}