[buildout]
extends =
  ${template:output}

[switch-softwaretype]
enb = dynamic-template-ors-enb:output
gnb = dynamic-template-ors-enb:output
obsolete = dynamic-template-obsolete:output
enb-epc = $${:obsolete}
gnb-epc = $${:obsolete}
epc = $${:obsolete}
mme = $${:obsolete}
ue =

[dynamic-template-obsolete]
< = jinja2-template-base
url = ${template-obsolete:target}
filename = instance-obsolete.cfg
extensions = jinja2.ext.do
extra-context =
    key slave_instance_list slap-configuration:slave-instance-list

# ORS-specific enb and gnb
# both are served by instance-ors-enb, which translates
# ORS enb/gnb schemas to generic enb with only one RU and one LTE or NR CELL
[dynamic-template-ors-enb]
< = dynamic-template-enb
url = ${template-ors-enb:target}
filename = instance-enb.cfg
extra-context +=
    section ors ors-version
    section ors_version ors-version
import-list +=
    rawfile instance-enb-base.jinja2.cfg ${template-enb:target}

[ors-version]
recipe = slapos.recipe.build
configuration = $${slap-configuration:configuration}
init =
  import subprocess
  range_map = {
    "B28": "758MHz - 803MHz",
    "B38": "2570MHz - 2620MHz",
    "B39": "1880MHz - 1920MHz",
    "B40": "2300MHz - 2400MHz",
    "B41": "2496MHz - 2690MHz",
    "B42": "3400MHz - 3600MHz",
    "B43": "3600MHz - 3800MHz",
    "N77": "3300MHz - 4200MHz",
    "N79": "4400MHz - 5000MHz",
    "UNKNOWN": "Information not available for this band",
  }
  default_tx_gain_map = {
    "B28": (60, 62),
    "B38": (59, 65),
    "B39": (59, 64),
    "B40": (59, 64),
    "B41": (59, 64),
    "B42": (63, 62),
    "B43": (63, 62),
    "N77": (60, 62),
    "N79": (60, 62),
    "UNKNOWN": (60, 62),
  }
  default_rx_gain_map = {
    "B28": (25, 25),
    "B38": (25, 25),
    "B39": (25, 25),
    "B40": (25, 25),
    "B41": (25, 25),
    "B42": (25, 25),
    "B43": (25, 25),
    "N77": (25, 25),
    "N79": (25, 25),
    "UNKNOWN": (25, 25),
  }
  default_earfcn_map = {
    "B28": 9550,
    "B38": 38050,
    "B39": 38350,
    "B40": 39150,
    "B41": 40620,
    "B42": 42590,
    "B43": 44590,
    "N77": 0,
    "N79": 0,
    "UNKNOWN": 0,
  }
  default_nr_arfcn_map = {
    "B28": 0,
    "B38": 519000,
    "B39": 378000,
    "B40": 470000,
    "B41": 518600,
    "B42": 632628,
    "B43": 646666,
    "N77": 660000,
    "N79": 720000,
    "UNKNOWN": 0,
  }
  default_nr_band_map = {
    "B28": 0,
    "B38": 41,
    "B39": 39,
    "B40": 40,
    "B41": 41,
    "B42": 78,
    "B43": 78,
    "N77": 77,
    "N79": 79,
    "UNKNOWN": 0,
  }
  power_map = {
    "B28": (
      lambda x: "UNKNOWN",
      lambda x: "UNKNOWN",
    ),
    "B38": (
      lambda x: (-0.008712931375092506) * x**2 + (2.1973585140044642) * x + (-94.29420762479742),
      lambda x: (-0.004472751640641793) * x**2 + (1.6308290630103919) * x + (-81.84549245154561),
    ),
    "B39": (
      lambda x: (-0.008712931375092506) * x**2 + (2.1973585140044642) * x + (-94.29420762479742),
      lambda x: (-0.0022523817802900985) * x**2 + (1.2674016231310092) * x + (-66.57165215468584),
    ),
    "B40": (
      lambda x: "UNKNOWN",
      lambda x: "UNKNOWN",
    ),
    "B41": (
      lambda x: "UNKNOWN",
      lambda x: "UNKNOWN",
    ),
    "B42": (
      lambda x: (-0.014198126839751619) * x**2 + (2.980758813262773) * x + (-125.25800492285738),
      lambda x: (0.003977721774394756) * x**2 + (0.527208191717173) * x + (-42.761142655285376),
    ),
    "B43": (
      lambda x: (-0.014198126839751619) * x**2 + (2.980758813262773) * x + (-125.25800492285738),
      lambda x: (-0.0036530114002551943) * x**2 + (1.510856844601873) * x + (-74.58790185136355),
    ),
    "N77": (
      lambda x: "UNKNOWN",
      lambda x: "UNKNOWN",
    ),
    "N79": (
      lambda x: "UNKNOWN",
      lambda x: "UNKNOWN",
    ),
    "UNKNOWN": (
      lambda x: "UNKNOWN",
      lambda x: "UNKNOWN",
    ),
  }
  def get_sdr_info(cmd):
    if options['configuration'].get('testing', False):
      return {'t': 'TDD', 'b': 'B39', 'v': '4.2', 's': 'B53'}[cmd].encode()
    return subprocess.check_output(
      ["sudo", "-n", "/opt/amarisoft/get-sdr-info", "-" + cmd]
    )
  version = get_sdr_info('v').decode()
  options['version'] = float(version) if version != 'UNKNOWN' else 0
  options['band'] = get_sdr_info('b').decode()
  options['tdd'] = get_sdr_info('t').decode()
  options['one-watt'] = bool(options['version'] >= 4)
  options['ors-version'] = "{} {} {}".format(
    options['tdd'],
    options['band'],
    "2x1W" if options['one-watt'] else "2x0.5W",
  )
  default_tx_gain  = default_tx_gain_map [options['band']][int(options['one-watt'])]
  default_rx_gain  = default_rx_gain_map [options['band']][int(options['one-watt'])]
  default_earfcn   = default_earfcn_map  [options['band']]
  default_nr_arfcn = default_nr_arfcn_map[options['band']]
  default_nr_band  = default_nr_band_map [options['band']]
  options['range']            = range_map           [options['band']]
  options['current-tx-gain']  = options['configuration'].get('tx_gain'    , default_tx_gain )
  options['current-rx-gain']  = options['configuration'].get('rx_gain'    , default_rx_gain )
  options['current-earfcn']   = options['configuration'].get('dl_earfcn'  , default_earfcn  )
  options['current-nr-arfcn'] = options['configuration'].get('dl_nr_arfcn', default_nr_arfcn)
  options['current-nr-band']  = options['configuration'].get('nr_band'    , default_nr_band )
  power_estimate_dbm = power_map[options['band']][int(options['one-watt'])](float(options['current-tx-gain']))
  if power_estimate_dbm == "UNKNOWN":
    power_estimate = "Information not available for this band"
  else:
    power_estimate_mw = 10 ** ( power_estimate_dbm / 10 )
    if power_estimate_mw < 0.01:
      power_estimate_s = "{:0.2f} µW".format(power_estimate_mw * 1000)
    else:
      power_estimate_s = "{:0.2f} mW".format(power_estimate_mw)
    power_estimate = "{:0.2f} dBm ({})".format(power_estimate_dbm, power_estimate_s)
  options['power-estimate'] = power_estimate