mirror of
https://github.com/MCKero6423/uv-k5-v3-emulator.git
synced 2026-10-02 03:15:36 +00:00
QMP takes a single client and the web UI holds it for its whole lifetime, so this is the normal outcome while the page is open rather than a broken emulator. Verified against a private instance: 128x64, 1819 pixels lit, 64 rows of ASCII.
72 lines
3.2 KiB
Python
72 lines
3.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Render the display controller's own memory, for any firmware, without a browser.
|
|
|
|
The web page already does this; this is the same thing from a shell, which is what you
|
|
want when the question is "does *this* build render correctly" and the answer has to be
|
|
compared rather than glanced at. It prints ASCII at one character per LCD pixel, so two
|
|
builds can be diffed, and can also write a scaled PNG.
|
|
|
|
tools/panel_dump.py --qmp 127.0.0.1:4444 # ASCII, as the panel shows it
|
|
tools/panel_dump.py --qmp 127.0.0.1:4444 --mapping mirror-cols
|
|
tools/panel_dump.py --qmp 127.0.0.1:4444 --png work/screen.png
|
|
|
|
The --mapping option exists because which mapping is right is a property of the *driver*,
|
|
not of the controller. Two builds can program identical panel registers -- 0xA1 segment
|
|
reverse, 0xC0, 0xA6 -- and still arrive in different orders, because one compensates in
|
|
software and the other does not. Measured on the 5.9.0.CN build against its own
|
|
framebuffer: 8188 of 8192 pixels agree with the panel data untouched, 6954 with the
|
|
columns mirrored.
|
|
"""
|
|
import argparse
|
|
import sys
|
|
|
|
import uvk5_lcd
|
|
|
|
|
|
def main(argv=None):
|
|
ap = argparse.ArgumentParser(description=__doc__,
|
|
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
ap.add_argument("--qmp", default="127.0.0.1:4444",
|
|
help="the emulator's QMP endpoint (host:port or unix:path)")
|
|
ap.add_argument("--mapping", default="identity",
|
|
choices=["identity", "mirror-cols", "mirror-rows", "both"])
|
|
ap.add_argument("--png", help="write a scaled PNG here instead of ASCII")
|
|
ap.add_argument("--scale", type=int, default=4)
|
|
args = ap.parse_args(argv)
|
|
|
|
from uvk5_qmp import QmpClient
|
|
# The frame addresses are unused on this path: the controller has its own memory.
|
|
try:
|
|
client = QmpClient(args.qmp, timeout=20)
|
|
except Exception as exc:
|
|
# QMP takes one client, and the web UI holds it for its whole lifetime -- so this
|
|
# is the normal outcome while the page is open, not a broken emulator.
|
|
print('cannot reach QMP at %s: %s' % (args.qmp, str(exc).splitlines()[0]), file=sys.stderr)
|
|
print('if the web UI is running it is holding the one QMP client; stop it, or use',
|
|
file=sys.stderr)
|
|
print('--qmp with the endpoint of an emulator started by tools/run.sh instead.',
|
|
file=sys.stderr)
|
|
return 2
|
|
grab = uvk5_lcd.FrameGrabber(client, 0, 0)
|
|
pixels = grab.panel_pixels()
|
|
if args.mapping in ("mirror-cols", "both"):
|
|
pixels = [list(reversed(row)) for row in pixels]
|
|
if args.mapping in ("mirror-rows", "both"):
|
|
pixels = list(reversed(pixels))
|
|
|
|
if args.png:
|
|
with open(args.png, "wb") as fh:
|
|
fh.write(uvk5_lcd.encode_png(pixels, args.scale))
|
|
print("wrote %s (%d x %d)" % (args.png, len(pixels[0]), len(pixels)))
|
|
return 0
|
|
|
|
print("panel %d x %d, %d pixels lit, mapping %s"
|
|
% (len(pixels[0]), len(pixels), sum(sum(r) for r in pixels), args.mapping))
|
|
for row in pixels:
|
|
print("".join("#" if value else "." for value in row))
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|