#!env python3 import json import sys import argparse from modenames import mode_names parser = argparse.ArgumentParser() parser.add_argument("--list-modes", help="list the available modes for tis file.", action = "store_true"); parser.add_argument("--temperature-range", help="only export waveforms in the temperature range of min,max °C."); parser.add_argument("--export-modes", help="comma-separated list of waveform mode IDs to export."); parser.add_argument("name", help="name of the waveform object."); args = parser.parse_args() waveforms = json.load(sys.stdin); total_size = 0 def phase_to_c(phase): """ Convert a 5 bit phase to a 4 bit C LUT. """ global total_size targets = [] for t in range(0, 32, 2): chunk = 0 line = [] for f in range(0, 32, 2): fr = phase[t][f] chunk = (chunk << 2) | fr if f and f % 8 == 6: line.append(chunk) chunk = 0 targets.append(line) total_size += len(line) return targets def list_to_c(l): if isinstance(l, list): children = [list_to_c(c) for c in l] return "{" + ",".join(children) + "}" elif isinstance(l, int): return f"0x{l:02x}" else: assert(false) if args.list_modes: for mode in waveforms["modes"]: print(f"""{mode["mode"]}: {mode_names[mode["mode"]]}""" ) sys.exit(0) tmin = -100 tmax = 1000 if args.temperature_range: tmin, tmax = map(int, args.temperature_range.split(",")) modes = [] mode_filter = list(range(len(waveforms["modes"]))) if args.export_modes: mode_filter = list(map(int, args.export_modes.split(","))) mode_filter = [m for m in mode_filter if any([wm["mode"] == m for wm in waveforms["modes"]])] num_modes = len(mode_filter) temp_intervals = [] for bounds in waveforms["temperature_ranges"]["range_bounds"]: temp_intervals.append(f"{{ .min = {bounds['from']}, .max = {bounds['to']} }}") modes = [] num_ranges = -1 for m_index, mode in enumerate(waveforms["modes"]): if not mode["mode"] in mode_filter: continue ranges = [] for i, r in enumerate(mode["ranges"]): bounds = waveforms["temperature_ranges"]["range_bounds"][i] if bounds["from"] < tmin or bounds["from"] > tmax: continue phases = [] phase_count = len(r["phases"]) prev_phase = None for phase in r["phases"]: phases.append(phase_to_c(phase)) name = f"epd_wp_{args.name}_{mode['mode']}_{r['index']}" phase_times= None if r.get("phase_times"): phase_times = [str(int(t * 10)) for t in r["phase_times"]] print(f"const int {name}_times[{len(phase_times)}] = {{ {','.join(phase_times) } }};") phase_times_str = f"&{name}_times[0]" if phase_times else "NULL" print(f"const uint8_t {name}_data[{phase_count}][16][4] = {list_to_c(phases)};") print(f"const EpdWaveformPhases {name} = {{ .phases = {phase_count}, .phase_times = {phase_times_str}, .luts = (const uint8_t*)&{name}_data[0] }};") ranges.append(name) assert(num_ranges < 0 or num_ranges == len(ranges)) num_ranges = len(ranges) name = f"epd_wm_{args.name}_{mode['mode']}" range_pointers = ','.join(['&' + n for n in ranges]) print(f"const EpdWaveformPhases* {name}_ranges[{len(ranges)}] = {{ {range_pointers} }};") print(f"const EpdWaveformMode {name} = {{ .type = {mode['mode']}, .temp_ranges = {len(ranges)}, .range_data = &{name}_ranges[0] }};"); modes.append(name) mode_pointers = ','.join(['&' + n for n in modes]) range_data = ",".join(temp_intervals) print(f"const EpdWaveformTempInterval {args.name}_intervals[{len(temp_intervals)}] = {{ {range_data} }};"); print(f"const EpdWaveformMode* {args.name}_modes[{num_modes}] = {{ {mode_pointers} }};"); print(f"const EpdWaveform {args.name} = {{ .num_modes = {num_modes}, .num_temp_ranges = {num_ranges}, .mode_data = &{args.name}_modes[0], .temp_intervals = &{args.name}_intervals[0] }};");