forked from arti/vt1200
Two faults the 60 fps work exposed, both in the delivery tooling: * `demo.sh --no-load` waited for the terminal to answer ping. A loaded payload owns the LANCE and stops the OS's stack with it, so that gate can never pass once the payload is running -- the recovery path documented for "already jumped" deadlocked for its full 180 s. The gate now runs only when this invocation is going to load the payload. * `rdebug_load.py` used a 5 s socket timeout and no retry, so a readback peek that timed out on a freshly booted OS failed a load whose pokes had already been acknowledged. Timeout is 15 s (--timeout) and the readback retries once before it is believed. Tests: the retry path is pinned with a fake remote that times out on the first peek (one timeout, then the successful pass over every chunk) and one that never answers (it must raise rather than loop). 9 tests in harness/badapple pass.
97 lines
3.9 KiB
Bash
Executable File
97 lines
3.9 KiB
Bash
Executable File
#!/bin/sh
|
|
# Play the streaming demo on a RUNNING terminal: wait for its OS network stack,
|
|
# deliver the payload over rdebug, then send the clip with the host sender.
|
|
#
|
|
# The terminal itself is started separately -- `harness/mame/run.sh net` for the
|
|
# emulator (its default VR319 monitor already gives the real unit's 1280-px /
|
|
# 256-byte framebuffer layout; `VT1200_MONITOR=VR150` reproduces the old derived
|
|
# 1024-px view), or a real VT1200 on the network. This script only talks
|
|
# to it, so one instance serves one demo: the jump hands the payload the
|
|
# remote-debug process and it never returns.
|
|
#
|
|
# demo.sh # committed 30-frame cache
|
|
# demo.sh --tiles /tmp/badapple --frames 3292 --fps 15
|
|
# demo.sh --host 192.168.99.2 --iface vt1200
|
|
# demo.sh --no-load # send only, payload already running
|
|
set -eu
|
|
|
|
HERE=$(cd "$(dirname "$0")" && pwd)
|
|
ROOT=$(cd "$HERE/../.." && pwd)
|
|
|
|
HOST=192.168.99.2
|
|
IFACE=vt1200
|
|
TILES=$ROOT/harness/udpstream/tiles
|
|
FRAMES=200
|
|
FPS=15
|
|
LOAD=1
|
|
SEND=1
|
|
WAIT=180
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--host) HOST=$2; shift 2 ;;
|
|
--iface) IFACE=$2; shift 2 ;;
|
|
--tiles) TILES=$2; shift 2 ;;
|
|
--frames) FRAMES=$2; shift 2 ;;
|
|
--fps) FPS=$2; shift 2 ;;
|
|
--wait) WAIT=$2; shift 2 ;;
|
|
--no-load) LOAD=0; shift ;;
|
|
--no-send) SEND=0; shift ;;
|
|
-h|--help) sed -n '2,20p' "$0"; exit 0 ;;
|
|
*) echo "demo.sh: unknown option $1" >&2; exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
# --- the cache, checked BEFORE anything irreversible ------------------------
|
|
# The jump hands the payload the remote-debug process and it never returns, so
|
|
# a bad --tiles path discovered afterwards leaves the machine needing a restart
|
|
# to try again. Refuse it here instead.
|
|
if [ "$SEND" = 1 ]; then
|
|
for f in dictionary.bin stream.bin; do
|
|
if [ ! -f "$TILES/$f" ]; then
|
|
echo "demo.sh: $TILES has no $f -- that is not a tile cache" >&2
|
|
if ls "$TILES"/[0-9]*.bin > /dev/null 2>&1; then
|
|
echo " it looks like a FRAMES directory (raw 1-bpp frames)." >&2
|
|
echo " build the cache from it first:" >&2
|
|
echo " python3 harness/udpstream/make_tiles.py --clip $TILES --out $TILES-tiles" >&2
|
|
fi
|
|
echo " the committed 30-frame cache is harness/udpstream/tiles" >&2
|
|
exit 2
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# --- readiness: an ICMP reply from the terminal's own stack -----------------
|
|
# Only when this run is going to load the payload. A loaded payload owns the
|
|
# LANCE (and stops the OS's stack with it), so it never answers ICMP: waiting for
|
|
# a ping after the load would deadlock -- which is exactly what --no-load used to
|
|
# do. --no-load therefore skips the gate and trusts the operator.
|
|
if [ "$LOAD" = 1 ]; then
|
|
start=$(date +%s)
|
|
while ! ping -c1 -W1 "$HOST" > /dev/null 2>&1; do
|
|
if [ $(( $(date +%s) - start )) -ge "$WAIT" ]; then
|
|
echo "demo.sh: $HOST did not answer within ${WAIT}s" >&2
|
|
echo " is the terminal booted and on the tap? (harness/mame/run.sh net)" >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
echo "demo.sh: $HOST answers ($(( $(date +%s) - start ))s)"
|
|
else
|
|
echo "demo.sh: --no-load: not waiting for ICMP (a loaded payload owns the LANCE)"
|
|
fi
|
|
|
|
# --- the payload, over the firmware's own remote-debug service --------------
|
|
if [ "$LOAD" = 1 ]; then
|
|
python3 "$HERE/rdebug_load.py" --host "$HOST"
|
|
# The payload takes the LANCE and the remote-debug process with it, so the
|
|
# sender is started once the machine has had time to arm its ring.
|
|
sleep 3
|
|
fi
|
|
|
|
# --- the clip ---------------------------------------------------------------
|
|
if [ "$SEND" = 1 ]; then
|
|
echo "demo.sh: sending $FRAMES frame(s) from $TILES at $FPS fps on $IFACE"
|
|
sudo -n python3 "$ROOT/harness/udpstream/vidsend.py" --iface "$IFACE" \
|
|
--tiles --tiles-dir "$TILES" --frames "$FRAMES" --fps "$FPS"
|
|
fi
|