mirror of
https://git.k-space.ee/arti/vt1200.git
synced 2026-10-30 12:03:54 +02:00
71 lines
1.9 KiB
C++
71 lines
1.9 KiB
C++
#include "vt1200_board.h"
|
|
|
|
bool vt1200_board::is_switch_port(uint32_t addr) const
|
|
{
|
|
// The monitor-selection switch lives in bits 4-6 of window 3's +0xD0
|
|
// register (harness offset 0x0d).
|
|
return addr == (VT1200_WIN3 + VT1200_OFF_SWITCH);
|
|
}
|
|
|
|
uint16_t vt1200_board::read(uint32_t addr)
|
|
{
|
|
auto ov = m_override.find(addr);
|
|
if (ov != m_override.end())
|
|
return ov->second;
|
|
|
|
uint16_t value = m_default;
|
|
auto st = m_store.find(addr);
|
|
if (st != m_store.end())
|
|
value = st->second;
|
|
|
|
// DMA command port: while a command is in flight the port reads back the
|
|
// latched command; once the configured ticks elapse it reads back 0.
|
|
if (m_dma_ticks > 0 && (addr & 0xffff0000) == VT1200_WIN1)
|
|
return (m_dma_left > 0) ? m_dma_cmd : (uint16_t)0x0000;
|
|
|
|
if (m_switch_set && is_switch_port(addr))
|
|
return (uint16_t)((value & 0xff8f) | (m_switch_bits & 0x0070));
|
|
|
|
if (m_handshake && (addr & 0xffff) == VT1200_OFF_STATUS)
|
|
{
|
|
auto busy = m_busy_left.find(addr & 0xffff0000);
|
|
if (busy != m_busy_left.end() && busy->second > 0)
|
|
value |= 0x0001;
|
|
else
|
|
value &= ~0x0001;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
void vt1200_board::write(uint32_t addr, uint16_t data)
|
|
{
|
|
m_store[addr] = data;
|
|
if (m_handshake && (addr & 0xffff) == VT1200_OFF_CMD)
|
|
{
|
|
const uint32_t win = addr & 0xffff0000;
|
|
auto ticks = m_busy_ticks_by_win.find(win);
|
|
m_busy_left[win] = (ticks != m_busy_ticks_by_win.end()) ? ticks->second : 0;
|
|
}
|
|
|
|
// A command written to the DMA command port (WIN1) is latched and, when the
|
|
// DMA model is configured, starts its completion timer.
|
|
if ((addr & 0xffff0000) == VT1200_WIN1)
|
|
{
|
|
m_dma_cmd = data;
|
|
if (m_dma_ticks > 0)
|
|
m_dma_left = m_dma_ticks;
|
|
}
|
|
}
|
|
|
|
void vt1200_board::tick()
|
|
{
|
|
// Advance every window's state machine, not just the one last touched.
|
|
for (auto &entry : m_busy_left)
|
|
if (entry.second > 0)
|
|
entry.second--;
|
|
|
|
// Merge the DMA pair's timer into the same tick.
|
|
if (m_dma_left > 0)
|
|
m_dma_left--;
|
|
}
|