#!/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()