def get_min_semiperiod_measurement(device_name):
    """Determines the minimum semi-period measurement time supported by the device.

    Depending on the timebase used, counter inputs can measure time intervals of
    various ranges. As a default, we pick a largish range - the one with the fastest
    timebase still capable of measuring 100 seconds, or the largest time interval if it
    is less than 100 seconds, and we save the smallest interval measurable with this
    timebase. Then labscript can ensure it doesn't make wait monitor pulses shorter than
    this. This should be a sensible default behaviour, though if the user has
    experiments considerably shorter or longer than 100 seconds, such that they want to
    use a different timebase, they may pass the min_semiperiod_measurement keyword
    argument into the DAQmx class, to tell labscript to make pulses some other duration
    compatible with the maximum wait time in their experiment. However, since there are
    software delays in timeouts of waits during a shot, any timed-out waits necessarily
    will last software timescales of up to ~100ms on a slow computer, preventing one
    from using very fast timebases with low-resolution counters if there is any
    possibility of timing out. For now (in the wait monitor worker class) we
    pessimistically add one second to the expected longest measurement to account for
    software delays. These decisions can be revisited if there is a need, do not
    hesitate to file an issue on bitbucket regarding this if it affects you.

    Args:
        device_name (str): NI-MAX device name

    Returns:
        float: Minimum measurement time.
    """
    CI_chans = DAQmxGetDevCIPhysicalChans(device_name)
    CI_chan = device_name + '/' + CI_chans[0]
    # Make a task with a semiperiod measurement
    task = Task()
    task.CreateCISemiPeriodChan(CI_chan, '', 1e-100, 1e100, c.DAQmx_Val_Seconds, "")
    try:
        task.StartTask()
    except PyDAQmx.DAQmxFunctions.CtrMinMaxError as e:
        # Parse the error to extract the allowed values:
        CI_ranges = []
        DT_MIN_PREFIX = "Value Must Be Greater Than:"
        DT_MAX_PREFIX = "Value Must Be Less Than:"
        error_lines = e.message.splitlines()
        for line in error_lines:
            if DT_MIN_PREFIX in line:
                dt_min = float(line.replace(DT_MIN_PREFIX, ''))
            if DT_MAX_PREFIX in line:
                dt_max = float(line.replace(DT_MAX_PREFIX, ''))
                CI_ranges.append([dt_min, dt_max])
    else:
        raise AssertionError("Can't figure out counter input ranges")
    finally:
        task.ClearTask()

    # Pick out the value we want. Either dtmin when dtmax is over 100, or the largest
    # dtmin if there is no dtmax over 100:
    for dtmin, dtmax in sorted(CI_ranges):
        if dtmax > 100:
            return dtmin
    return dtmin