Beispiel #1
0
def write(infofile, version, serial_number, calibfile, no_calib):
    if infofile is not None:
        if serial_number is not None or version is not None:
            raise click.UsageError(("--infofile and --version/--serial_number"
                                    " are mutually exclusive"))
        cape_data = CapeData.from_yaml(infofile)
        with EEPROM() as eeprom:
            eeprom.write_cape_data(cape_data)
    elif serial_number is not None or version is not None:
        if version is None or serial_number is None:
            raise click.UsageError(
                ("--version and --serial_number are required"))
        cape_data = CapeData.from_values(serial_number, version)
        with EEPROM() as eeprom:
            eeprom.write_cape_data(cape_data)

    if calibfile is not None:
        if no_calib:
            raise click.UsageError(
                "--no-calib and --calibfile are mutually exclusive")
        calib = CalibrationData.from_yaml(calibfile)
        with EEPROM() as eeprom:
            cape_data = eeprom.write_calibration(calib)
    if no_calib:
        calib = CalibrationData.from_default()

        with EEPROM() as eeprom:
            eeprom.write_calibration(calib)
Beispiel #2
0
def make(filename, output_path):
    cd = CalibrationData.from_measurements(filename)
    if output_path is None:
        print(repr(cd))
    else:
        with open(output_path, "w") as f:
            f.write(repr(cd))
Beispiel #3
0
def data_h5(tmp_path):
    store_path = tmp_path / "record_example.h5"
    with LogWriter(store_path, CalibrationData.from_default()) as store:
        for i in range(100):
            len_ = 10_000
            fake_data = DataBuffer(random_data(len_), random_data(len_), i)
            store.write_buffer(fake_data)
    return store_path
Beispiel #4
0
def log_writer(tmp_path):
    calib = CalibrationData.from_default()
    with LogWriter(
            force_overwrite=True,
            store_path=tmp_path / "test.h5",
            mode="load",
            calibration_data=calib,
    ) as lw:
        yield lw
Beispiel #5
0
def log_writer(tmp_path, mode):
    calib = CalibrationData.from_default()
    with LogWriter(
            mode=mode,
            calibration_data=calib,
            force=True,
            store_path=tmp_path / "test.h5",
    ) as lw:
        yield lw
Beispiel #6
0
def emulator(request, shepherd_up, log_reader):
    emu = Emulator(
        calibration_recording=log_reader.get_calibration_data(),
        calibration_emulation=CalibrationData.from_default(),
        initial_buffers=log_reader.read_buffers(end=64),
    )
    request.addfinalizer(emu.__del__)
    emu.__enter__()
    request.addfinalizer(emu.__exit__)
    return emu
Beispiel #7
0
def emulator(request, shepherd_up, log_reader, virtsource_settings_yml):
    vs_settings = VirtualSourceData(virtsource_settings_yml)
    emu = Emulator(
        calibration_recording=log_reader.get_calibration_data(),
        calibration_emulation=CalibrationData.from_default(),
        initial_buffers=log_reader.read_buffers(end=64),
        settings_virtsource=vs_settings,
    )
    request.addfinalizer(emu.__del__)
    emu.__enter__()
    request.addfinalizer(emu.__exit__)
    return emu
Beispiel #8
0
def data_calibration():
    return CalibrationData.from_default()
Beispiel #9
0
def test_from_bytestr(default_bytestr):
    calib = CalibrationData.from_bytestr(default_bytestr)
Beispiel #10
0
def test_from_measurements(data_meas_example_yml):
    calib = CalibrationData.from_measurements(data_meas_example_yml)
Beispiel #11
0
def test_from_yaml(data_example_yml):
    calib = CalibrationData.from_yaml(data_example_yml)
Beispiel #12
0
def test_from_default():
    calib = CalibrationData.from_default()
Beispiel #13
0
def default_calib():
    calib = CalibrationData.from_default()
    return calib
Beispiel #14
0
def calibration_data():
    cd = CalibrationData.from_default()
    return cd
Beispiel #15
0
class VirtualSource(object):
    """
    this is ported py-version of the pru-code, goals:
    - stay close to original code-base
    - offer a comparison for the tests
    - step 1 to a virtualization of emulation

    """

    vsc = dict()
    cal = CalibrationData.from_default()

    def __init__(self, vs_settings):
        """

        :param vs_settings: YAML-Path, dict, or regulator-name
        """
        # NOTE:
        #  - yaml is based on nA, mV, ms, uF
        #  - c-code and py-copy is using nA, uV, ns, nF, pW
        vs_settings = VirtualSourceData(vs_settings)
        values = vs_settings.export_for_sysfs()

        # CONSTs, TODO: bring to commons (datalog can probably benefit as well)
        ADC_SAMPLES_PER_BUFFER = 10000
        BUFFER_PERIOD_NS = 100000000
        SAMPLE_INTERVAL_NS = (BUFFER_PERIOD_NS / ADC_SAMPLES_PER_BUFFER)
        LUT_SIZE = 12
        self.vsc["LUT_size"] = LUT_SIZE

        # generate a new dict from raw_list (that is intended for PRU / sys_fs, see commons.h)
        self.vsc["converter_mode"] = values[0]

        # direct regulator
        self.vsc["C_output_nF"] = values[
            1]  # final (always last) stage to catch current spikes of target

        # boost regulator
        self.vsc["V_inp_boost_threshold_uV"] = values[
            2]  # min input-voltage for the boost converter to work
        self.vsc["C_storage_nF"] = values[3]
        self.vsc["V_storage_init_uV"] = values[
            4]  # allow a proper / fast startup
        self.vsc["V_storage_max_uV"] = values[5]  # -> boost shuts off

        self.vsc["V_storage_leak_nA"] = values[6]

        self.vsc["V_storage_enable_threshold_uV"] = values[
            7]  # -> target gets connected (hysteresis-combo with next value)
        self.vsc["V_storage_disable_threshold_uV"] = values[
            8]  # -> target gets disconnected

        self.vsc["interval_check_thresholds_ns"] = values[
            9]  # some BQs check every 65 ms if output should be disconnected

        self.vsc["V_pwr_good_low_threshold_uV"] = values[
            10]  # range where target is informed by output-pin
        self.vsc["V_pwr_good_high_threshold_uV"] = values[11]

        self.vsc["dV_stor_en_thrs_uV"] = values[12]

        # Buck Boost, ie. BQ25570)
        self.vsc["V_output_uV"] = values[13]
        self.vsc["dV_stor_low_uV"] = values[14]

        # LUTs
        LUT1_END = 15 + LUT_SIZE * LUT_SIZE
        LUT2_END = LUT1_END + LUT_SIZE
        self.vsc["LUT_inp_efficiency_n8"] = values[
            15:
            LUT1_END]  # depending on inp_voltage, inp_current, (cap voltage),
        self.vsc["LUT_inv_output_efficiency_n10"] = values[
            LUT1_END:LUT2_END]  # depending on output_current

        # boost internal state
        self.vsc["P_inp_pW"] = 0.0
        self.vsc["P_out_pW"] = 0.0
        self.vsc["dt_us_per_C_nF"] = SAMPLE_INTERVAL_NS / (
            1000 * self.vsc["C_storage_nF"])

        self.vsc["internal_check_thrs_sample"] = self.vsc[
            "interval_check_thresholds_ns"] / SAMPLE_INTERVAL_NS
        self.vsc["V_store_uV"] = self.vsc["V_storage_init_uV"]
        # buck internal state
        self.vsc["V_out_uV"] = self.vsc["V_output_uV"]
        self.vsc["V_out_dac_raw"] = 1023  # TODO: unimplemented

    def calc_inp_power(self, input_current_nA: int,
                       input_voltage_uV) -> NoReturn:

        V_inp_uV = 0
        if input_voltage_uV > self.vsc["V_inp_boost_threshold_uV"]:
            V_inp_uV = input_voltage_uV
        if V_inp_uV > self.vsc["V_store_uV"]:
            V_inp_uV = self.vsc["V_store_uV"]

        eta_inp = self.get_input_efficieny(input_voltage_uV, input_current_nA)
        self.vsc["P_inp_pW"] = V_inp_uV * input_current_nA * eta_inp

    def calc_out_power(self, current_adc_raw):

        I_out_nA = self.conv_adc_raw_to_nA(current_adc_raw)
        eta_inv_out = self.get_output_efficiency(current_adc_raw)
        dP_leak_pW = self.vsc["V_store_uV"] * self.vsc["I_storage_leak_nA"]
        self.vsc["P_out_pW"] = I_out_nA * self.vsc[
            "V_out_uV"] * eta_inv_out + dP_leak_pW

    def update_capacitor(self):

        P_sum_pW = self.vsc["P_inp_pW"] - self.vsc["P_out_pW"]
        I_cStor_nA = P_sum_pW / self.vsc["V_store_uV"]
        dV_cStor_uV = I_cStor_nA * self.vsc["dt_us_per_C_nF"]
        self.vsc["V_store_uV"] = self.vsc["V_store_uV"] + dV_cStor_uV

    def update_buckboost(self) -> int:
        global sample_count, is_outputting

        if self.vsc["V_store_uV"] > self.vsc["V_storage_max_uV"]:
            self.vsc["V_store_uV"] = self.vsc["V_storage_max_uV"]

        sample_count += 1
        if sample_count == self.vsc["interval_check_thrs_sample"]:
            sample_count = 0
            if is_outputting:
                if (self.vsc["V_store_uV"] < self.vsc["V_out_uV"]) or \
                        (self.vsc["V_store_uV"] < self.vsc["V_storage_disable_threshold_uV"]):
                    is_outputting = False
            else:
                if self.vsc["V_store_uV"] > self.vsc["V_out_uV"]:
                    is_outputting = True
                    self.vsc["V_store_uV"] = self.vsc["V_store_uV"] - self.vsc[
                        "dV_stor_low_uV"]
                if self.vsc["V_store_uV"] > self.vsc[
                        "V_storage_disable_threshold_uV"]:
                    is_outputting = True
                    self.vsc["V_store_uV"] = self.vsc["V_store_uV"] - self.vsc[
                        "dV_stor_en_thrs_uV"]

        return self.vsc["V_out_dac_raw"] if is_outputting else 0

    def conf_adc_raw_to_nA(self, current_raw: int) -> float:
        return self.cal.convert_raw_to_value("emulation", "adc_current",
                                             current_raw) * (10**9)

    def conv_uV_to_dac_raw(self, voltage_uV: int) -> int:
        return self.cal.convert_value_to_raw("emulation", "dac_voltage_b",
                                             float(voltage_uV) / (10**6))

    def get_input_efficiency(self, voltage_uV: int, current_nA: int) -> float:
        pos_v = int(round(math.log2(voltage_uV)))
        pos_c = int(round(math.log2(current_nA)))
        for value in pos_v, pos_c:
            if value >= self.vsc["LUT_size"]:
                value = self.vsc["LUT_size"] - 1
        return self.vsc["LUT_inp_efficiency_n8"][pos_v * self.vsc["LUT_size"] *
                                                 pos_c] / (2**8)

    def get_output_efficiency(self, current) -> float:
        pos_c = int(round(math.log2(current)))
        if pos_c >= self.vsc["LUT_size"]:
            pos_c = self.vsc["LUT_size"] - 1
        return self.vsc["LUT_out_inv_efficiency_n10"][pos_c] / (2**10)

    def set_input_power_pW(self, value):
        self.vsc["P_inp_pW"] = value

    def set_output_power_pW(self, value):
        self.vsc["P_out_pW"] = value

    def set_storage_Capacitor_uV(self, value):
        self.vsc["V_store_uV"] = value

    def get_input_power_pW(self, value):
        return self.vsc["P_inp_pW"]

    def get_output_power_pW(self, value):
        return self.vsc["P_out_pW"]

    def get_storage_Capacitor_uV(self, value):
        return self.vsc["V_store_uV"]