#!/usr/bin/env python

"""
Copyright (c) 2025 Silicon Laboratories Inc.

SPDX-License-Identifier: Apache-2.0
"""
import argparse
import datetime
import re
from pathlib import Path

devices = {
  "xg21": {
    "bits": "platform/Device/SiliconLabs/EFR32MG21/Include/efr32mg21_iadc.h",
    "values": {
      "SUPPLY": {
        0: "AVDD",
        1: "IOVDD",
        4: "DVDD",
        7: "DECOUPLE"
      }
    }
  },
  "xg22": {
    "bits": "platform/Device/SiliconLabs/EFR32BG22/Include/efr32bg22_iadc.h",
    "values": {
      "SUPPLY": {
        0: "AVDD",
        1: "IOVDD",
        4: "DVDD",
        7: "DECOUPLE"
      }
    }
  },
  "xg23": {
    "bits": "platform/Device/SiliconLabs/EFR32FG23/Include/efr32fg23_iadc.h",
    "values": {
      "SUPPLY": {
        0: "AVDD",
        1: "IOVDD",
        4: "DVDD",
        7: "DECOUPLE"
      }
    }
  },
  "xg24": {
    "bits": "platform/Device/SiliconLabs/EFR32MG24/Include/efr32mg24_iadc.h",
    "values": {
      "SUPPLY": {
        0: "AVDD",
        1: "IOVDD",
        4: "DVDD",
        7: "DECOUPLE"
      }
    }
  },
  "xg27": {
    "bits": "platform/Device/SiliconLabs/EFR32BG27/Include/efr32bg27_iadc.h",
    "values": {
      "SUPPLY": {
        0: "AVDD",
        1: "IOVDD",
        2: "VBAT",
        4: "DVDD",
        7: "DECOUPLE"
      }
    }
  },
  "xg29": {
    "bits": "platform/Device/SiliconLabs/EFR32BG29/Include/efr32bg29_iadc.h",
    "values": {
      "SUPPLY": {
        0: "AVDD",
        1: "IOVDD",
        2: "VBAT",
        4: "DVDD",
        7: "DECOUPLE"
      }
    }
  }
}

alias = {
  "PADANA0": "AIN0",
  "PADANA1": "AIN1",
  "PADANA2": "AIN2",
  "PADANA3": "AIN3",
}

def insert(values, key, val):
  if key in values:
    assert values[key] == val, f"{key} = {values[key]} from a previous device, new value = {val}"
  else:
    values[key] = val


if __name__ == "__main__":
  parser = argparse.ArgumentParser(description="Generate headers for ADC for Series 2 "
                                   "devices. The headers are used from DeviceTree, and represent "
                                   "every ADC input as a DT compatible macro.")
  parser.add_argument("--out", "-o", type=Path, default=Path(__file__).parent / "out",
                      help="Output directory. Defaults to the directory ./out/ relative to the "
                      "script. Set to $ZEPHYR_BASE/include/zephyr/dt-bindings/adc/ "
                      "to directly generate output into the expected location within the Zephyr "
                      "main tree.")
  parser.add_argument("--sdk", "-s", type=Path, default=Path(__file__).parent.parent / "simplicity_sdk",
                      help="Path to Simplicity SDK to extract data from. Defaults to the directory "
                       "../simplicity_sdk relative to the script.")
  args = parser.parse_args()

  args.out.mkdir(exist_ok=True)

  values = {}
  for device, data_source in devices.items():
    print(f"Parse ADC data for {device}")

    with (args.sdk / data_source["bits"]).open() as f:
      for line in f:
        if m := re.match(r"#define _IADC_SINGLE_PORT(POS|NEG)_([^\s]+)\s+(0x[0-9A-F]*)UL", line):
          port = m.group(2)
          port_base = int(m.group(3), base=16) * 16
          if port in ["MASK", "DEFAULT"]:
             continue
          if port in data_source["values"]:
            for value, key in data_source["values"][port].items():
              insert(values, key, port_base + value)
          elif port.startswith("PORT"):
            for pin in range(16):
              insert(values, f"P{port[4]}{pin}", port_base + pin)
          else:
            insert(values, alias.get(port,port), port_base)

  file = [
    "/*",
    f" * Copyright (c) {datetime.date.today().year} Silicon Laboratories Inc.",
    " *",
    " * SPDX-License-Identifier: Apache-2.0",
    " *",
    f" * This file was generated by the script {Path(__file__).name} in the hal_silabs module.",
    " * Do not manually edit.",
    " */",
    "",
    f"#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ADC_SILABS_ADC_H_",
    f"#define ZEPHYR_INCLUDE_DT_BINDINGS_ADC_SILABS_ADC_H_",
    "",
  ]

  max_key = max(len(k) for k in values)
  for k, v in sorted(values.items(), key=lambda i: (i[1],i[0])):
    file.append(f"#define IADC_INPUT_{k}{' ' * (max_key - len(k) + 1)}0x{v:x}")

  file.append("")
  file.append(f"#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_ADC_SILABS_ADC_H_ */")
  file.append("")

  outfile = args.out / f"silabs-adc.h"
  outfile.write_text("\n".join(file))
