"""Integer timer-divider calculator, independent of vendor hardware."""
from fractions import Fraction


def frequency(clock, psc, arr):
    if clock <= 0 or not (0 <= psc <= 65535 and 0 <= arr <= 65535):
        raise ValueError("clock must be positive; dividers must fit this 16-bit model")
    return Fraction(clock, (psc + 1) * (arr + 1))


def find_exact(clock, target):
    for psc in range(65536):
        denominator = target * (psc + 1)
        if clock % denominator == 0:
            arr = clock // denominator - 1
            if 0 <= arr <= 65535:
                return psc, arr
    return None


def main():
    assert frequency(84_000_000, 83, 999) == 1000
    pair = find_exact(84_000_000, 1000)
    assert pair is not None and frequency(84_000_000, *pair) == 1000
    assert frequency(84_000_000, 0, 0) == 84_000_000
    try:
        frequency(84_000_000, -1, 999)
    except ValueError:
        pass
    else:
        raise AssertionError("invalid register value accepted")
    print(f"84 MHz, PSC=83, ARR=999 -> 1000 Hz; first exact pair={pair}")
    print("ISR toggling each update -> 500 Hz square wave")
    print("PASS")


if __name__ == "__main__":
    main()
