RIO working: serial wire tap, conf tuning, four-patch writeup
The RIO cockpit board now runs sustained sessions with button mashing; dropouts self-heal in ~1-3s. Documented in RIO-NOTES.md: - directserial RIO_TAP=<path> (host env): logs every TX/RX byte with host-us + emu-ms timestamps, plus config/RTS/DTR/break lines. This instrument found every root cause below. - Confs: rxburst:16 restored (no-burst reply pacing made the game ACK ~14ms late -> board dropped on the first long analog stream; the old 'rxburst corrupts boot' belief was the then-unpatched PCSPAK crash). priority=highest,highest (unfocused DOSBox was demoted and blew the ACK deadline). - BTL4OPT.EXE patch lineage (in ALPHA_1/, zip left pristine): v2 full DISABLE_AND_DIE NOPs (v1 left the IRQ/RTS-retract prologue live -> first protocol error deafened the driver), v3 TXMAXIDLE 4->32 (kills the button-press ACK-window livelock), v4 analog retry limit 15s->0.5s (dev value was 0.2s; recovery now near-instant). - Board firmware patch plan recorded for the EPROM-dump route. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -29,9 +29,32 @@
|
||||
|
||||
#include "libserial.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
/* This is a serial passthrough class. Its amazingly simple to */
|
||||
/* write now that the serial ports themselves were abstracted out */
|
||||
|
||||
static double tap_now_us() {
|
||||
using namespace std::chrono;
|
||||
return duration<double, std::micro>(
|
||||
steady_clock::now().time_since_epoch()).count();
|
||||
}
|
||||
|
||||
/* One log line per byte on the wire. Host-relative microseconds tell the
|
||||
* real-time story (the RIO's ACK deadline is wall clock); PIC_FullIndex()
|
||||
* (emulated ms) ties each byte to game-side timing. */
|
||||
void CDirectSerial::tapLine(char dir, unsigned val, unsigned err) {
|
||||
if (!tap_fp) return;
|
||||
double us = tap_now_us() - tap_t0_us;
|
||||
if (err)
|
||||
fprintf(tap_fp, "%12.1f %11.3f %c %02X err=%02X\n",
|
||||
us, PIC_FullIndex(), dir, val, err);
|
||||
else
|
||||
fprintf(tap_fp, "%12.1f %11.3f %c %02X\n",
|
||||
us, PIC_FullIndex(), dir, val);
|
||||
fflush(tap_fp);
|
||||
}
|
||||
|
||||
CDirectSerial::CDirectSerial (Bitu id, CommandLine* cmd)
|
||||
:CSerial (id, cmd) {
|
||||
InstallationSuccessful = false;
|
||||
@@ -86,6 +109,22 @@ CDirectSerial::CDirectSerial (Bitu id, CommandLine* cmd)
|
||||
(unsigned)rx_burst);
|
||||
}
|
||||
|
||||
// RIO_TAP=<path> (host env, like the VPX_* vars): append one line per
|
||||
// TX/RX byte. Appends across runs; each open writes a header line.
|
||||
const char *tp = getenv("RIO_TAP");
|
||||
if (tp && tp[0]) {
|
||||
tap_fp = fopen(tp, "a");
|
||||
if (tap_fp) {
|
||||
tap_t0_us = tap_now_us();
|
||||
fprintf(tap_fp, "# COM%d tap open (host-us rel | emu-ms | dir | byte)\n",
|
||||
(int)COMNUMBER);
|
||||
fflush(tap_fp);
|
||||
LOG_MSG("Serial%d: RIO_TAP logging to '%s'", (int)COMNUMBER, tp);
|
||||
} else {
|
||||
LOG_MSG("Serial%d: RIO_TAP cannot open '%s'", (int)COMNUMBER, tp);
|
||||
}
|
||||
}
|
||||
|
||||
CSerial::Init_Registers();
|
||||
InstallationSuccessful = true;
|
||||
rx_state = D_RX_IDLE;
|
||||
@@ -94,6 +133,7 @@ CDirectSerial::CDirectSerial (Bitu id, CommandLine* cmd)
|
||||
|
||||
CDirectSerial::~CDirectSerial () {
|
||||
if(comport) SERIAL_close(comport);
|
||||
if(tap_fp) fclose(tap_fp);
|
||||
// We do not use own events so we don't have to clear them.
|
||||
}
|
||||
|
||||
@@ -293,6 +333,7 @@ void CDirectSerial::handleUpperEvent(uint16_t type) {
|
||||
bool CDirectSerial::doReceive() {
|
||||
int value = SERIAL_getextchar(comport);
|
||||
if(value) {
|
||||
tapLine('R', (unsigned)(value & 0xff), (unsigned)((value >> 8) & 0xff));
|
||||
receiveByteEx((uint8_t)(value&0xff),(uint8_t)((value&0xff00)>>8));
|
||||
return true;
|
||||
}
|
||||
@@ -326,6 +367,12 @@ void CDirectSerial::updatePortConfig (uint16_t divider, uint8_t lcr) {
|
||||
else stopbits = SERIAL_2STOP;
|
||||
} else stopbits = SERIAL_1STOP;
|
||||
|
||||
if (tap_fp) {
|
||||
fprintf(tap_fp, "# %12.1f %11.3f config %u baud %d%c%d\n",
|
||||
tap_now_us() - tap_t0_us, PIC_FullIndex(),
|
||||
(unsigned)baudrate, (int)bytelength, (char)parity, (int)stopbits);
|
||||
fflush(tap_fp);
|
||||
}
|
||||
if(!SERIAL_setCommParameters(comport, (int)baudrate, (char)parity, (char)stopbits, (char)bytelength)) {
|
||||
#if SERIAL_DEBUG
|
||||
log_ser(dbg_aux,"Serial port settings not supported by host." );
|
||||
@@ -346,6 +393,7 @@ void CDirectSerial::updateMSR () {
|
||||
}
|
||||
|
||||
void CDirectSerial::transmitByte (uint8_t val, bool first) {
|
||||
tapLine('T', val, 0);
|
||||
if(!SERIAL_sendchar(comport, (char)val))
|
||||
LOG_MSG("Serial%d: COM port error: write failed!", (int)COMNUMBER);
|
||||
if(first) setEvent(SERIAL_THR_EVENT, bytetime/8);
|
||||
@@ -355,20 +403,41 @@ void CDirectSerial::transmitByte (uint8_t val, bool first) {
|
||||
|
||||
// setBreak(val) switches break on or off
|
||||
void CDirectSerial::setBreak (bool value) {
|
||||
if (tap_fp) {
|
||||
fprintf(tap_fp, "# %12.1f %11.3f break=%d\n",
|
||||
tap_now_us() - tap_t0_us, PIC_FullIndex(), value ? 1 : 0);
|
||||
fflush(tap_fp);
|
||||
}
|
||||
SERIAL_setBREAK(comport,value);
|
||||
}
|
||||
|
||||
// updateModemControlLines(mcr) sets DTR and RTS.
|
||||
// updateModemControlLines(mcr) sets DTR and RTS.
|
||||
void CDirectSerial::setRTSDTR(bool rts, bool dtr) {
|
||||
if (tap_fp) {
|
||||
fprintf(tap_fp, "# %12.1f %11.3f rts=%d dtr=%d\n",
|
||||
tap_now_us() - tap_t0_us, PIC_FullIndex(),
|
||||
rts ? 1 : 0, dtr ? 1 : 0);
|
||||
fflush(tap_fp);
|
||||
}
|
||||
SERIAL_setRTS(comport,rts);
|
||||
SERIAL_setDTR(comport,dtr);
|
||||
}
|
||||
|
||||
void CDirectSerial::setRTS(bool val) {
|
||||
if (tap_fp) {
|
||||
fprintf(tap_fp, "# %12.1f %11.3f rts=%d\n",
|
||||
tap_now_us() - tap_t0_us, PIC_FullIndex(), val ? 1 : 0);
|
||||
fflush(tap_fp);
|
||||
}
|
||||
SERIAL_setRTS(comport,val);
|
||||
}
|
||||
|
||||
void CDirectSerial::setDTR(bool val) {
|
||||
if (tap_fp) {
|
||||
fprintf(tap_fp, "# %12.1f %11.3f dtr=%d\n",
|
||||
tap_now_us() - tap_t0_us, PIC_FullIndex(), val ? 1 : 0);
|
||||
fflush(tap_fp);
|
||||
}
|
||||
SERIAL_setDTR(comport,val);
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,12 @@ private:
|
||||
// sitting in the host buffer. n>1 delivers buffered bytes n times
|
||||
// faster, cutting multi-byte reply latency (RIO analog packets).
|
||||
float rx_burst_div = 1.0f;
|
||||
// RIO_TAP=<path> (host env): wire-level byte log ("<host-us> <emu-ms>
|
||||
// T|R <hex>") to verify whether RIO requests reach the wire and when
|
||||
// replies come back. NULL when disabled.
|
||||
FILE *tap_fp = nullptr;
|
||||
double tap_t0_us = 0.0;
|
||||
void tapLine(char dir, unsigned val, unsigned err);
|
||||
bool doReceive();
|
||||
|
||||
#if SERIAL_DEBUG
|
||||
|
||||
Reference in New Issue
Block a user