Tasmota/lib/libesp32_epdiy/scripts/waveform_hdrgen.py

124 lines
4.0 KiB
Python
Executable File

#!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] }};");