#!/bin/sh
# retroDE_ps2 — Ch330 RUNTIME COMMAND-LIST FEEDER silicon proof (HPS-staged primitive lists).
#
# Streams a normalized combined-TAZ triangle list into the feeder's staging RAM over the HPS
# bridge, then pulses GO to retrigger the renderer — no RBF rebuild, no reset. Proves repeatable
# runtime command-list ingestion by cycling list A -> B -> A -> B (ends on B):
#   list A : 4 textured tris in tile t0 (top-left)      -> blue triangle top-left
#   list B : 4 textured tris in tile t15 (bottom-right) -> blue triangle bottom-right
# Ending on B means the final screen (bottom-right) differs from the power-up screen (top-left),
# so the runtime swap is unambiguous rather than netting back to where it started.
# The board powers up drawing list A already (FEEDER_STG_INIT_FILE bitstream-inits the staging
# RAM); this script re-stages it from the HPS to prove the *runtime* path, not just power-up.
#
# REQUIRES the Ch330 feeder bitstream:  ./scripts/select_de25_profile.sh feeder  (then re-fit).
#
# Register map (bridge BASE 0x40000000):
#   0x0D8  R: bit0 = feeder ready (FSM in C_READY)      W: staging word address (set 0 before a list)
#   0x0DC  W: staging word LOW 32 bits
#   0x0E4  W: staging word HIGH 32 -> commits {hi,lo} to staging[addr], auto-increments addr
#          R: records_emitted (primitives the last list pushed; expect 4)
#   0x0E8  W: bit0 = GO (retrigger)                     R: fifo_wait_cycles (backpressure stalls)
#
# Acceptance: after each GO, records == 4 and the HDMI image matches the staged list (A/B/A/B).
# Watch the HDMI output change top-left -> bottom-right -> top-left -> bottom-right as lists are staged.

set -u
BASE="${PS2_BRIDGE_BASE:-0x40000000}"
DEVMEM="${DEVMEM:-busybox devmem}"

OFF_STATUS=0x0D8   # R ready / W staging addr
OFF_LO=0x0DC       # W low 32
OFF_HI=0x0E4       # W high 32 (commit+inc) / R records
OFF_GO=0x0E8       # W go / R waits

w() { $DEVMEM $(printf "0x%X" $(( BASE + $1 ))) w "$2" >/dev/null; }
r() { $DEVMEM $(printf "0x%X" $(( BASE + $1 ))) w; }

# 43 staging words each (count + FRAME/ALPHA/TEST/ZBUF/TEX0/PRIM + 4 tris x 9 vertex words).
# A = tile t0 (top-left), B = tile t15 (col3,row3 = bottom-right, diagonal opposite of t0) —
# identical lists except the XYZ2 vertex coordinates, so the triangle jumps corner-to-corner.
LIST_A="0000000000000004 0000000000010000 0000000000000044 0000000000050000 0000000000000002 0000000888004040 0000000000000053 00000000ff000000 0000000000000000 0000500000100010 00000000ff000000 0000000000000030 00005000001000e0 00000000ff000000 00000000000c0000 0000500000e00010 00000000ff000000 0000000000000000 0000510000100010 00000000ff000000 0000000000000030 00005100001000e0 00000000ff000000 00000000000c0000 0000510000e00010 00000000ff000000 0000000000000000 0000520000100010 00000000ff000000 0000000000000030 00005200001000e0 00000000ff000000 00000000000c0000 0000520000e00010 00000000ff000000 0000000000000000 0000530000100010 00000000ff000000 0000000000000030 00005300001000e0 00000000ff000000 00000000000c0000 0000530000e00010"
LIST_B="0000000000000004 0000000000010000 0000000000000044 0000000000050000 0000000000000002 0000000888004040 0000000000000053 00000000ff000000 0000000000000000 0000500003100310 00000000ff000000 0000000000000030 00005000031003e0 00000000ff000000 00000000000c0000 0000500003e00310 00000000ff000000 0000000000000000 0000510003100310 00000000ff000000 0000000000000030 00005100031003e0 00000000ff000000 00000000000c0000 0000510003e00310 00000000ff000000 0000000000000000 0000520003100310 00000000ff000000 0000000000000030 00005200031003e0 00000000ff000000 00000000000c0000 0000520003e00310 00000000ff000000 0000000000000000 0000530003100310 00000000ff000000 0000000000000030 00005300031003e0 00000000ff000000 00000000000c0000 0000530003e00310"

wait_ready() { # poll 0x0D8 bit0 until ready, or give up after ~3 s
    i=0
    while [ $i -lt 300 ]; do
        st=$(r $OFF_STATUS)
        [ $(( st & 1 )) -eq 1 ] && return 0
        i=$(( i + 1 )); sleep 0.01 2>/dev/null || true
    done
    echo "  !! feeder never reported ready (0x0D8 bit0) — is this the feeder bitstream?"
    return 1
}

stage_and_go() { # $1 = label, $2 = whitespace-separated 16-hex-digit words
    label="$1"; words="$2"
    echo "[$label] waiting for feeder ready ..."
    wait_ready || return 1
    echo "[$label] writing the whole list, then GO ..."
    w $OFF_STATUS 0x0          # staging address = 0 (auto-increments per HI write)
    n=0
    for word in $words; do
        lo=$(printf '%s' "$word" | cut -c9-16)
        hi=$(printf '%s' "$word" | cut -c1-8)
        w $OFF_LO 0x$lo
        w $OFF_HI 0x$hi        # commit {hi,lo} -> staging[n], addr -> n+1
        n=$(( n + 1 ))
    done
    badr=$(r $OFF_LO)          # 0x0DC read = bridge staging address — must equal n (all words committed)
    echo "[$label] wrote $n words; bridge staging addr now=$(( badr )) (expect $n)"
    [ $(( badr )) -eq $n ] || echo "  !! bridge addr != $n — not all commits landed"
    wait_ready || return 1     # FSM still C_READY (staging writes don't change state); confirm
    w $OFF_GO 0x1              # retrigger
    wait_ready || return 1     # render + grid drain -> back to C_READY
    rec=$(r $OFF_HI); wts=$(r $OFF_GO)
    echo "[$label] staged $n words -> records=$(( rec )) (expect 4)  fifo_wait_cycles=$(( wts ))"
    [ $(( rec )) -eq 4 ] || { echo "  !! records != 4 — list not fully emitted"; return 1; }
    echo "[$label] OK — look at HDMI."
    sleep 2 2>/dev/null || true
}

echo "=== Ch330 runtime command-list feeder — A -> B -> A -> B (no RBF rebuild, no reset) ==="
stage_and_go "A (t0 top-left)" "$LIST_A" || exit 1
stage_and_go "B (t15 bottom-right)" "$LIST_B" || exit 1
stage_and_go "A (t0 top-left)"  "$LIST_A" || exit 1
stage_and_go "B (t15 bottom-right)" "$LIST_B" || exit 1
echo "=== done — ENDS ON B: triangle should now be at the BOTTOM-RIGHT (t15), NOT top-left."
echo "    If it's at bottom-right, the runtime swap works end-to-end. If still top-left, tell me the"
echo "    'bridge staging addr now=' lines so I can see whether all 43 words committed. ==="
