Initial commit

This commit is contained in:
jaseg 2021-12-06 18:50:08 +01:00
commit 94633e2bf8
7 changed files with 337 additions and 0 deletions

146
8seg_vcd_render.py Normal file
View file

@ -0,0 +1,146 @@
import os
from os import path
from uuid import uuid4
import copy
from os import path
import sys
from bs4 import BeautifulSoup
import vcdvcd
from flask import Flask, redirect, url_for, abort, send_file, render_template, request, flash, Response
from werkzeug.utils import secure_filename
app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 100 * 1000
app.config.from_envvar('VCD8SEG_SETTINGS')
@app.route('/')
def index():
return render_template('index.html')
@app.route('/show/<uuid:uuid>')
def show(uuid):
uuid = str(uuid)
fp = path.join(app.config['UPLOAD_PATH'], secure_filename(uuid))
if not path.isfile(fp):
abort(404)
return send_file(fp, mimetype='image/svg+xml')
@app.route('/upload', methods=['POST'])
def upload_vcd():
if not (file := request.files.get('file')):
flash('Request is missing file part.')
return redirect(url_for('index'))
if file.filename == '':
flash('No file selected.')
return redirect(url_for('index'))
if path.splitext(file.filename)[1].lower() != '.vcd':
flash('Please upload a .vcd waveform file (not e.g. .v or .vvp)')
return redirect(url_for('index'))
uuid = str(uuid4())
fp = path.join(app.config['UPLOAD_PATH'], secure_filename(uuid))
file.save(fp)
return redirect(url_for('vcd_setup', uuid=uuid))
@app.route('/setup/<uuid:uuid>', methods=['GET', 'POST'])
def vcd_setup(uuid):
uuid = str(uuid)
fp = path.join(app.config['UPLOAD_PATH'], secure_filename(uuid))
if not path.isfile(fp):
abort(404)
with open(fp) as f:
vcd = f.read()
if request.method == 'GET':
default_signal, signal_names = vcd_signal_names(vcd)
return render_template('setup.html', uuid=uuid, signal_names=signal_names, default_signal=default_signal)
else: # request.method == 'POST'
try:
svg = vcd_to_8seg_svg(vcd, request.form['signal'])
except IndexError:
abort(Response(400, 'Signal not found'))
os.remove(path.join(app.config['UPLOAD_PATH'], secure_filename(uuid)))
uuid = str(uuid4())
fp = path.join(app.config['UPLOAD_PATH'], secure_filename(uuid))
with open(fp, 'w') as f:
f.write(svg)
return redirect(url_for('show', uuid=uuid))
def vcd_signal_names(data):
vcd = vcdvcd.VCDVCD(vcd_string=data)
signal_names = list(vcd.references_to_ids.keys())
default_signal = [*[n for n in signal_names if 'segments' in n],
*[n for n in signal_names if 'segs' in n],
*signal_names][0]
return default_signal, signal_names
def vcd_to_8seg_svg(in_vcd, signal=None):
with open(path.join(app.static_folder, '8seg-template.svg')) 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:
raise IndexError('Signal {signal} not found. Available signals: {", ".join(signal_names)}')
# Only use first 10k rows
for i, (time, value) in zip(range(10000), sig.tv):
value = ('0' * int(sig.size) + value)[-int(sig.size):]
yield [int(x) for x in value]
return str(concat_digits(list(parse_vcd(in_vcd, signal))))