vcd-render/vcd_to_8seg_svg.py
2021-12-06 18:50:08 +01:00

82 lines
2.5 KiB
Python

#!/usr/bin/env python3
import copy
from os import path
import sys
import click
from bs4 import BeautifulSoup
import vcdvcd
@click.command()
@click.option('-s', '--signal', default=None)
@click.option('--svg-template', type=click.File('r'), default=(path.dirname(__file__) + '/img/8seg-template.svg'))
@click.argument('in_vcd', type=click.File('r'))
@click.argument('out_svg', type=click.File('w'))
def vcd_to_8seg_svg(in_vcd, out_svg, svg_template, signal):
with svg_template as f:
soup = BeautifulSoup(f.read(), 'xml')
(vb_x, vb_y, vb_w, vb_h) = list(map(int, soup.find('svg')['viewBox'].split()))
display_template = soup.find(id='display').extract()
def generate_digit(segments):
inst = copy.copy(display_template)
for seg, val in zip('abcdefgh', segments):
if val:
tag = inst.find(id=f'seg_{seg}')
tag['style'] = tag['style'].replace('fill:#202040', 'fill:#ff0000')
return inst
def concat_digits(digits):
inst = copy.copy(soup)
svg = inst.find('svg')
x, y = vb_x, vb_y
w, h = 0, 0
for i, segments in enumerate(digits):
digit = generate_digit(segments)
digit['id'] = f'digit{i}'
digit['transform'] = f'translate({x}, {y})'
svg.append(digit)
x += vb_w
w += vb_w
h = vb_h
w_phys = (i+1) * 15 # mm
svg['viewBox'] = f'{vb_x} {vb_y} {w} {h}'
svg['width'] = f'{w_phys}mm'
svg['height'] = f'{15 * (vb_h / vb_w)}mm'
return svg
def parse_vcd(data, signal=None):
vcd = vcdvcd.VCDVCD(vcd_string=data) # vcd? vcd vcd, vcd!
signal_names = vcd.references_to_ids.keys()
if signal is None:
signal = [*[n for n in signal_names if 'segments' in n],
*[n for n in signal_names if 'segs' in n],
*signal_names][0]
try:
sig = vcd[signal]
except IndexError:
print('Signal {signal} not found. Available signals:', file=sys.stderr)
for sig in signal_names:
print(' ', sig, file=sys.stderr)
raise ClickException()
for time, value in sig.tv:
value = ('0' * int(sig.size) + value)[-int(sig.size):]
print(f'@{time}: {signal} = {value}')
yield [int(x) for x in value]
with in_vcd as f_in:
with out_svg as f_out:
f_out.write(str(concat_digits(list(parse_vcd(in_vcd.read(), signal)))))
if __name__ == '__main__':
vcd_to_8seg_svg()