sinclair/next/specnext.cpp: Implemented DMA delay (allows to stop DMA in Continious mode for ISR)
This commit is contained in:
parent
c65da9b69d
commit
fdce3c40fa
@ -184,7 +184,7 @@ void z80dma_device::device_reset()
|
||||
m_timer->reset();
|
||||
|
||||
m_status = 0;
|
||||
m_dma_seq = ~0;
|
||||
m_dma_seq = SEQ_IDLE;
|
||||
m_rdy = 0;
|
||||
m_force_ready = 0;
|
||||
m_wait = 0;
|
||||
@ -298,6 +298,8 @@ void z80dma_device::disable()
|
||||
{
|
||||
set_busrq(CLEAR_LINE);
|
||||
}
|
||||
m_dma_seq = SEQ_IDLE;
|
||||
LOGDMA("IDLE\n");
|
||||
}
|
||||
|
||||
void z80dma_device::update_bao()
|
||||
@ -607,6 +609,7 @@ TIMER_CALLBACK_MEMBER(z80dma_device::clock_w)
|
||||
}
|
||||
break;
|
||||
|
||||
case SEQ_IDLE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -919,6 +922,9 @@ void z80dma_device::bai_w(int state)
|
||||
{
|
||||
m_busrq_ack = state;
|
||||
update_bao();
|
||||
|
||||
if (m_busrq_ack && m_dma_seq == SEQ_IDLE)
|
||||
set_busrq(CLEAR_LINE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -93,7 +93,8 @@ protected:
|
||||
|
||||
enum
|
||||
{
|
||||
SEQ_WAIT_READY = 0,
|
||||
SEQ_IDLE = 0,
|
||||
SEQ_WAIT_READY,
|
||||
SEQ_REQUEST_BUS,
|
||||
SEQ_WAITING_ACK,
|
||||
SEQ_TRANS1_INC_DEC_SOURCE_ADDRESS,
|
||||
|
||||
@ -1523,6 +1523,8 @@ void specnext_state::update_dma_delay()
|
||||
const u16 dma_int_mask = (m_nr_cc_dma_int_en_0_7 << INT_PRIORITY_NMI) | ((m_nr_cc_dma_int_en_0_10 & 1) << INT_PRIORITY_ULA)
|
||||
| (m_nr_cd_dma_int_en_1 << INT_PRIORITY_CTC) | ((m_nr_cc_dma_int_en_0_10 >> 1) << INT_PRIORITY_LINE);
|
||||
m_dma->dma_delay_w((m_nr_c0_int_mode_pulse_0_im2_1 && (dma_int_mask & m_im2_int_status)) ? 1 : 0);
|
||||
if (m_nr_c0_int_mode_pulse_0_im2_1)
|
||||
LOGINTVVV("DMA delay %d (int_status=%04x, int_mask=%04x)\n", (dma_int_mask & m_im2_int_status) ? 1 : 0, m_im2_int_status, dma_int_mask);
|
||||
}
|
||||
|
||||
u8 specnext_state::reg_r(offs_t nr_register)
|
||||
@ -2714,19 +2716,44 @@ void specnext_state::irq_w(int state)
|
||||
{
|
||||
m_maincpu->set_input_line(INPUT_LINE_IRQ0, state);
|
||||
|
||||
const std::array<int, 10> states =
|
||||
{
|
||||
m_im2_line->z80daisy_irq_state(),
|
||||
m_im2_uart0_rx->z80daisy_irq_state(),
|
||||
m_im2_uart1_rx->z80daisy_irq_state(),
|
||||
m_ctc->z80daisy_chanel_irq_state(0),
|
||||
m_ctc->z80daisy_chanel_irq_state(1),
|
||||
m_ctc->z80daisy_chanel_irq_state(2),
|
||||
m_ctc->z80daisy_chanel_irq_state(3),
|
||||
m_im2_ula->z80daisy_irq_state(),
|
||||
m_im2_uart0_tx->z80daisy_irq_state(),
|
||||
m_im2_uart1_tx->z80daisy_irq_state()
|
||||
};
|
||||
|
||||
const std::array<u16, 10> masks =
|
||||
{
|
||||
1 << INT_PRIORITY_LINE,
|
||||
1 << INT_PRIORITY_UART0_RX,
|
||||
1 << INT_PRIORITY_UART1_RX,
|
||||
1 << (INT_PRIORITY_CTC + 0),
|
||||
1 << (INT_PRIORITY_CTC + 1),
|
||||
1 << (INT_PRIORITY_CTC + 2),
|
||||
1 << (INT_PRIORITY_CTC + 3),
|
||||
1 << INT_PRIORITY_ULA,
|
||||
1 << INT_PRIORITY_UART0_TX,
|
||||
1 << INT_PRIORITY_UART1_TX
|
||||
};
|
||||
|
||||
const int tmp = m_im2_int_status;
|
||||
m_im2_int_status &= 1 << INT_PRIORITY_NMI;
|
||||
m_im2_int_status |= ((m_im2_uart0_tx->z80daisy_irq_state() & Z80_DAISY_IEO) != 0) << INT_PRIORITY_UART0_TX;
|
||||
m_im2_int_status |= ((m_im2_uart1_tx->z80daisy_irq_state() & Z80_DAISY_IEO) != 0) << INT_PRIORITY_UART1_TX;
|
||||
m_im2_int_status |= ((m_im2_ula->z80daisy_irq_state() & Z80_DAISY_IEO) != 0) << INT_PRIORITY_ULA;
|
||||
m_im2_int_status |= ((m_ctc->z80daisy_chanel_irq_state(3) & Z80_DAISY_IEO) != 0) << (INT_PRIORITY_CTC + 3);
|
||||
m_im2_int_status |= ((m_ctc->z80daisy_chanel_irq_state(2) & Z80_DAISY_IEO) != 0) << (INT_PRIORITY_CTC + 2);
|
||||
m_im2_int_status |= ((m_ctc->z80daisy_chanel_irq_state(1) & Z80_DAISY_IEO) != 0) << (INT_PRIORITY_CTC + 1);
|
||||
m_im2_int_status |= ((m_ctc->z80daisy_chanel_irq_state(0) & Z80_DAISY_IEO) != 0) << (INT_PRIORITY_CTC + 0);
|
||||
m_im2_int_status |= ((m_im2_uart0_rx->z80daisy_irq_state() & Z80_DAISY_IEO) != 0) << INT_PRIORITY_UART0_RX;
|
||||
m_im2_int_status |= ((m_im2_uart1_rx->z80daisy_irq_state() & Z80_DAISY_IEO) != 0) << INT_PRIORITY_UART1_RX;
|
||||
m_im2_int_status |= ((m_im2_line->z80daisy_irq_state() & Z80_DAISY_IEO) != 0) << INT_PRIORITY_LINE;
|
||||
LOGINTVVV("IRQ%s: %04x -> %04x\n", state ? "+" : "-", tmp, m_im2_int_status);
|
||||
m_im2_int_status = 0;
|
||||
for(int i = 0; i < states.size(); ++i)
|
||||
{
|
||||
m_im2_int_status |= (states[i] & Z80_DAISY_IEO) ? masks[i] : 0;
|
||||
if ((states[i] & Z80_DAISY_INT) && !m_im2_int_status) // only highest priority IRQ
|
||||
m_im2_int_status |= masks[i];
|
||||
}
|
||||
m_im2_int_status |= tmp & (1 << INT_PRIORITY_NMI);
|
||||
LOGINTVVV("IRQs: %s %04x -> %04x\n", state ? "+" : "-", tmp, m_im2_int_status);
|
||||
|
||||
update_dma_delay();
|
||||
}
|
||||
|
||||
@ -42,6 +42,16 @@ specnext_dma_device::specnext_dma_device(const machine_config &mconfig, const ch
|
||||
{
|
||||
}
|
||||
|
||||
void specnext_dma_device::dma_delay_w(bool dma_delay)
|
||||
{
|
||||
if (m_dma_delay && !dma_delay && (m_dma_seq == SEQ_WAIT_READY))
|
||||
{
|
||||
set_busrq(ASSERT_LINE);
|
||||
m_dma_seq = SEQ_WAITING_ACK;
|
||||
}
|
||||
m_dma_delay = dma_delay;
|
||||
}
|
||||
|
||||
void specnext_dma_device::reset_byte_counter()
|
||||
{
|
||||
m_byte_counter = m_dma_mode ? 0 : 1;
|
||||
@ -97,8 +107,8 @@ TIMER_CALLBACK_MEMBER(specnext_dma_device::clock_w)
|
||||
{
|
||||
set_busrq(CLEAR_LINE);
|
||||
m_dma_seq = SEQ_WAIT_READY;
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ public:
|
||||
specnext_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
void dma_mode_w(bool dma_mode) { m_dma_mode = dma_mode; }
|
||||
void dma_delay_w(bool dma_delay) { m_dma_delay = dma_delay; }
|
||||
void dma_delay_w(bool dma_delay);
|
||||
|
||||
virtual void write(u8 data) override;
|
||||
|
||||
|
||||
@ -8,6 +8,10 @@
|
||||
#include "specnext_im2.h"
|
||||
|
||||
|
||||
#define VERBOSE 0
|
||||
#include "logmacro.h"
|
||||
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(SPECNEXT_IM2, specnext_im2_device, "specnext_im2", "Spectrum Next IM2")
|
||||
|
||||
@ -35,17 +39,34 @@ int specnext_im2_device::z80daisy_irq_ack()
|
||||
|
||||
void specnext_im2_device::z80daisy_irq_reti()
|
||||
{
|
||||
m_state = 0;
|
||||
m_irq_cb(CLEAR_LINE);
|
||||
if (m_state & Z80_DAISY_IEO)
|
||||
{
|
||||
m_state &= ~Z80_DAISY_IEO;
|
||||
m_irq_cb((m_state & Z80_DAISY_INT) ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
void specnext_im2_device::irq_w(int state)
|
||||
{
|
||||
if (state != CLEAR_LINE)
|
||||
m_state = Z80_DAISY_INT;
|
||||
if (state == CLEAR_LINE)
|
||||
{
|
||||
m_state = 0;
|
||||
m_irq_cb(CLEAR_LINE);
|
||||
}
|
||||
else if (m_state & Z80_DAISY_IEO)
|
||||
{
|
||||
LOG("IM2: Ignoring IRQ while in IEO\n");
|
||||
}
|
||||
else
|
||||
m_state &= ~Z80_DAISY_INT;
|
||||
m_irq_cb(state);
|
||||
{
|
||||
// FPGA im2_device in S_ISR cannot transition to S_REQ;
|
||||
// don't assert INT while being serviced (IEO set), or
|
||||
// the daisy chain would ACK this device, consuming the
|
||||
// new INT, and a subsequent RETI would clear IEO while
|
||||
// the original ISR still runs.
|
||||
m_state |= Z80_DAISY_INT;
|
||||
m_irq_cb(ASSERT_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user