Files
vt1200/harness/mame/test_vt1200_board.cpp
T

139 lines
4.9 KiB
C++

// Standalone unit tests for the VT1200 board register model.
// g++ -std=c++17 -o /tmp/t vt1200_board.cpp test_vt1200_board.cpp && /tmp/t
#include "vt1200_board.h"
#include <cassert>
#include <cstdio>
static int failures = 0;
#define CHECK(cond) do { if (!(cond)) { \
std::printf("FAIL %s:%d %s\n", __FILE__, __LINE__, #cond); failures++; } } while (0)
static void test_default_read(void)
{
vt1200_board b;
b.set_default(0x0000);
CHECK(b.read(VT1200_WIN2 + VT1200_OFF_STATUS) == 0x0000);
}
static void test_override_read(void)
{
vt1200_board b;
b.set_override(VT1200_WIN2 + VT1200_OFF_STATUS, 0x00b7);
CHECK(b.read(VT1200_WIN2 + VT1200_OFF_STATUS) == 0x00b7);
}
static void test_monitor_switch_is_mixed_with_latches(void)
{
vt1200_board b;
b.set_monitor_switch(7); // position 7 -> bits 4-6 = 0x70
b.write(VT1200_WIN3 + VT1200_OFF_SWITCH, 0x0001); // output latch writes bit 0
const uint16_t v = b.read(VT1200_WIN3 + VT1200_OFF_SWITCH);
CHECK((v & 0x0070) == 0x0070); // switch bits read back as input
CHECK((v & 0x0001) == 0x0001); // output bits read back as latched
}
static void test_busy_bit_arms_on_write_and_clears(void)
{
vt1200_board b;
b.set_model_handshake(true);
b.set_busy_ticks(2);
const uint32_t status = VT1200_WIN2 + VT1200_OFF_STATUS;
const uint32_t cmd = VT1200_WIN2 + VT1200_OFF_CMD;
CHECK((b.read(status) & 0x0001) == 0x0000); // idle
b.write(cmd, 0x00ca); // command arms it
CHECK((b.read(status) & 0x0001) == 0x0001); // busy
b.tick();
CHECK((b.read(status) & 0x0001) == 0x0001); // still busy
b.tick();
CHECK((b.read(status) & 0x0001) == 0x0000); // done
}
static void test_windows_are_independent(void)
{
vt1200_board b;
b.set_model_handshake(true);
b.set_window_busy_ticks(VT1200_WIN2, 1);
b.set_window_busy_ticks(VT1200_WIN3, 3);
b.write(VT1200_WIN2 + VT1200_OFF_CMD, 0x0001);
b.write(VT1200_WIN3 + VT1200_OFF_CMD, 0x0001);
CHECK((b.read(VT1200_WIN2 + VT1200_OFF_STATUS) & 1) == 1);
CHECK((b.read(VT1200_WIN3 + VT1200_OFF_STATUS) & 1) == 1);
b.tick();
CHECK((b.read(VT1200_WIN2 + VT1200_OFF_STATUS) & 1) == 0); // WIN2 finished
CHECK((b.read(VT1200_WIN3 + VT1200_OFF_STATUS) & 1) == 1); // WIN3 still busy
}
static void test_monitor_switch_accepts_raw_bits_or_position(void)
{
vt1200_board raw;
raw.set_monitor_switch(0x70); // raw register bits
raw.write(VT1200_WIN3 + VT1200_OFF_SWITCH, 0x0001);
CHECK((raw.read(VT1200_WIN3 + VT1200_OFF_SWITCH) & 0x0070) == 0x0070);
vt1200_board pos;
pos.set_monitor_switch(7); // position 7
pos.write(VT1200_WIN3 + VT1200_OFF_SWITCH, 0x0001);
CHECK((pos.read(VT1200_WIN3 + VT1200_OFF_SWITCH) & 0x0070) == 0x0070);
}
static void test_switch_mix_only_when_configured(void)
{
vt1200_board b; // no set_monitor_switch call
b.write(VT1200_WIN3 + VT1200_OFF_SWITCH, 0x0070);
CHECK(b.read(VT1200_WIN3 + VT1200_OFF_SWITCH) == 0x0070); // returned verbatim
}
static void test_dma_pair_command_completes(void)
{
vt1200_board b;
b.set_model_handshake(true);
b.set_dma_ticks(2);
b.write(VT1200_WIN0, 0x0000); // data port first (as the firmware does)
b.write(VT1200_WIN1, 0x0001); // then a command
CHECK(b.read(VT1200_WIN1) == 0x0001); // accepted
b.tick(); b.tick();
CHECK(b.read(VT1200_WIN1) == 0x0000); // completed
}
// The two timers the sweep tunes (window busy and DMA completion) must advance
// on the same tick(), or a later slower timer would silently stretch the other.
static void test_one_tick_advances_window_and_dma_timers(void)
{
vt1200_board b;
b.set_model_handshake(true);
b.set_window_busy_ticks(VT1200_WIN2, 2);
b.set_dma_ticks(2);
b.write(VT1200_WIN2 + VT1200_OFF_CMD, 0x0001); // arms WIN2's busy bit
b.write(VT1200_WIN0, 0x0000); // data port first
b.write(VT1200_WIN1, 0x0042); // then a DMA command
b.tick(); // one frame: both advance
CHECK((b.read(VT1200_WIN2 + VT1200_OFF_STATUS) & 1) == 1);
CHECK(b.read(VT1200_WIN1) == 0x0042);
b.tick();
CHECK((b.read(VT1200_WIN2 + VT1200_OFF_STATUS) & 1) == 0);
CHECK(b.read(VT1200_WIN1) == 0x0000);
}
int main(void)
{
test_default_read();
test_override_read();
test_monitor_switch_is_mixed_with_latches();
test_busy_bit_arms_on_write_and_clears();
test_windows_are_independent();
test_monitor_switch_accepts_raw_bits_or_position();
test_switch_mix_only_when_configured();
test_dma_pair_command_completes();
test_one_tick_advances_window_and_dma_timers();
std::printf(failures ? "%d FAILURE(S)\n" : "all board tests passed\n", failures);
return failures ? 1 : 0;
}