mirror of
https://github.com/holub/mame
synced 2025-10-06 17:08:28 +03:00
commit
4d9ab25ec8
@ -1,5 +1,4 @@
|
|||||||
// license:BSD-3-Clause
|
// license:BSD-3-Clause copyright-holders: Joakim Larsson Edstrom
|
||||||
// copyright-holders: Joakim Larsson Edstrom
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
|
||||||
Z80-SCC Serial Communications Controller emulation
|
Z80-SCC Serial Communications Controller emulation
|
||||||
@ -153,8 +152,8 @@ z80scc_device::z80scc_device(const machine_config &mconfig, device_type type, co
|
|||||||
m_out_txdrqa_cb(*this),
|
m_out_txdrqa_cb(*this),
|
||||||
m_out_rxdrqb_cb(*this),
|
m_out_rxdrqb_cb(*this),
|
||||||
m_out_txdrqb_cb(*this),
|
m_out_txdrqb_cb(*this),
|
||||||
m_variant(variant)
|
m_variant(variant),
|
||||||
{
|
m_wr0_ptrbits(0){
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
m_int_state[i] = 0;
|
m_int_state[i] = 0;
|
||||||
}
|
}
|
||||||
@ -247,6 +246,8 @@ void z80scc_device::device_start()
|
|||||||
|
|
||||||
// state saving
|
// state saving
|
||||||
save_item(NAME(m_int_state));
|
save_item(NAME(m_int_state));
|
||||||
|
|
||||||
|
LOG((" - SCC variant %02x\n", m_variant));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -276,9 +277,9 @@ int z80scc_device::z80daisy_irq_state()
|
|||||||
int state = 0;
|
int state = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
LOG(("Z80SCC \"%s\" : Interrupt State A:%d%d%d%d B:%d%d%d%d\n", tag(),
|
LOG(("%s %s A:%d%d%d B:%d%d%d ",FUNCNAME, tag(),
|
||||||
m_int_state[0], m_int_state[1], m_int_state[2], m_int_state[3],
|
m_int_state[0], m_int_state[1], m_int_state[2],
|
||||||
m_int_state[4], m_int_state[5], m_int_state[6], m_int_state[7]));
|
m_int_state[3], m_int_state[4], m_int_state[5]));
|
||||||
|
|
||||||
// loop over all interrupt sources
|
// loop over all interrupt sources
|
||||||
for (i = 0; i < 6; i++)
|
for (i = 0; i < 6; i++)
|
||||||
@ -292,7 +293,7 @@ int z80scc_device::z80daisy_irq_state()
|
|||||||
state |= m_int_state[i];
|
state |= m_int_state[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(("Z80SCC \"%s\" : Interrupt State %u\n", tag(), state));
|
LOG(("Interrupt State %u\n", state));
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
@ -306,7 +307,7 @@ int z80scc_device::z80daisy_irq_ack()
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
LOG(("Z80SCC \"%s\" Interrupt Acknowledge\n", tag()));
|
LOG(("%s %s - needs fixing for SCC\n",FUNCNAME, tag()));
|
||||||
|
|
||||||
// loop over all interrupt sources
|
// loop over all interrupt sources
|
||||||
for (i = 0; i < 6; i++)
|
for (i = 0; i < 6; i++)
|
||||||
@ -316,10 +317,10 @@ int z80scc_device::z80daisy_irq_ack()
|
|||||||
{
|
{
|
||||||
// clear interrupt, switch to the IEO state, and update the IRQs
|
// clear interrupt, switch to the IEO state, and update the IRQs
|
||||||
m_int_state[i] = Z80_DAISY_IEO;
|
m_int_state[i] = Z80_DAISY_IEO;
|
||||||
m_chanA->m_rr0 &= ~z80scc_channel::RR0_INTERRUPT_PENDING;
|
//m_chanA->m_rr0 &= ~z80scc_channel::RR0_INTERRUPT_PENDING;
|
||||||
check_interrupts();
|
check_interrupts();
|
||||||
|
|
||||||
LOG(("Z80SCC \"%s\" : Interrupt Acknowledge Vector %02x\n", tag(), m_chanB->m_rr2));
|
//LOG(("%s %s \n",FUNCNAME, tag(), m_chanB->m_rr2));
|
||||||
|
|
||||||
return m_chanB->m_rr2;
|
return m_chanB->m_rr2;
|
||||||
}
|
}
|
||||||
@ -339,7 +340,7 @@ void z80scc_device::z80daisy_irq_reti()
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
LOG(("Z80SCC \"%s\" Return from Interrupt\n", tag()));
|
LOG(("%s %s \n",FUNCNAME, tag()));
|
||||||
|
|
||||||
// loop over all interrupt sources
|
// loop over all interrupt sources
|
||||||
for (i = 0; i < 6; i++)
|
for (i = 0; i < 6; i++)
|
||||||
@ -365,7 +366,7 @@ void z80scc_device::z80daisy_irq_reti()
|
|||||||
void z80scc_device::check_interrupts()
|
void z80scc_device::check_interrupts()
|
||||||
{
|
{
|
||||||
int state = (z80daisy_irq_state() & Z80_DAISY_INT) ? ASSERT_LINE : CLEAR_LINE;
|
int state = (z80daisy_irq_state() & Z80_DAISY_INT) ? ASSERT_LINE : CLEAR_LINE;
|
||||||
LOG(("Z80SCC \"%s\" : %s() state = %d\n", m_owner->tag(), __func__, state));
|
LOG(("%s %s \n",FUNCNAME, tag()));
|
||||||
m_out_int_cb(state);
|
m_out_int_cb(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,7 +377,8 @@ void z80scc_device::check_interrupts()
|
|||||||
|
|
||||||
void z80scc_device::reset_interrupts()
|
void z80scc_device::reset_interrupts()
|
||||||
{
|
{
|
||||||
// reset internal interrupi sources
|
LOG(("%s %s \n",FUNCNAME, tag()));
|
||||||
|
// reset internal interrupt sources
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
m_int_state[i] = 0;
|
m_int_state[i] = 0;
|
||||||
@ -428,6 +430,8 @@ void z80scc_device::trigger_interrupt(int index, int state)
|
|||||||
|
|
||||||
int prio_level = 0;
|
int prio_level = 0;
|
||||||
|
|
||||||
|
LOG(("%s %s:%c %d \n",FUNCNAME, tag(), 'A' + index, state));
|
||||||
|
|
||||||
/* The Master Interrupt Enable (MIE) bit, WR9 D3, must be set to enable the SCC to generate interrupts.*/
|
/* The Master Interrupt Enable (MIE) bit, WR9 D3, must be set to enable the SCC to generate interrupts.*/
|
||||||
if (!(m_chanA->m_wr9 & z80scc_channel::WR9_BIT_MIE))
|
if (!(m_chanA->m_wr9 & z80scc_channel::WR9_BIT_MIE))
|
||||||
{
|
{
|
||||||
@ -480,7 +484,7 @@ void z80scc_device::trigger_interrupt(int index, int state)
|
|||||||
vector = modify_vector(vector, index, source);
|
vector = modify_vector(vector, index, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : Interrupt Request %u\n", tag(), 'A' + index, state));
|
//LOG(("Z80SCC \"%s\": %c : Interrupt Request %u\n", tag(), 'A' + index, state));
|
||||||
|
|
||||||
// update vector register // TODO: What if interrupts are nested? May we loose the modified vector or even get the wrong one?
|
// update vector register // TODO: What if interrupts are nested? May we loose the modified vector or even get the wrong one?
|
||||||
m_chanB->m_wr2 = vector;
|
m_chanB->m_wr2 = vector;
|
||||||
@ -602,6 +606,7 @@ WRITE8_MEMBER( z80scc_device::ba_cd_w )
|
|||||||
}
|
}
|
||||||
|
|
||||||
LOG(("z80scc_device::ba_cd_w ba:%02x cd:%02x\n", ba, cd));
|
LOG(("z80scc_device::ba_cd_w ba:%02x cd:%02x\n", ba, cd));
|
||||||
|
|
||||||
if (cd)
|
if (cd)
|
||||||
channel->control_write(data);
|
channel->control_write(data);
|
||||||
else
|
else
|
||||||
@ -617,14 +622,29 @@ WRITE8_MEMBER( z80scc_device::ba_cd_w )
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
z80scc_channel::z80scc_channel(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
z80scc_channel::z80scc_channel(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||||
: z80sio_channel( mconfig, tag, owner, clock)
|
: device_t(mconfig, Z80SCC_CHANNEL, "Z80 SCC channel", tag, owner, clock, "z80scc_channel", __FILE__),
|
||||||
|
device_serial_interface(mconfig, *this),
|
||||||
|
m_rx_error(0),
|
||||||
|
m_rx_clock(0),
|
||||||
|
m_rx_first(0),
|
||||||
|
m_rx_break(0),
|
||||||
|
m_rx_rr0_latch(0),
|
||||||
|
m_rxd(0),
|
||||||
|
m_cts(0),
|
||||||
|
m_dcd(0),
|
||||||
|
m_tx_data(0),
|
||||||
|
m_tx_clock(0),
|
||||||
|
m_dtr(0),
|
||||||
|
m_rts(0),
|
||||||
|
m_sync(0)
|
||||||
{
|
{
|
||||||
// Reset all SCC specific registers; z80sio_channel:: manages the base registers
|
LOG(("%s\n",FUNCNAME));
|
||||||
m_rr0 = m_rr1 = m_rr2 =
|
|
||||||
m_rr3 = m_rr4 = m_rr5 = m_rr6 = m_rr7 = m_rr8 = m_rr9 =
|
// Reset all registers
|
||||||
m_rr10 = m_rr11 = m_rr12 = m_rr13 = m_rr14 = m_rr15 = 0;
|
m_rr0 = m_rr1 = m_rr2 = m_rr3 = m_rr4 = m_rr5 = m_rr6 = m_rr7 = m_rr8
|
||||||
m_wr0 = m_wr1 = m_wr2 = m_wr3 = m_wr4 = m_wr5 = m_wr6 = m_wr7 =
|
= m_rr9 = m_rr10 = m_rr11 = m_rr12 = m_rr13 = m_rr14 = m_rr15 = 0;
|
||||||
m_wr8 = m_wr9 = m_wr10 = m_wr11 = m_wr12 = m_wr13 = m_wr14 = m_wr15 = 0;
|
m_wr0 = m_wr1 = m_wr2 = m_wr3 = m_wr4 = m_wr5 = m_wr6 = m_wr7 = m_wr8
|
||||||
|
= m_wr9 = m_wr10 = m_wr11 = m_wr12 = m_wr13 = m_wr14 = m_wr15 = 0;
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) // TODO adapt to SCC fifos
|
for (int i = 0; i < 3; i++) // TODO adapt to SCC fifos
|
||||||
{
|
{
|
||||||
@ -640,17 +660,16 @@ z80scc_channel::z80scc_channel(const machine_config &mconfig, const char *tag, d
|
|||||||
|
|
||||||
void z80scc_channel::device_start()
|
void z80scc_channel::device_start()
|
||||||
{
|
{
|
||||||
m_uart = downcast<z80scc_device *>(owner());
|
|
||||||
LOG(("%s\n", FUNCNAME));
|
LOG(("%s\n", FUNCNAME));
|
||||||
|
m_uart = downcast<z80scc_device *>(owner());
|
||||||
m_index = m_uart->get_channel_index(this);
|
m_index = m_uart->get_channel_index(this);
|
||||||
m_ph = 0;
|
|
||||||
m_variant = ((z80scc_device *)m_owner)->m_variant;
|
|
||||||
|
|
||||||
m_rx_fifo_sz = (m_variant & SET_ESCC) ? 8 : 3;
|
m_uart->m_wr0_ptrbits = 0;
|
||||||
|
|
||||||
|
m_rx_fifo_sz = (m_uart->m_variant & SET_ESCC) ? 8 : 3;
|
||||||
m_rx_fifo_wp = m_rx_fifo_rp = 0;
|
m_rx_fifo_wp = m_rx_fifo_rp = 0;
|
||||||
|
|
||||||
// state saving
|
// state saving
|
||||||
// m_rr0-m_rr2 is handled by the z80sio_channel driver, our base class
|
|
||||||
save_item(NAME(m_rr0));
|
save_item(NAME(m_rr0));
|
||||||
save_item(NAME(m_rr1));
|
save_item(NAME(m_rr1));
|
||||||
save_item(NAME(m_rr2));
|
save_item(NAME(m_rr2));
|
||||||
@ -667,7 +686,6 @@ void z80scc_channel::device_start()
|
|||||||
save_item(NAME(m_rr13));
|
save_item(NAME(m_rr13));
|
||||||
save_item(NAME(m_rr14));
|
save_item(NAME(m_rr14));
|
||||||
save_item(NAME(m_rr15));
|
save_item(NAME(m_rr15));
|
||||||
// m_wr0-m_wr7 is handled by the z80sio_channel driver, our base class
|
|
||||||
save_item(NAME(m_wr0));
|
save_item(NAME(m_wr0));
|
||||||
save_item(NAME(m_wr1));
|
save_item(NAME(m_wr1));
|
||||||
save_item(NAME(m_wr2));
|
save_item(NAME(m_wr2));
|
||||||
@ -701,7 +719,7 @@ void z80scc_channel::device_start()
|
|||||||
save_item(NAME(m_dtr));
|
save_item(NAME(m_dtr));
|
||||||
save_item(NAME(m_rts));
|
save_item(NAME(m_rts));
|
||||||
save_item(NAME(m_sync));
|
save_item(NAME(m_sync));
|
||||||
save_item(NAME(m_ph));
|
|
||||||
device_serial_interface::register_save_state(machine().save(), this);
|
device_serial_interface::register_save_state(machine().save(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -712,7 +730,7 @@ void z80scc_channel::device_start()
|
|||||||
|
|
||||||
void z80scc_channel::device_reset()
|
void z80scc_channel::device_reset()
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s\n", m_owner->tag(), 'A' + m_index, FUNCNAME));
|
LOG(("%s\n", FUNCNAME));
|
||||||
|
|
||||||
// Reset RS232 emulation
|
// Reset RS232 emulation
|
||||||
receive_register_reset();
|
receive_register_reset();
|
||||||
@ -724,7 +742,7 @@ void z80scc_channel::device_reset()
|
|||||||
m_wr3 &= 0x01;
|
m_wr3 &= 0x01;
|
||||||
m_wr4 |= 0x04;
|
m_wr4 |= 0x04;
|
||||||
m_wr5 &= 0x61;
|
m_wr5 &= 0x61;
|
||||||
if (m_variant & (z80scc_device::TYPE_SCC85C30 | SET_ESCC))
|
if (m_uart->m_variant & (z80scc_device::TYPE_SCC85C30 | SET_ESCC))
|
||||||
m_wr7 = 0x20;
|
m_wr7 = 0x20;
|
||||||
m_wr9 &= 0xdf; // WR9 has a different hard reset value
|
m_wr9 &= 0xdf; // WR9 has a different hard reset value
|
||||||
m_wr10 &= 0x60; // WR10 has a different hard reset value
|
m_wr10 &= 0x60; // WR10 has a different hard reset value
|
||||||
@ -739,7 +757,10 @@ void z80scc_channel::device_reset()
|
|||||||
m_rr3 = 0x00;
|
m_rr3 = 0x00;
|
||||||
m_rr10 &= 0x40;
|
m_rr10 &= 0x40;
|
||||||
|
|
||||||
#if 0 // old reset code
|
#if 1 // old reset code
|
||||||
|
// disable receiver
|
||||||
|
m_wr3 &= ~WR3_RX_ENABLE;
|
||||||
|
|
||||||
// disable transmitter
|
// disable transmitter
|
||||||
m_wr5 &= ~WR5_TX_ENABLE;
|
m_wr5 &= ~WR5_TX_ENABLE;
|
||||||
m_rr0 |= RR0_TX_BUFFER_EMPTY;
|
m_rr0 |= RR0_TX_BUFFER_EMPTY;
|
||||||
@ -866,14 +887,15 @@ void z80scc_channel::rcv_callback()
|
|||||||
{
|
{
|
||||||
if (m_wr3 & WR3_RX_ENABLE)
|
if (m_wr3 & WR3_RX_ENABLE)
|
||||||
{
|
{
|
||||||
LOG(("%" I64FMT "d %s() \"%s \"Channel %c Received Data Bit %d\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_rxd));
|
|
||||||
receive_register_update_bit(m_rxd);
|
receive_register_update_bit(m_rxd);
|
||||||
}
|
}
|
||||||
|
#if 1
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG(("%" I64FMT "d %s() \"%s \"Channel %c Received Data Bit but receiver is disabled\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index));
|
LOG(("%" I64FMT "d %s() \"%s \"Channel %c Received Data Bit but receiver is disabled\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index));
|
||||||
logerror("Z80SCC %s() \"%s \"Channel %c Received data dit but receiver is disabled\n", __func__, m_owner->tag(), 'A' + m_index);
|
logerror("Z80SCC %s() \"%s \"Channel %c Received data dit but receiver is disabled\n", __func__, m_owner->tag(), 'A' + m_index);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -924,7 +946,7 @@ TODO:
|
|||||||
*/
|
*/
|
||||||
void z80scc_channel::set_rts(int state)
|
void z80scc_channel::set_rts(int state)
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s(%d)\n", m_owner->tag(), 'A' + m_index, __func__, state));
|
LOG(("%s(%d) \"%s\": %c \n", FUNCNAME, state, m_owner->tag(), 'A' + m_index));
|
||||||
if (m_index == z80scc_device::CHANNEL_A)
|
if (m_index == z80scc_device::CHANNEL_A)
|
||||||
m_uart->m_out_rtsa_cb(state);
|
m_uart->m_out_rtsa_cb(state);
|
||||||
else
|
else
|
||||||
@ -933,7 +955,7 @@ void z80scc_channel::set_rts(int state)
|
|||||||
|
|
||||||
void z80scc_channel::update_rts()
|
void z80scc_channel::update_rts()
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s\n", m_owner->tag(), 'A' + m_index, __func__));
|
// LOG(("%s(%d) \"%s\": %c \n", FUNCNAME, state, m_owner->tag(), 'A' + m_index));
|
||||||
if (m_wr5 & WR5_RTS)
|
if (m_wr5 & WR5_RTS)
|
||||||
{
|
{
|
||||||
// when the RTS bit is set, the _RTS output goes low
|
// when the RTS bit is set, the _RTS output goes low
|
||||||
@ -1006,6 +1028,25 @@ int z80scc_channel::get_tx_word_length()
|
|||||||
return bits;
|
return bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This register contains the status of the receive and transmit buffers; the
|
||||||
|
* DCD, CTS, and SYNC inputs; the Transmit Underrun/EOM latch; and the
|
||||||
|
* Break/Abort latch. */
|
||||||
|
UINT8 z80scc_channel::do_sccreg_rr0()
|
||||||
|
{
|
||||||
|
LOG(("%s %s\n",FUNCNAME, tag()));
|
||||||
|
return m_rr0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This register contains the Special Receive condition status bits and Residue
|
||||||
|
* codes for the I-Field in the SDLC Receive Mode. */
|
||||||
|
UINT8 z80scc_channel::do_sccreg_rr1()
|
||||||
|
{
|
||||||
|
LOG(("%s %s\n",FUNCNAME, tag()));
|
||||||
|
return m_rr1;
|
||||||
|
}
|
||||||
|
|
||||||
/* From Zilog SCC/ESCC USers manual, UM010902-0609:
|
/* From Zilog SCC/ESCC USers manual, UM010902-0609:
|
||||||
"RR2 contains the interrupt vector written into WR2. When the register is accessed in Channel A,
|
"RR2 contains the interrupt vector written into WR2. When the register is accessed in Channel A,
|
||||||
the vector returned is the vector actually stored in WR2. When this register is accessed in Channel
|
the vector returned is the vector actually stored in WR2. When this register is accessed in Channel
|
||||||
@ -1055,7 +1096,7 @@ UINT8 z80scc_channel::do_sccreg_rr3()
|
|||||||
UINT8 z80scc_channel::do_sccreg_rr4()
|
UINT8 z80scc_channel::do_sccreg_rr4()
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC %s()\n", __func__));
|
LOG(("Z80SCC %s()\n", __func__));
|
||||||
if (m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
|
if (m_uart->m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
|
||||||
return (BIT(m_wr7, 6) ? m_wr4 : m_rr0);
|
return (BIT(m_wr7, 6) ? m_wr4 : m_rr0);
|
||||||
else
|
else
|
||||||
return m_rr0;
|
return m_rr0;
|
||||||
@ -1068,7 +1109,7 @@ UINT8 z80scc_channel::do_sccreg_rr4()
|
|||||||
UINT8 z80scc_channel::do_sccreg_rr5()
|
UINT8 z80scc_channel::do_sccreg_rr5()
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC %s()\n", __func__));
|
LOG(("Z80SCC %s()\n", __func__));
|
||||||
if (m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
|
if (m_uart->m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
|
||||||
return BIT(m_wr7, 6) ? m_wr5 : m_rr1;
|
return BIT(m_wr7, 6) ? m_wr5 : m_rr1;
|
||||||
else
|
else
|
||||||
return m_rr1;
|
return m_rr1;
|
||||||
@ -1083,7 +1124,7 @@ UINT8 z80scc_channel::do_sccreg_rr5()
|
|||||||
UINT8 z80scc_channel::do_sccreg_rr6()
|
UINT8 z80scc_channel::do_sccreg_rr6()
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC %s()\n", __func__));
|
LOG(("Z80SCC %s()\n", __func__));
|
||||||
if (!(m_variant & (SET_NMOS)))
|
if (!(m_uart->m_variant & (SET_NMOS)))
|
||||||
{
|
{
|
||||||
logerror("Z80SCC %s() not implemented feature\n", __func__);
|
logerror("Z80SCC %s() not implemented feature\n", __func__);
|
||||||
return 0;
|
return 0;
|
||||||
@ -1102,7 +1143,7 @@ UINT8 z80scc_channel::do_sccreg_rr6()
|
|||||||
UINT8 z80scc_channel::do_sccreg_rr7()
|
UINT8 z80scc_channel::do_sccreg_rr7()
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC %s()\n", __func__));
|
LOG(("Z80SCC %s()\n", __func__));
|
||||||
if (!(m_variant & (SET_NMOS)))
|
if (!(m_uart->m_variant & (SET_NMOS)))
|
||||||
{
|
{
|
||||||
logerror("Z80SCC %s() not implemented feature\n", __func__);
|
logerror("Z80SCC %s() not implemented feature\n", __func__);
|
||||||
return 0;
|
return 0;
|
||||||
@ -1125,7 +1166,7 @@ UINT8 z80scc_channel::do_sccreg_rr8()
|
|||||||
UINT8 z80scc_channel::do_sccreg_rr9()
|
UINT8 z80scc_channel::do_sccreg_rr9()
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC %s()\n", __func__));
|
LOG(("Z80SCC %s()\n", __func__));
|
||||||
if (m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
|
if (m_uart->m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
|
||||||
return BIT(m_wr7, 6) ? m_wr3 : m_rr13;
|
return BIT(m_wr7, 6) ? m_wr3 : m_rr13;
|
||||||
else
|
else
|
||||||
return m_rr13;
|
return m_rr13;
|
||||||
@ -1146,7 +1187,7 @@ UINT8 z80scc_channel::do_sccreg_rr10()
|
|||||||
UINT8 z80scc_channel::do_sccreg_rr11()
|
UINT8 z80scc_channel::do_sccreg_rr11()
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC %s()\n", __func__));
|
LOG(("Z80SCC %s()\n", __func__));
|
||||||
if (m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
|
if (m_uart->m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
|
||||||
return BIT(m_wr7, 6) ? m_wr10 : m_rr15;
|
return BIT(m_wr7, 6) ? m_wr10 : m_rr15;
|
||||||
else
|
else
|
||||||
return m_rr15;
|
return m_rr15;
|
||||||
@ -1173,7 +1214,7 @@ On the NMOS/CMOS version, a read to this location returns an image of RR10.*/
|
|||||||
UINT8 z80scc_channel::do_sccreg_rr14()
|
UINT8 z80scc_channel::do_sccreg_rr14()
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC %s()\n", __func__));
|
LOG(("Z80SCC %s()\n", __func__));
|
||||||
if (m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
|
if (m_uart->m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
|
||||||
return BIT(m_wr7, 6) ? m_wr7 : m_rr10;
|
return BIT(m_wr7, 6) ? m_wr7 : m_rr10;
|
||||||
else
|
else
|
||||||
return m_rr10;
|
return m_rr10;
|
||||||
@ -1195,13 +1236,11 @@ UINT8 z80scc_channel::do_sccreg_rr15()
|
|||||||
UINT8 z80scc_channel::control_read()
|
UINT8 z80scc_channel::control_read()
|
||||||
{
|
{
|
||||||
UINT8 data = 0;
|
UINT8 data = 0;
|
||||||
int reg = m_wr0;
|
int reg = m_uart->m_wr0_ptrbits; //m_wr0;
|
||||||
int regmask = (WR0_REGISTER_MASK | m_ph);
|
int regmask = (WR0_REGISTER_MASK | (m_uart->m_wr0_ptrbits & WR0_POINT_HIGH));
|
||||||
|
|
||||||
// LOG(("%s(%02x) reg %02x, regmask %02x, WR0 %02x\n", __func__, data, reg, regmask, m_wr0));
|
// LOG(("%s(%02x) reg %02x, regmask %02x, WR0 %02x\n", __func__, data, reg, regmask, m_wr0));
|
||||||
|
m_uart->m_wr0_ptrbits = 0;
|
||||||
m_ph = 0; // The "Point High" command is only valid for one access
|
|
||||||
|
|
||||||
reg &= regmask;
|
reg &= regmask;
|
||||||
|
|
||||||
if (reg != 0)
|
if (reg != 0)
|
||||||
@ -1213,8 +1252,8 @@ UINT8 z80scc_channel::control_read()
|
|||||||
/* TODO. Sort out 80X30 limitations in register access */
|
/* TODO. Sort out 80X30 limitations in register access */
|
||||||
switch (reg)
|
switch (reg)
|
||||||
{
|
{
|
||||||
case REG_RR0_STATUS: data = do_sioreg_rr0(); break; // TODO: verify handling of SCC specific bits: D6 and D1
|
case REG_RR0_STATUS: data = do_sccreg_rr0(); break; // TODO: verify handling of SCC specific bits: D6 and D1
|
||||||
case REG_RR1_SPEC_RCV_COND: data = do_sioreg_rr1(); break;
|
case REG_RR1_SPEC_RCV_COND: data = do_sccreg_rr1(); break;
|
||||||
case REG_RR2_INTERRUPT_VECT: data = do_sccreg_rr2(); break; // Channel dependent and SCC specific handling compared to SIO
|
case REG_RR2_INTERRUPT_VECT: data = do_sccreg_rr2(); break; // Channel dependent and SCC specific handling compared to SIO
|
||||||
/* registers 3-7 are specific to SCC. TODO: Check variant and log/stop misuse */
|
/* registers 3-7 are specific to SCC. TODO: Check variant and log/stop misuse */
|
||||||
case REG_RR3_INTERUPPT_PEND: data = do_sccreg_rr3(); break;
|
case REG_RR3_INTERUPPT_PEND: data = do_sccreg_rr3(); break;
|
||||||
@ -1232,18 +1271,42 @@ UINT8 z80scc_channel::control_read()
|
|||||||
case REG_RR14_WR7_OR_R10: data = do_sccreg_rr14(); break;
|
case REG_RR14_WR7_OR_R10: data = do_sccreg_rr14(); break;
|
||||||
case REG_RR15_WR15_EXT_STAT: data = do_sccreg_rr15(); break;
|
case REG_RR15_WR15_EXT_STAT: data = do_sccreg_rr15(); break;
|
||||||
default:
|
default:
|
||||||
logerror("Z80SCC \"%s\" %s Channel %c : Unsupported RRx register:%02x\n", m_owner->tag(), __func__, 'A' + m_index, reg);
|
logerror("Z80SCC \"%s\" %s: %c : Unsupported RRx register:%02x\n", m_owner->tag(), __func__, 'A' + m_index, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
//LOG(("Z80SCC \"%s\" Channel %c : Register R%d read '%02x'\n", m_owner->tag(), 'A' + m_index, reg, data));
|
//LOG(("Z80SCC \"%s\": %c : Register R%d read '%02x'\n", m_owner->tag(), 'A' + m_index, reg, data));
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* CRC Initialization Code handling - candidate for breaking out in a z80sio_base class
|
||||||
|
Handle the WR0 CRC Reset/Init bits separatelly, needed by derived devices separatelly from the commands */
|
||||||
|
void z80scc_channel::do_sccreg_wr0_resets(UINT8 data)
|
||||||
|
{
|
||||||
|
LOG(("%s(%02x) %s",FUNCNAME, data, tag()));
|
||||||
|
switch (data & WR0_CRC_RESET_CODE_MASK)
|
||||||
|
{
|
||||||
|
case WR0_CRC_RESET_NULL:
|
||||||
|
LOG((" CRC_RESET_NULL\n"));
|
||||||
|
break;
|
||||||
|
case WR0_CRC_RESET_RX: /* In Synchronous mode: all Os (zeros) (CCITT-O CRC-16) */
|
||||||
|
LOG((" CRC_RESET_RX - not implemented\n"));
|
||||||
|
break;
|
||||||
|
case WR0_CRC_RESET_TX: /* In HDLC mode: all 1s (ones) (CCITT-1) */
|
||||||
|
LOG((" CRC_RESET_TX - not implemented\n"));
|
||||||
|
break;
|
||||||
|
case WR0_CRC_RESET_TX_UNDERRUN: /* Resets Tx underrun/EOM bit (D6 of the SRO register) */
|
||||||
|
LOG((" CRC_RESET_TX_UNDERRUN - not implemented\n"));
|
||||||
|
break;
|
||||||
|
default: /* Will not happen unless someone messes with the mask */
|
||||||
|
logerror(" Wrong CRC reset/init command:%02x\n", data & WR0_CRC_RESET_CODE_MASK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
void z80scc_channel::do_sccreg_wr0(UINT8 data)
|
void z80scc_channel::do_sccreg_wr0(UINT8 data)
|
||||||
{
|
{
|
||||||
m_wr0 = data;
|
m_wr0 = data;
|
||||||
|
m_uart->m_wr0_ptrbits = data & WR0_REGISTER_MASK;
|
||||||
|
|
||||||
/* Sort out SCC specific behaviours from legacy SIO behaviour */
|
/* Sort out SCC specific behaviours from legacy SIO behaviour */
|
||||||
/* WR0_Z_* are Z80X30 specific commands */
|
/* WR0_Z_* are Z80X30 specific commands */
|
||||||
@ -1256,13 +1319,14 @@ void z80scc_channel::do_sccreg_wr0(UINT8 data)
|
|||||||
version of the SCC. Note that WR0 changes form depending upon the SCC version.
|
version of the SCC. Note that WR0 changes form depending upon the SCC version.
|
||||||
Register access for the Z80X30 version of the SCC is accomplished through direct
|
Register access for the Z80X30 version of the SCC is accomplished through direct
|
||||||
addressing*/
|
addressing*/
|
||||||
if (m_variant & SET_Z85X3X)
|
if (m_uart->m_variant & SET_Z85X3X)
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC \"%s\" %s Channel %c : %s - Point High command\n", m_owner->tag(), __func__, 'A' + m_index, __func__));
|
LOG(("Z80SCC \"%s\" %s: %c : %s - Point High command\n", m_owner->tag(), __func__, 'A' + m_index, __func__));
|
||||||
m_ph = 8;
|
//m_ph = 8;
|
||||||
|
m_uart->m_wr0_ptrbits |= 8;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LOG(("Z80SCC \"%s\" %s Channel %c : %s - NULL command 2\n", m_owner->tag(), __func__, 'A' + m_index, __func__));
|
LOG(("Z80SCC \"%s\" %s: %c : %s - NULL command 2\n", m_owner->tag(), __func__, 'A' + m_index, __func__));
|
||||||
break;
|
break;
|
||||||
case WR0_RESET_EXT_STATUS: // TODO: Take care of the Zero Count flag and the 2 slot fifo
|
case WR0_RESET_EXT_STATUS: // TODO: Take care of the Zero Count flag and the 2 slot fifo
|
||||||
/*After an External/Status interrupt (a change on a modem line or a break condition,
|
/*After an External/Status interrupt (a change on a modem line or a break condition,
|
||||||
@ -1276,19 +1340,19 @@ void z80scc_channel::do_sccreg_wr0(UINT8 data)
|
|||||||
External/Status interrupt. However, if this second status change does not persist
|
External/Status interrupt. However, if this second status change does not persist
|
||||||
(there are two transitions), another interrupt is not generated. Exceptions to this
|
(there are two transitions), another interrupt is not generated. Exceptions to this
|
||||||
rule are detailed in the RR0 description.*/
|
rule are detailed in the RR0 description.*/
|
||||||
do_sioreg_wr0(data);
|
// do_sccreg_wr0(data);
|
||||||
if (!m_zc)
|
if (!m_zc)
|
||||||
{
|
{
|
||||||
m_rr0 |= RR0_ZC;
|
m_rr0 |= RR0_ZC;
|
||||||
}
|
}
|
||||||
LOG(("Z80SCC \"%s\" %s Channel %c : %s - Reset External/Status Interrupt\n", m_owner->tag(), __func__, 'A' + m_index, __func__));
|
LOG(("Z80SCC \"%s\" %s: %c : %s - Reset External/Status Interrupt\n", m_owner->tag(), __func__, 'A' + m_index, __func__));
|
||||||
break;
|
break;
|
||||||
case WR0_RESET_HIGHEST_IUS:
|
case WR0_RESET_HIGHEST_IUS:
|
||||||
/* This command resets the highest priority Interrupt Under Service (IUS) bit, allowing lower
|
/* This command resets the highest priority Interrupt Under Service (IUS) bit, allowing lower
|
||||||
priority conditions to request interrupts. This command allows the use of the internal
|
priority conditions to request interrupts. This command allows the use of the internal
|
||||||
daisy chain (even in systems without an external daisy chain) and is the last operation in
|
daisy chain (even in systems without an external daisy chain) and is the last operation in
|
||||||
an interrupt service routine.TODO: Implement internal Daisychain */
|
an interrupt service routine.TODO: Implement internal Daisychain */
|
||||||
LOG(("Z80SCC \"%s\" %s Channel %c : Reset Highest IUS\n", m_owner->tag(), __func__, 'A' + m_index));
|
LOG(("Z80SCC \"%s\" %s: %c : Reset Highest IUS\n", m_owner->tag(), __func__, 'A' + m_index));
|
||||||
break;
|
break;
|
||||||
case WR0_ERROR_RESET:
|
case WR0_ERROR_RESET:
|
||||||
/*Error Reset Command (110). This command resets the error bits in RR1. If interrupt on first Rx
|
/*Error Reset Command (110). This command resets the error bits in RR1. If interrupt on first Rx
|
||||||
@ -1296,21 +1360,37 @@ void z80scc_channel::do_sccreg_wr0(UINT8 data)
|
|||||||
data with the special condition is held in the Receive FIFO until this command is issued. If either
|
data with the special condition is held in the Receive FIFO until this command is issued. If either
|
||||||
of these modes is selected and this command is issued before the data has been read from the
|
of these modes is selected and this command is issued before the data has been read from the
|
||||||
Receive FIFO, the data is lost */
|
Receive FIFO, the data is lost */
|
||||||
LOG(("Z80SCC \"%s\" %s Channel %c : WR0_ERROR_RESET\n", m_owner->tag(), __func__, 'A' + m_index));
|
LOG(("Z80SCC \"%s\" %s: %c : WR0_ERROR_RESET\n", m_owner->tag(), __func__, 'A' + m_index));
|
||||||
do_sioreg_wr0(data); // reset status registers
|
//do_sccreg_wr0(data); // reset status registers
|
||||||
m_rx_fifo_rp_step(); // Reset error state in fifo and unlock it. unlock == step to next slot in fifo.
|
m_rx_fifo_rp_step(); // Reset error state in fifo and unlock it. unlock == step to next slot in fifo.
|
||||||
break;
|
break;
|
||||||
case WR0_SEND_ABORT:
|
case WR0_SEND_ABORT:
|
||||||
data &= 0xef; // convert SCC SEND_ABORT command to a SIO SEND_ABORT command and fall through
|
data &= 0xef; // convert SCC SEND_ABORT command to a SIO SEND_ABORT command and fall through
|
||||||
/* The following commands relies on the SIO default behviour */
|
/* The following commands relies on the SIO default behviour */
|
||||||
case WR0_NULL:
|
case WR0_NULL:
|
||||||
|
LOG(("Z80SCC \"%s\" Channel %c : Null\n", m_owner->tag(), 'A' + m_index));
|
||||||
|
break;
|
||||||
case WR0_ENABLE_INT_NEXT_RX:
|
case WR0_ENABLE_INT_NEXT_RX:
|
||||||
|
// enable interrupt on next receive character
|
||||||
|
LOG(("Z80SCC \"%s\" Channel %c : Enable Interrupt on Next Received Character\n", m_owner->tag(), 'A' + m_index));
|
||||||
|
m_rx_first = 1;
|
||||||
|
break;
|
||||||
case WR0_RESET_TX_INT:
|
case WR0_RESET_TX_INT:
|
||||||
|
// reset transmitter interrupt pending
|
||||||
|
LOG(("Z80SCC \"%s\" Channel %c : Reset Transmitter Interrupt Pending\n", m_owner->tag(), 'A' + m_index));
|
||||||
|
logerror("Z80SCC \"%s\" Channel %c : unsupported command: Reset Transmitter Interrupt Pending\n", m_owner->tag(), 'A' + m_index);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
do_sioreg_wr0(data);
|
break;
|
||||||
|
// do_sioreg_wr0(data);
|
||||||
}
|
}
|
||||||
do_sioreg_wr0_resets(data);
|
do_sccreg_wr0_resets(data);
|
||||||
if ( m_variant & SET_Z80X30) // TODO: Implement adress decoding for Z80X30 using the shift logic described below
|
|
||||||
|
if ( m_uart->m_variant & SET_Z85X3X)
|
||||||
|
{
|
||||||
|
m_uart->m_wr0_ptrbits |= (m_wr0 & (WR0_REGISTER_MASK));
|
||||||
|
}
|
||||||
|
else if ( m_uart->m_variant & SET_Z80X30) // TODO: Implement adress decoding for Z80X30 using the shift logic described below
|
||||||
{
|
{
|
||||||
/*The registers in the Z80X30 are addressed via the address on AD7-AD0 and are latched by the rising
|
/*The registers in the Z80X30 are addressed via the address on AD7-AD0 and are latched by the rising
|
||||||
edge of /AS. The Shift Right/Shift Left bit in the Channel B WR0 controls which bits are
|
edge of /AS. The Shift Right/Shift Left bit in the Channel B WR0 controls which bits are
|
||||||
@ -1335,14 +1415,14 @@ void z80scc_channel::do_sccreg_wr0(UINT8 data)
|
|||||||
switch(data & WR0_Z_SHIFT_MASK)
|
switch(data & WR0_Z_SHIFT_MASK)
|
||||||
{
|
{
|
||||||
case WR0_Z_SEL_SHFT_LEFT:
|
case WR0_Z_SEL_SHFT_LEFT:
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s - Shift Left Addressing Mode - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
|
LOG(("Z80SCC \"%s\": %c : %s - Shift Left Addressing Mode - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
|
||||||
break;
|
break;
|
||||||
case WR0_Z_SEL_SHFT_RIGHT:
|
case WR0_Z_SEL_SHFT_RIGHT:
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s - Shift Right Addressing Mode - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
|
LOG(("Z80SCC \"%s\": %c : %s - Shift Right Addressing Mode - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
// LOG(("Z80SCC \"%s\" Channel %c : %s - Null commands\n", m_owner->tag(), 'A' + m_index, __func__));
|
// LOG(("Z80SCC \"%s\": %c : %s - Null commands\n", m_owner->tag(), 'A' + m_index, __func__));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1350,11 +1430,36 @@ void z80scc_channel::do_sccreg_wr0(UINT8 data)
|
|||||||
/* Write Register 1 is the control register for the various SCC interrupt and Wait/Request modes.*/
|
/* Write Register 1 is the control register for the various SCC interrupt and Wait/Request modes.*/
|
||||||
void z80scc_channel::do_sccreg_wr1(UINT8 data)
|
void z80scc_channel::do_sccreg_wr1(UINT8 data)
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s - %02x\n", m_owner->tag(), 'A' + m_index, __func__, data));
|
LOG(("%s(%02x) \"%s\": %c : %s - %02x\n", FUNCNAME, data, m_owner->tag(), 'A' + m_index, __func__, data));
|
||||||
/* TODO: Sort out SCC specific behaviours from legacy SIO behaviours:
|
/* TODO: Sort out SCC specific behaviours from legacy SIO behaviours:
|
||||||
- Channel B only bits vs
|
- Channel B only bits vs
|
||||||
- Parity Is Special Condition, bit2 */
|
- Parity Is Special Condition, bit2 */
|
||||||
do_sioreg_wr1(data & ~0x40); // Lets SIO code handle it for now but mask out dangerous bits
|
m_wr1 = data;
|
||||||
|
LOG(("- External Interrupt Enable %u\n", (data & WR1_EXT_INT_ENABLE) ? 1 : 0));
|
||||||
|
LOG(("- Transmit Interrupt Enable %u\n", (data & WR1_TX_INT_ENABLE) ? 1 : 0));
|
||||||
|
LOG(("- Parity is special condition %u\n", (data & WR1_PARITY_IS_SPEC_COND) ? 1 : 0));
|
||||||
|
LOG(("- Wait/Ready Enable %u\n", (data & WR1_WRDY_ENABLE) ? 1 : 0));
|
||||||
|
LOG(("- Wait/Ready Function %s\n", (data & WR1_WRDY_FUNCTION) ? "Ready" : "Wait"));
|
||||||
|
LOG(("- Wait/Ready on %s\n", (data & WR1_WRDY_ON_RX_TX) ? "Receive" : "Transmit"));
|
||||||
|
|
||||||
|
switch (data & WR1_RX_INT_MODE_MASK)
|
||||||
|
{
|
||||||
|
case WR1_RX_INT_DISABLE:
|
||||||
|
LOG(("- Receiver Interrupt Disabled\n"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WR1_RX_INT_FIRST:
|
||||||
|
LOG(("- Receiver Interrupt on First Character\n"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WR1_RX_INT_ALL_PARITY:
|
||||||
|
LOG(("- Receiver Interrupt on All Characters, Parity Affects Vector\n"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WR1_RX_INT_ALL:
|
||||||
|
LOG(("- Receiver Interrupt on All Characters\n"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
m_uart->check_interrupts();
|
m_uart->check_interrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1363,7 +1468,7 @@ accessed through either channel. The interrupt vector can be modified by status
|
|||||||
is controlled by the Vector Includes Status (VIS) and the Status High/Status Low bits in WR9.*/
|
is controlled by the Vector Includes Status (VIS) and the Status High/Status Low bits in WR9.*/
|
||||||
void z80scc_channel::do_sccreg_wr2(UINT8 data)
|
void z80scc_channel::do_sccreg_wr2(UINT8 data)
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s - Setting the interrupt vector to: %02x \n", m_owner->tag(), 'A' + m_index, __func__, data));
|
LOG(("%s(%d) Setting the interrupt vector\n", FUNCNAME, data));
|
||||||
m_wr2 = data;
|
m_wr2 = data;
|
||||||
m_uart->m_chanA->m_rr2 = data;
|
m_uart->m_chanA->m_rr2 = data;
|
||||||
m_uart->m_chanB->m_rr2 = data; /* TODO: Sort out the setting of ChanB depending on bits in WR9 */
|
m_uart->m_chanB->m_rr2 = data; /* TODO: Sort out the setting of ChanB depending on bits in WR9 */
|
||||||
@ -1371,14 +1476,52 @@ void z80scc_channel::do_sccreg_wr2(UINT8 data)
|
|||||||
m_uart->check_interrupts();
|
m_uart->check_interrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void z80scc_channel::do_sccreg_wr3(UINT8 data)
|
||||||
* NOTE: Register WR3-WR7 are identical to the Z80SIO so handled by z80sio.c
|
{
|
||||||
*/
|
LOG(("%s(%d) Setting up the receiver\n", FUNCNAME, data));
|
||||||
|
m_wr3 = data;
|
||||||
|
LOG(("- Receiver Enable %u\n", (data & WR3_RX_ENABLE) ? 1 : 0));
|
||||||
|
LOG(("- Auto Enables %u\n", (data & WR3_AUTO_ENABLES) ? 1 : 0));
|
||||||
|
LOG(("- Receiver Bits/Character %u\n", get_rx_word_length()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void z80scc_channel::do_sccreg_wr4(UINT8 data)
|
||||||
|
{
|
||||||
|
LOG(("%s(%d) Setting up asynchronous frame format and clock\n", FUNCNAME, data));
|
||||||
|
m_wr4 = data;
|
||||||
|
LOG(("- Parity Enable %u\n", (data & WR4_PARITY_ENABLE) ? 1 : 0));
|
||||||
|
LOG(("- Parity %s\n", (data & WR4_PARITY_EVEN) ? "Even" : "Odd"));
|
||||||
|
LOG(("- Stop Bits %s\n", stop_bits_tostring(get_stop_bits())));
|
||||||
|
LOG(("- Clock Mode %uX\n", get_clock_mode()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void z80scc_channel::do_sccreg_wr5(UINT8 data)
|
||||||
|
{
|
||||||
|
LOG(("%s(%d) Setting up the transmitter\n", FUNCNAME, data));
|
||||||
|
m_wr5 = data;
|
||||||
|
LOG(("- Transmitter Enable %u\n", (data & WR5_TX_ENABLE) ? 1 : 0));
|
||||||
|
LOG(("- Transmitter Bits/Character %u\n", get_tx_word_length()));
|
||||||
|
LOG(("- Send Break %u\n", (data & WR5_SEND_BREAK) ? 1 : 0));
|
||||||
|
LOG(("- Request to Send %u\n", (data & WR5_RTS) ? 1 : 0));
|
||||||
|
LOG(("- Data Terminal Ready %u\n", (data & WR5_DTR) ? 1 : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void z80scc_channel::do_sccreg_wr6(UINT8 data)
|
||||||
|
{
|
||||||
|
LOG(("%s(%d) Transmit sync\n", FUNCNAME, data));
|
||||||
|
m_sync = (m_sync & 0xff00) | data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void z80scc_channel::do_sccreg_wr7(UINT8 data)
|
||||||
|
{
|
||||||
|
LOG(("%s(%d) Receive sync\n", FUNCNAME, data));
|
||||||
|
m_sync = (data << 8) | (m_sync & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
/* WR8 is the transmit buffer register */
|
/* WR8 is the transmit buffer register */
|
||||||
void z80scc_channel::do_sccreg_wr8(UINT8 data)
|
void z80scc_channel::do_sccreg_wr8(UINT8 data)
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : Transmit Buffer read %02x\n", m_owner->tag(), 'A' + m_index, data));
|
LOG(("%s(%d) \"%s\": %c : Transmit Buffer read %02x\n", FUNCNAME, data, m_owner->tag(), 'A' + m_index, data));
|
||||||
data_write(data);
|
data_write(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1388,7 +1531,7 @@ at the same time as the Reset command, because these bits are only reset by a ha
|
|||||||
note that the Z80X30 contains only one WR2 and WR9; these registers may be written from either channel.*/
|
note that the Z80X30 contains only one WR2 and WR9; these registers may be written from either channel.*/
|
||||||
void z80scc_channel::do_sccreg_wr9(UINT8 data)
|
void z80scc_channel::do_sccreg_wr9(UINT8 data)
|
||||||
{
|
{
|
||||||
if (m_variant & SET_Z80X30)
|
if (m_uart->m_variant & SET_Z80X30)
|
||||||
{
|
{
|
||||||
m_uart->m_chanA->m_wr9 = data;
|
m_uart->m_chanA->m_wr9 = data;
|
||||||
m_uart->m_chanB->m_wr9 = data;
|
m_uart->m_chanB->m_wr9 = data;
|
||||||
@ -1399,18 +1542,18 @@ void z80scc_channel::do_sccreg_wr9(UINT8 data)
|
|||||||
switch (data & WR9_CMD_MASK)
|
switch (data & WR9_CMD_MASK)
|
||||||
{
|
{
|
||||||
case WR9_CMD_NORESET:
|
case WR9_CMD_NORESET:
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : Master Interrupt Control - No reset %02x\n", m_owner->tag(), 'A' + m_index, data));
|
LOG(("Z80SCC \"%s\": %c : Master Interrupt Control - No reset %02x\n", m_owner->tag(), 'A' + m_index, data));
|
||||||
break;
|
break;
|
||||||
case WR9_CMD_CHNB_RESET:
|
case WR9_CMD_CHNB_RESET:
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : Master Interrupt Control - Channel B reset %02x\n", m_owner->tag(), 'A' + m_index, data));
|
LOG(("Z80SCC \"%s\": %c : Master Interrupt Control - Channel B reset %02x\n", m_owner->tag(), 'A' + m_index, data));
|
||||||
m_uart->m_chanB->reset();
|
m_uart->m_chanB->reset();
|
||||||
break;
|
break;
|
||||||
case WR9_CMD_CHNA_RESET:
|
case WR9_CMD_CHNA_RESET:
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : Master Interrupt Control - Channel A reset %02x\n", m_owner->tag(), 'A' + m_index, data));
|
LOG(("Z80SCC \"%s\": %c : Master Interrupt Control - Channel A reset %02x\n", m_owner->tag(), 'A' + m_index, data));
|
||||||
m_uart->m_chanA->reset();
|
m_uart->m_chanA->reset();
|
||||||
break;
|
break;
|
||||||
case WR9_CMD_HW_RESET:
|
case WR9_CMD_HW_RESET:
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : Master Interrupt Control - Device reset %02x\n", m_owner->tag(), 'A' + m_index, data));
|
LOG(("Z80SCC \"%s\": %c : Master Interrupt Control - Device reset %02x\n", m_owner->tag(), 'A' + m_index, data));
|
||||||
/*"The effects of this command are identical to those of a hardware reset, except that the Shift Right/Shift Left bit is
|
/*"The effects of this command are identical to those of a hardware reset, except that the Shift Right/Shift Left bit is
|
||||||
not changed and the MIE, Status High/Status Low and DLC bits take the programmed values that accompany this command."
|
not changed and the MIE, Status High/Status Low and DLC bits take the programmed values that accompany this command."
|
||||||
The Shift Right/Shift Left bits of the WR0 is only valid on SCC8030 device hence not implemented yet, just the SCC8530 */
|
The Shift Right/Shift Left bits of the WR0 is only valid on SCC8030 device hence not implemented yet, just the SCC8530 */
|
||||||
@ -1428,7 +1571,7 @@ enabled, this register may be read as RR11.*/
|
|||||||
void z80scc_channel::do_sccreg_wr10(UINT8 data)
|
void z80scc_channel::do_sccreg_wr10(UINT8 data)
|
||||||
{
|
{
|
||||||
m_wr10 = data;
|
m_wr10 = data;
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s Misc Tx/Rx Control %02x - not implemented \n", m_owner->tag(), 'A' + m_index, __func__, data));
|
LOG(("Z80SCC \"%s\": %c : %s Misc Tx/Rx Control %02x - not implemented \n", m_owner->tag(), 'A' + m_index, __func__, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* WR11 is the Clock Mode Control register. The bits in this register control the sources of both the
|
/* WR11 is the Clock Mode Control register. The bits in this register control the sources of both the
|
||||||
@ -1436,7 +1579,7 @@ receive and transmit clocks, the type of signal on the /SYNC and /RTxC pins, and
|
|||||||
the /TRxC pin.*/
|
the /TRxC pin.*/
|
||||||
void z80scc_channel::do_sccreg_wr11(UINT8 data)
|
void z80scc_channel::do_sccreg_wr11(UINT8 data)
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s Clock Mode Control %02x - not implemented \n", m_owner->tag(), 'A' + m_index, __func__, data));
|
LOG(("Z80SCC \"%s\": %c : %s Clock Mode Control %02x - not implemented \n", m_owner->tag(), 'A' + m_index, __func__, data));
|
||||||
m_wr11 = data;
|
m_wr11 = data;
|
||||||
/*Bit 7: This bit controls the type of input signal the SCC expects to see on the /RTxC pin. If this bit is set
|
/*Bit 7: This bit controls the type of input signal the SCC expects to see on the /RTxC pin. If this bit is set
|
||||||
to 0, the SCC expects a TTL-compatible signal as an input to this pin. If this bit is set to 1, the SCC
|
to 0, the SCC expects a TTL-compatible signal as an input to this pin. If this bit is set to 1, the SCC
|
||||||
@ -1520,14 +1663,14 @@ This is then fed to a toggle flip-flop to make the output a square wave.
|
|||||||
void z80scc_channel::do_sccreg_wr12(UINT8 data)
|
void z80scc_channel::do_sccreg_wr12(UINT8 data)
|
||||||
{
|
{
|
||||||
m_wr12 = data;
|
m_wr12 = data;
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s %02x Low byte of Time Constant for Baudrate generator - not implemented \n", m_owner->tag(), 'A' + m_index, __func__, data));
|
LOG(("Z80SCC \"%s\": %c : %s %02x Low byte of Time Constant for Baudrate generator - not implemented \n", m_owner->tag(), 'A' + m_index, __func__, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* WR13 contains the upper byte of the time constant for the baud rate generator. */
|
/* WR13 contains the upper byte of the time constant for the baud rate generator. */
|
||||||
void z80scc_channel::do_sccreg_wr13(UINT8 data)
|
void z80scc_channel::do_sccreg_wr13(UINT8 data)
|
||||||
{
|
{
|
||||||
m_wr13 = data;
|
m_wr13 = data;
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s %02x High byte of Time Constant for Baudrate generator - not implemented \n", m_owner->tag(), 'A' + m_index, __func__, data));
|
LOG(("Z80SCC \"%s\": %c : %s %02x High byte of Time Constant for Baudrate generator - not implemented \n", m_owner->tag(), 'A' + m_index, __func__, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1537,7 +1680,7 @@ void z80scc_channel::do_sccreg_wr14(UINT8 data)
|
|||||||
switch (data & WR14_DPLL_CMD_MASK)
|
switch (data & WR14_DPLL_CMD_MASK)
|
||||||
{
|
{
|
||||||
case WR14_CMD_NULL:
|
case WR14_CMD_NULL:
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s Misc Control Bits Null Command %02x\n", m_owner->tag(), 'A' + m_index, __func__, data));
|
LOG(("Z80SCC \"%s\": %c : %s Misc Control Bits Null Command %02x\n", m_owner->tag(), 'A' + m_index, __func__, data));
|
||||||
break;
|
break;
|
||||||
case WR14_CMD_ESM:
|
case WR14_CMD_ESM:
|
||||||
/* Issuing this command causes the DPLL to enter the Search mode, where the DPLL searches for a locking edge in the
|
/* Issuing this command causes the DPLL to enter the Search mode, where the DPLL searches for a locking edge in the
|
||||||
@ -1559,36 +1702,36 @@ void z80scc_channel::do_sccreg_wr14(UINT8 data)
|
|||||||
see an edge during the expected window, the one clock missing bit in RR10 is set. If the DPLL does not see an edge
|
see an edge during the expected window, the one clock missing bit in RR10 is set. If the DPLL does not see an edge
|
||||||
after two successive attempts, the two clocks missing bits in RR10 are set and the DPLL automatically enters the
|
after two successive attempts, the two clocks missing bits in RR10 are set and the DPLL automatically enters the
|
||||||
Search mode. This command resets both clocks missing latches.*/
|
Search mode. This command resets both clocks missing latches.*/
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s Misc Control Bits Enter Search Mode Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
|
LOG(("Z80SCC \"%s\": %c : %s Misc Control Bits Enter Search Mode Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
|
||||||
break;
|
break;
|
||||||
case WR14_CMD_RMC:
|
case WR14_CMD_RMC:
|
||||||
/* Issuing this command disables the DPLL, resets the clock missing latches in RR10, and forces a continuous Search mode state */
|
/* Issuing this command disables the DPLL, resets the clock missing latches in RR10, and forces a continuous Search mode state */
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s Misc Control Bits Reset Missing Clocks Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
|
LOG(("Z80SCC \"%s\": %c : %s Misc Control Bits Reset Missing Clocks Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
|
||||||
break;
|
break;
|
||||||
case WR14_CMD_DISABLE_DPLL:
|
case WR14_CMD_DISABLE_DPLL:
|
||||||
/* Issuing this command disables the DPLL, resets the clock missing latches in RR10, and forces a continuous Search mode state.*/
|
/* Issuing this command disables the DPLL, resets the clock missing latches in RR10, and forces a continuous Search mode state.*/
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s Misc Control Bits Disable DPLL Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
|
LOG(("Z80SCC \"%s\": %c : %s Misc Control Bits Disable DPLL Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
|
||||||
break;
|
break;
|
||||||
case WR14_CMD_SS_BGR:
|
case WR14_CMD_SS_BGR:
|
||||||
/* Issuing this command forces the clock for the DPLL to come from the output of the BRG. */
|
/* Issuing this command forces the clock for the DPLL to come from the output of the BRG. */
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s Misc Control Bits Baudrate Generator Input DPLL Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
|
LOG(("Z80SCC \"%s\": %c : %s Misc Control Bits Baudrate Generator Input DPLL Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
|
||||||
break;
|
break;
|
||||||
case WR14_CMD_SS_RTXC:
|
case WR14_CMD_SS_RTXC:
|
||||||
/* Issuing the command forces the clock for the DPLL to come from the /RTxC pin or the crystal oscillator, depending on
|
/* Issuing the command forces the clock for the DPLL to come from the /RTxC pin or the crystal oscillator, depending on
|
||||||
the state of the XTAL/no XTAL bit in WR11. This mode is selected by a channel or hardware reset*/
|
the state of the XTAL/no XTAL bit in WR11. This mode is selected by a channel or hardware reset*/
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s Misc Control Bits RTxC Input DPLL Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
|
LOG(("Z80SCC \"%s\": %c : %s Misc Control Bits RTxC Input DPLL Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
|
||||||
break;
|
break;
|
||||||
case WR14_CMD_SET_FM:
|
case WR14_CMD_SET_FM:
|
||||||
/* This command forces the DPLL to operate in the FM mode and is used to recover the clock from FM or Manchester-Encoded
|
/* This command forces the DPLL to operate in the FM mode and is used to recover the clock from FM or Manchester-Encoded
|
||||||
data. (Manchester is decoded by placing the receiver in NRZ mode while the DPLL is in FM mode.)*/
|
data. (Manchester is decoded by placing the receiver in NRZ mode while the DPLL is in FM mode.)*/
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s Misc Control Bits Set FM Mode Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
|
LOG(("Z80SCC \"%s\": %c : %s Misc Control Bits Set FM Mode Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
|
||||||
break;
|
break;
|
||||||
case WR14_CMD_SET_NRZI:
|
case WR14_CMD_SET_NRZI:
|
||||||
/* Issuing this command forces the DPLL to operate in the NRZI mode. This mode is also selected by a hardware or channel reset.*/
|
/* Issuing this command forces the DPLL to operate in the NRZI mode. This mode is also selected by a hardware or channel reset.*/
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s Mics Control Bits Set NRZI Mode Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
|
LOG(("Z80SCC \"%s\": %c : %s Mics Control Bits Set NRZI Mode Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logerror("Z80SCC \"%s\" Channel %c : %s Mics Control Bits command %02x - not implemented \n", m_owner->tag(), 'A' + m_index, __func__, data);
|
logerror("Z80SCC \"%s\": %c : %s Mics Control Bits command %02x - not implemented \n", m_owner->tag(), 'A' + m_index, __func__, data);
|
||||||
}
|
}
|
||||||
// TODO: Add info on the other bits of this register
|
// TODO: Add info on the other bits of this register
|
||||||
m_wr14 = data;
|
m_wr14 = data;
|
||||||
@ -1600,21 +1743,43 @@ Only the External/Status conditions that occur after the controlling bit is set
|
|||||||
interrupt. This is true, even if an External/Status condition is pending at the time the bit is set*/
|
interrupt. This is true, even if an External/Status condition is pending at the time the bit is set*/
|
||||||
void z80scc_channel::do_sccreg_wr15(UINT8 data)
|
void z80scc_channel::do_sccreg_wr15(UINT8 data)
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s External/Status Source Control Bits %02x - not implemented \n", m_owner->tag(), 'A' + m_index, __func__, data));
|
LOG(("%s(%d) \"%s\": %c : External/Status Control Bits - not implemented\n",
|
||||||
|
FUNCNAME, data, m_owner->tag(), 'A' + m_index));
|
||||||
m_wr15 = data;
|
m_wr15 = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*TODO: Z80X30 Register Access
|
||||||
|
----------------------------
|
||||||
|
The Shift Right/Shift Left bit in the Channel B WR0 controls which bits are decoded to form the register
|
||||||
|
address. See do_sccreg_wr0() for details */
|
||||||
|
|
||||||
|
/*Z85X30 Register Access
|
||||||
|
-----------------------
|
||||||
|
The registers in the Z85X30 are accessed in a two step process, using a Register Pointer to perform
|
||||||
|
the addressing. To access a particular register, the pointer bits are set by writing to WR0. The
|
||||||
|
pointer bits may be written in either channel because only one set exists in the Z85X30. After the
|
||||||
|
pointer bits are set, the next read or write cycle of the Z85X30 having D//C Low will access the
|
||||||
|
desired register. At the conclusion of this read or write cycle the pointer bits are reset to 0s, so that
|
||||||
|
the next control write is to the pointers in WR0.
|
||||||
|
|
||||||
|
A read to RR8 (the receive data FIFO) or a write to WR8 (the transmit data FIFO) is either done in
|
||||||
|
this fashion or by accessing the Z85X30 having D//C pin High. A read or write with D//C High
|
||||||
|
accesses the data registers directly, and independently of the state of the pointer bits. This allows
|
||||||
|
single-cycle access to the data registers and does not disturb the pointer bits.
|
||||||
|
|
||||||
|
The fact that the pointer bits are reset to 0, unless explicitly set otherwise, means that WR0 and
|
||||||
|
RR0 may also be accessed in a single cycle. That is, it is not necessary to write the pointer bits
|
||||||
|
with 0 before accessing WR0 or RR0.*/
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// control_write - write control register
|
// control_write - write control register
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void z80scc_channel::control_write(UINT8 data)
|
void z80scc_channel::control_write(UINT8 data)
|
||||||
{
|
{
|
||||||
UINT8 reg = m_wr0;
|
UINT8 reg = m_uart->m_wr0_ptrbits; //m_wr0;
|
||||||
UINT8 regmask = (WR0_REGISTER_MASK | m_ph);
|
UINT8 regmask = (WR0_REGISTER_MASK | (m_uart->m_wr0_ptrbits & WR0_POINT_HIGH));
|
||||||
|
|
||||||
m_ph = 0; // The "Point High" command is only valid for one access
|
m_uart->m_wr0_ptrbits = 0; // The "Point High" command is only valid for one access
|
||||||
|
|
||||||
reg &= regmask;
|
reg &= regmask;
|
||||||
|
|
||||||
@ -1624,33 +1789,33 @@ void z80scc_channel::control_write(UINT8 data)
|
|||||||
m_wr0 &= ~regmask;
|
m_wr0 &= ~regmask;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(("%s(%02x) reg %02x, regmask %02x, WR0 %02x\n", __func__, data, reg, regmask, m_wr0));
|
LOG(("\n%s(%02x) reg %02x, regmask %02x\n", FUNCNAME, data, reg, regmask));
|
||||||
|
|
||||||
/* TODO. Sort out 80X30 & other SCC variants limitations in register access */
|
/* TODO. Sort out 80X30 & other SCC variants limitations in register access */
|
||||||
switch (reg)
|
switch (reg)
|
||||||
{
|
{
|
||||||
case REG_WR0_COMMAND_REGPT: do_sccreg_wr0(data); break;
|
case REG_WR0_COMMAND_REGPT: do_sccreg_wr0(data); ;break;
|
||||||
case REG_WR1_INT_DMA_ENABLE: do_sccreg_wr1(data); m_uart->check_interrupts(); break;
|
case REG_WR1_INT_DMA_ENABLE: do_sccreg_wr1(data); m_uart->check_interrupts(); break;
|
||||||
case REG_WR2_INT_VECTOR: do_sccreg_wr2(data); break;
|
case REG_WR2_INT_VECTOR: do_sccreg_wr2(data); break;
|
||||||
case REG_WR3_RX_CONTROL:
|
case REG_WR3_RX_CONTROL:
|
||||||
do_sioreg_wr3(data);
|
do_sccreg_wr3(data);
|
||||||
update_serial();
|
update_serial();
|
||||||
receive_register_reset();
|
receive_register_reset();
|
||||||
break;
|
break;
|
||||||
case REG_WR4_RX_TX_MODES:
|
case REG_WR4_RX_TX_MODES:
|
||||||
do_sioreg_wr4(data);
|
do_sccreg_wr4(data);
|
||||||
update_serial();
|
update_serial();
|
||||||
transmit_register_reset();
|
transmit_register_reset();
|
||||||
receive_register_reset();
|
receive_register_reset();
|
||||||
break;
|
break;
|
||||||
case REG_WR5_TX_CONTROL:
|
case REG_WR5_TX_CONTROL:
|
||||||
do_sioreg_wr5(data);
|
do_sccreg_wr5(data);
|
||||||
update_serial();
|
update_serial();
|
||||||
transmit_register_reset();
|
transmit_register_reset();
|
||||||
update_rts();
|
update_rts();
|
||||||
break;
|
break;
|
||||||
case REG_WR6_SYNC_OR_SDLC_A: do_sioreg_wr6(data); break;
|
case REG_WR6_SYNC_OR_SDLC_A: do_sccreg_wr6(data); break;
|
||||||
case REG_WR7_SYNC_OR_SDLC_F: do_sioreg_wr7(data); break;
|
case REG_WR7_SYNC_OR_SDLC_F: do_sccreg_wr7(data); break;
|
||||||
case REG_WR8_TRANSMIT_DATA: do_sccreg_wr8(data); break;
|
case REG_WR8_TRANSMIT_DATA: do_sccreg_wr8(data); break;
|
||||||
case REG_WR9_MASTER_INT_CTRL: do_sccreg_wr9(data); break;
|
case REG_WR9_MASTER_INT_CTRL: do_sccreg_wr9(data); break;
|
||||||
case REG_WR10_MSC_RX_TX_CTRL: do_sccreg_wr10(data); break;
|
case REG_WR10_MSC_RX_TX_CTRL: do_sccreg_wr10(data); break;
|
||||||
@ -1658,11 +1823,9 @@ void z80scc_channel::control_write(UINT8 data)
|
|||||||
case REG_WR12_LO_BAUD_GEN: do_sccreg_wr12(data); break;
|
case REG_WR12_LO_BAUD_GEN: do_sccreg_wr12(data); break;
|
||||||
case REG_WR13_HI_BAUD_GEN: do_sccreg_wr13(data); break;
|
case REG_WR13_HI_BAUD_GEN: do_sccreg_wr13(data); break;
|
||||||
case REG_WR14_MISC_CTRL: do_sccreg_wr14(data); break;
|
case REG_WR14_MISC_CTRL: do_sccreg_wr14(data); break;
|
||||||
case REG_WR15_EXT_ST_INT_CTRL:
|
case REG_WR15_EXT_ST_INT_CTRL:do_sccreg_wr15(data); break;
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : unsupported command: External/Status Control Bits %02x\n", m_owner->tag(), 'A' + m_index, data));
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
logerror("Z80SCC \"%s\" Channel %c : Unsupported WRx register:%02x\n", m_owner->tag(), 'A' + m_index, reg);
|
logerror("Z80SCC \"%s\": %c : Unsupported WRx register:%02x\n", m_owner->tag(), 'A' + m_index, reg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1675,6 +1838,8 @@ UINT8 z80scc_channel::data_read()
|
|||||||
{
|
{
|
||||||
UINT8 data = 0;
|
UINT8 data = 0;
|
||||||
|
|
||||||
|
LOG(("%s \"%s\": %c : Data Register Read: \n", FUNCNAME, m_owner->tag(), 'A' + m_index));
|
||||||
|
|
||||||
if (m_rx_fifo_wp != m_rx_fifo_rp)
|
if (m_rx_fifo_wp != m_rx_fifo_rp)
|
||||||
{
|
{
|
||||||
/* Special Receive Condition interrupts are generated after the character is read from
|
/* Special Receive Condition interrupts are generated after the character is read from
|
||||||
@ -1723,11 +1888,11 @@ UINT8 z80scc_channel::data_read()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
LOG(("data_read: Attempt to read out character from empty FIFO\n"));
|
||||||
logerror("data_read: Attempt to read out character from empty FIFO\n");
|
logerror("data_read: Attempt to read out character from empty FIFO\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : Data Register Read '%02x'\n", m_owner->tag(), 'A' + m_index, data));
|
LOG(("'%c' %02x\n", isascii(data) ? data : ' ', data));
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1760,17 +1925,21 @@ void z80scc_channel::m_rx_fifo_rp_step()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
READ8_MEMBER (z80scc_device::da_r) { return m_chanA->data_read(); }
|
||||||
|
WRITE8_MEMBER (z80scc_device::da_w) { m_chanA->data_write(data); }
|
||||||
|
READ8_MEMBER (z80scc_device::db_r) { return m_chanB->data_read(); }
|
||||||
|
WRITE8_MEMBER (z80scc_device::db_w) { m_chanB->data_write(data); }
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// data_write - write data register
|
// data_write - write data register
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void z80scc_channel::data_write(UINT8 data)
|
void z80scc_channel::data_write(UINT8 data)
|
||||||
{
|
{
|
||||||
m_tx_data = data;
|
m_tx_data = data;
|
||||||
|
|
||||||
if ((m_wr5 & WR5_TX_ENABLE) && is_transmit_register_empty())
|
if ((m_wr5 & WR5_TX_ENABLE) && is_transmit_register_empty())
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : Transmit Data Byte '%02x'\n", m_owner->tag(), 'A' + m_index, m_tx_data));
|
LOG(("%s(%d) \"%s\": %c : Transmit Data Byte '%02x'\n", FUNCNAME, data, m_owner->tag(), 'A' + m_index, m_tx_data));
|
||||||
|
|
||||||
transmit_register_setup(m_tx_data);
|
transmit_register_setup(m_tx_data);
|
||||||
|
|
||||||
@ -1785,11 +1954,10 @@ void z80scc_channel::data_write(UINT8 data)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_rr0 &= ~RR0_TX_BUFFER_EMPTY;
|
m_rr0 &= ~RR0_TX_BUFFER_EMPTY;
|
||||||
|
LOG(("%s(%d) \"%s\": %c : failed to send %c,(%02x)\n", FUNCNAME, data, m_owner->tag(), 'A' + m_index, isascii(data) ? data : ' ', data));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_rr1 &= ~RR1_ALL_SENT;
|
m_rr1 &= ~RR1_ALL_SENT;
|
||||||
|
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : Data Register Write '%02x'\n", m_owner->tag(), 'A' + m_index, data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1799,7 +1967,7 @@ void z80scc_channel::data_write(UINT8 data)
|
|||||||
|
|
||||||
void z80scc_channel::receive_data(UINT8 data)
|
void z80scc_channel::receive_data(UINT8 data)
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : Receive Data Byte '%02x'\n", m_owner->tag(), 'A' + m_index, data));
|
LOG(("Z80SCC \"%s\": %c : Receive Data Byte '%02x'\n", m_owner->tag(), 'A' + m_index, data));
|
||||||
|
|
||||||
if (m_rx_fifo_wp + 1 == m_rx_fifo_rp ||
|
if (m_rx_fifo_wp + 1 == m_rx_fifo_rp ||
|
||||||
( (m_rx_fifo_wp + 1 == m_rx_fifo_sz) && (m_rx_fifo_rp == 0) ))
|
( (m_rx_fifo_wp + 1 == m_rx_fifo_sz) && (m_rx_fifo_rp == 0) ))
|
||||||
@ -1850,7 +2018,7 @@ void z80scc_channel::receive_data(UINT8 data)
|
|||||||
|
|
||||||
WRITE_LINE_MEMBER( z80scc_channel::cts_w )
|
WRITE_LINE_MEMBER( z80scc_channel::cts_w )
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC \"%s\" %s Channel %c : CTS %u\n", m_owner->tag(), __func__, 'A' + m_index, state));
|
LOG(("Z80SCC \"%s\" %s: %c : CTS %u\n", m_owner->tag(), __func__, 'A' + m_index, state));
|
||||||
|
|
||||||
if (m_cts != state)
|
if (m_cts != state)
|
||||||
{
|
{
|
||||||
@ -1880,7 +2048,6 @@ WRITE_LINE_MEMBER( z80scc_channel::cts_w )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// m_rr0 &= ~RR0_CTS; // Remove, just to test
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1890,7 +2057,7 @@ WRITE_LINE_MEMBER( z80scc_channel::cts_w )
|
|||||||
|
|
||||||
WRITE_LINE_MEMBER( z80scc_channel::dcd_w )
|
WRITE_LINE_MEMBER( z80scc_channel::dcd_w )
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : DCD %u\n", m_owner->tag(), 'A' + m_index, state));
|
LOG(("Z80SCC \"%s\": %c : DCD %u\n", m_owner->tag(), 'A' + m_index, state));
|
||||||
|
|
||||||
if (m_dcd != state)
|
if (m_dcd != state)
|
||||||
{
|
{
|
||||||
@ -1928,7 +2095,7 @@ WRITE_LINE_MEMBER( z80scc_channel::dcd_w )
|
|||||||
|
|
||||||
WRITE_LINE_MEMBER( z80scc_channel::ri_w )
|
WRITE_LINE_MEMBER( z80scc_channel::ri_w )
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : RI %u\n", m_owner->tag(), 'A' + m_index, state));
|
LOG(("Z80SCC \"%s\": %c : RI %u\n", m_owner->tag(), 'A' + m_index, state));
|
||||||
|
|
||||||
if (m_ri != state)
|
if (m_ri != state)
|
||||||
{
|
{
|
||||||
@ -1959,7 +2126,7 @@ WRITE_LINE_MEMBER( z80scc_channel::ri_w )
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
WRITE_LINE_MEMBER( z80scc_channel::sync_w )
|
WRITE_LINE_MEMBER( z80scc_channel::sync_w )
|
||||||
{
|
{
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : SYNC %u\n", m_owner->tag(), 'A' + m_index, state));
|
LOG(("Z80SCC \"%s\": %c : SYNC %u\n", m_owner->tag(), 'A' + m_index, state));
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
@ -1967,7 +2134,9 @@ WRITE_LINE_MEMBER( z80scc_channel::sync_w )
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
WRITE_LINE_MEMBER( z80scc_channel::rxc_w )
|
WRITE_LINE_MEMBER( z80scc_channel::rxc_w )
|
||||||
{
|
{
|
||||||
//LOG(("Z80SCC \"%s\" Channel %c : Receiver Clock Pulse\n", m_owner->tag(), m_index + 'A'));
|
//LOG(("Z80SCC \"%s\": %c : Receiver Clock Pulse\n", m_owner->tag(), m_index + 'A'));
|
||||||
|
if (m_wr3 & WR3_RX_ENABLE)
|
||||||
|
{
|
||||||
int clocks = get_clock_mode();
|
int clocks = get_clock_mode();
|
||||||
if (clocks == 1)
|
if (clocks == 1)
|
||||||
rx_clock_w(state);
|
rx_clock_w(state);
|
||||||
@ -1981,13 +2150,16 @@ WRITE_LINE_MEMBER( z80scc_channel::rxc_w )
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// txc_w - transmit clock
|
// txc_w - transmit clock
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
WRITE_LINE_MEMBER( z80scc_channel::txc_w )
|
WRITE_LINE_MEMBER( z80scc_channel::txc_w )
|
||||||
{
|
{
|
||||||
//LOG(("Z80SCC \"%s\" Channel %c : Transmitter Clock Pulse\n", m_owner->tag(), m_index + 'A'));
|
//LOG(("Z80SCC \"%s\": %c : Transmitter Clock Pulse\n", m_owner->tag(), m_index + 'A'));
|
||||||
|
if (m_wr5 & WR5_TX_ENABLE)
|
||||||
|
{
|
||||||
int clocks = get_clock_mode();
|
int clocks = get_clock_mode();
|
||||||
if (clocks == 1)
|
if (clocks == 1)
|
||||||
tx_clock_w(state);
|
tx_clock_w(state);
|
||||||
@ -1998,7 +2170,7 @@ WRITE_LINE_MEMBER( z80scc_channel::txc_w )
|
|||||||
m_tx_clock++;
|
m_tx_clock++;
|
||||||
if (m_tx_clock == clocks)
|
if (m_tx_clock == clocks)
|
||||||
m_tx_clock = 0;
|
m_tx_clock = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2045,9 +2217,9 @@ void z80scc_channel::update_serial()
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
void z80scc_channel::set_dtr(int state)
|
void z80scc_channel::set_dtr(int state)
|
||||||
{
|
{
|
||||||
|
LOG(("%s(%d)\n", FUNCNAME, state));
|
||||||
m_dtr = state;
|
m_dtr = state;
|
||||||
|
|
||||||
LOG(("Z80SCC \"%s\" Channel %c : %s(%d)\n", m_owner->tag(), 'A' + m_index, __func__, state));
|
|
||||||
if (m_index == z80scc_device::CHANNEL_A)
|
if (m_index == z80scc_device::CHANNEL_A)
|
||||||
m_uart->m_out_dtra_cb(m_dtr);
|
m_uart->m_out_dtra_cb(m_dtr);
|
||||||
else
|
else
|
||||||
@ -2062,7 +2234,6 @@ void z80scc_channel::set_dtr(int state)
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
WRITE_LINE_MEMBER(z80scc_channel::write_rx)
|
WRITE_LINE_MEMBER(z80scc_channel::write_rx)
|
||||||
{
|
{
|
||||||
// printf("%c", state ? '+' : 'o');
|
|
||||||
m_rxd = state;
|
m_rxd = state;
|
||||||
//only use rx_w when self-clocked
|
//only use rx_w when self-clocked
|
||||||
if(m_rxc)
|
if(m_rxc)
|
||||||
|
@ -108,7 +108,9 @@
|
|||||||
|
|
||||||
class z80scc_device;
|
class z80scc_device;
|
||||||
|
|
||||||
class z80scc_channel : public z80sio_channel
|
//class z80scc_channel : public z80sio_channel
|
||||||
|
class z80scc_channel : public device_t,
|
||||||
|
public device_serial_interface
|
||||||
{
|
{
|
||||||
friend class z80scc_device;
|
friend class z80scc_device;
|
||||||
|
|
||||||
@ -146,6 +148,7 @@ public:
|
|||||||
|
|
||||||
// write register handlers
|
// write register handlers
|
||||||
void do_sccreg_wr0(UINT8 data);
|
void do_sccreg_wr0(UINT8 data);
|
||||||
|
void do_sccreg_wr0_resets(UINT8 data);
|
||||||
void do_sccreg_wr1(UINT8 data);
|
void do_sccreg_wr1(UINT8 data);
|
||||||
void do_sccreg_wr2(UINT8 data);
|
void do_sccreg_wr2(UINT8 data);
|
||||||
void do_sccreg_wr3(UINT8 data);
|
void do_sccreg_wr3(UINT8 data);
|
||||||
@ -185,11 +188,9 @@ public:
|
|||||||
|
|
||||||
// Register state
|
// Register state
|
||||||
// read registers enum
|
// read registers enum
|
||||||
#if 0 //defined by z80sio.h
|
|
||||||
UINT8 m_rr0; // REG_RR0_STATUS
|
UINT8 m_rr0; // REG_RR0_STATUS
|
||||||
UINT8 m_rr1; // REG_RR1_SPEC_RCV_COND
|
UINT8 m_rr1; // REG_RR1_SPEC_RCV_COND
|
||||||
UINT8 m_rr2; // REG_RR2_INTERRUPT_VECT
|
UINT8 m_rr2; // REG_RR2_INTERRUPT_VECT
|
||||||
#endif
|
|
||||||
UINT8 m_rr3; // REG_RR3_INTERUPPT_PEND
|
UINT8 m_rr3; // REG_RR3_INTERUPPT_PEND
|
||||||
UINT8 m_rr4; // REG_RR4_WR4_OR_RR0
|
UINT8 m_rr4; // REG_RR4_WR4_OR_RR0
|
||||||
UINT8 m_rr5; // REG_RR5_WR5_OR_RR0
|
UINT8 m_rr5; // REG_RR5_WR5_OR_RR0
|
||||||
@ -205,7 +206,6 @@ public:
|
|||||||
UINT8 m_rr15; // REG_RR15_WR15_EXT_STAT
|
UINT8 m_rr15; // REG_RR15_WR15_EXT_STAT
|
||||||
|
|
||||||
// write registers enum
|
// write registers enum
|
||||||
#if 0 //defined by z80sio.h
|
|
||||||
UINT8 m_wr0; // REG_WR0_COMMAND_REGPT
|
UINT8 m_wr0; // REG_WR0_COMMAND_REGPT
|
||||||
UINT8 m_wr1; // REG_WR1_INT_DMA_ENABLE
|
UINT8 m_wr1; // REG_WR1_INT_DMA_ENABLE
|
||||||
UINT8 m_wr2; // REG_WR2_INT_VECTOR
|
UINT8 m_wr2; // REG_WR2_INT_VECTOR
|
||||||
@ -214,7 +214,6 @@ public:
|
|||||||
UINT8 m_wr5; // REG_WR5_TX_CONTROL
|
UINT8 m_wr5; // REG_WR5_TX_CONTROL
|
||||||
UINT8 m_wr6; // REG_WR6_SYNC_OR_SDLC_A
|
UINT8 m_wr6; // REG_WR6_SYNC_OR_SDLC_A
|
||||||
UINT8 m_wr7; // REG_WR7_SYNC_OR_SDLC_F
|
UINT8 m_wr7; // REG_WR7_SYNC_OR_SDLC_F
|
||||||
#endif
|
|
||||||
UINT8 m_wr8; // REG_WR8_TRANSMIT_DATA
|
UINT8 m_wr8; // REG_WR8_TRANSMIT_DATA
|
||||||
UINT8 m_wr9; // REG_WR9_MASTER_INT_CTRL
|
UINT8 m_wr9; // REG_WR9_MASTER_INT_CTRL
|
||||||
UINT8 m_wr10; // REG_WR10_MSC_RX_TX_CTRL
|
UINT8 m_wr10; // REG_WR10_MSC_RX_TX_CTRL
|
||||||
@ -506,7 +505,7 @@ protected:
|
|||||||
// synchronous state
|
// synchronous state
|
||||||
UINT16 m_sync; // sync character
|
UINT16 m_sync; // sync character
|
||||||
|
|
||||||
// int m_index;
|
int m_index;
|
||||||
z80scc_device *m_uart;
|
z80scc_device *m_uart;
|
||||||
|
|
||||||
// SCC specifics
|
// SCC specifics
|
||||||
@ -557,10 +556,11 @@ public:
|
|||||||
DECLARE_READ8_MEMBER( ba_cd_r );
|
DECLARE_READ8_MEMBER( ba_cd_r );
|
||||||
DECLARE_WRITE8_MEMBER( ba_cd_w );
|
DECLARE_WRITE8_MEMBER( ba_cd_w );
|
||||||
|
|
||||||
DECLARE_READ8_MEMBER( da_r ) { return m_chanA->data_read(); }
|
/* Definitions moved to z80scc.c for enhencements */
|
||||||
DECLARE_WRITE8_MEMBER( da_w ) { m_chanA->data_write(data); }
|
DECLARE_READ8_MEMBER( da_r ); // { return m_chanA->data_read(); }
|
||||||
DECLARE_READ8_MEMBER( db_r ) { return m_chanB->data_read(); }
|
DECLARE_WRITE8_MEMBER( da_w ); // { m_chanA->data_write(data); }
|
||||||
DECLARE_WRITE8_MEMBER( db_w ) { m_chanB->data_write(data); }
|
DECLARE_READ8_MEMBER( db_r ); // { return m_chanB->data_read(); }
|
||||||
|
DECLARE_WRITE8_MEMBER( db_w ); // { m_chanB->data_write(data); }
|
||||||
|
|
||||||
DECLARE_READ8_MEMBER( ca_r ) { return m_chanA->control_read(); }
|
DECLARE_READ8_MEMBER( ca_r ) { return m_chanA->control_read(); }
|
||||||
DECLARE_WRITE8_MEMBER( ca_w ) { m_chanA->control_write(data); }
|
DECLARE_WRITE8_MEMBER( ca_w ) { m_chanA->control_write(data); }
|
||||||
@ -662,6 +662,7 @@ protected:
|
|||||||
int m_int_state[6]; // interrupt state
|
int m_int_state[6]; // interrupt state
|
||||||
|
|
||||||
int m_variant;
|
int m_variant;
|
||||||
|
UINT8 m_wr0_ptrbits;
|
||||||
};
|
};
|
||||||
|
|
||||||
class scc8030_device : public z80scc_device
|
class scc8030_device : public z80scc_device
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
check that an operation is invalid because of package type but relies
|
check that an operation is invalid because of package type but relies
|
||||||
on the software to be adapated for the particular version.
|
on the software to be adapated for the particular version.
|
||||||
|
|
||||||
Package: DIP40 SIO/0, SIO/1, SIO/2,
|
Package: DIP40 SIO/0, SIO/1, SIO/2, SIO/9
|
||||||
QFP44 SIO/3
|
QFP44 SIO/3
|
||||||
PLCC44 SIO/4
|
PLCC44 SIO/4
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
@ -166,7 +166,6 @@ z80sio_device::z80sio_device(const machine_config &mconfig, const char *tag, dev
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// device_start - device-specific startup
|
// device_start - device-specific startup
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void z80sio_device::device_start()
|
void z80sio_device::device_start()
|
||||||
{
|
{
|
||||||
LOG(("%s\n", FUNCNAME));
|
LOG(("%s\n", FUNCNAME));
|
||||||
@ -203,7 +202,6 @@ void z80sio_device::device_start()
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// device_reset - device-specific reset
|
// device_reset - device-specific reset
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void z80sio_device::device_reset()
|
void z80sio_device::device_reset()
|
||||||
{
|
{
|
||||||
LOG(("%s \"%s\" \n", FUNCNAME, tag()));
|
LOG(("%s \"%s\" \n", FUNCNAME, tag()));
|
||||||
@ -215,13 +213,13 @@ void z80sio_device::device_reset()
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// z80daisy_irq_state - get interrupt status
|
// z80daisy_irq_state - get interrupt status
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
int z80sio_device::z80daisy_irq_state()
|
int z80sio_device::z80daisy_irq_state()
|
||||||
{
|
{
|
||||||
int state = 0;
|
int state = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
LOG(("Z80SIO \"%s\" : Interrupt State A:%d%d%d%d B:%d%d%d%d\n", tag(),
|
|
||||||
|
LOG(("%s %s A:%d%d%d%d B:%d%d%d%d ",FUNCNAME, tag(),
|
||||||
m_int_state[0], m_int_state[1], m_int_state[2], m_int_state[3],
|
m_int_state[0], m_int_state[1], m_int_state[2], m_int_state[3],
|
||||||
m_int_state[4], m_int_state[5], m_int_state[6], m_int_state[7]));
|
m_int_state[4], m_int_state[5], m_int_state[6], m_int_state[7]));
|
||||||
|
|
||||||
@ -237,7 +235,7 @@ int z80sio_device::z80daisy_irq_state()
|
|||||||
state |= m_int_state[i];
|
state |= m_int_state[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(("Z80SIO \"%s\" : Interrupt State %u\n", tag(), state));
|
LOG(("Interrupt State %u\n", state));
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
@ -246,12 +244,11 @@ int z80sio_device::z80daisy_irq_state()
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// z80daisy_irq_ack - interrupt acknowledge
|
// z80daisy_irq_ack - interrupt acknowledge
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
int z80sio_device::z80daisy_irq_ack()
|
int z80sio_device::z80daisy_irq_ack()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
LOG(("Z80SIO \"%s\" Interrupt Acknowledge\n", tag()));
|
LOG(("%s %s \n",FUNCNAME, tag()));
|
||||||
|
|
||||||
// loop over all interrupt sources
|
// loop over all interrupt sources
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
@ -264,7 +261,7 @@ int z80sio_device::z80daisy_irq_ack()
|
|||||||
m_chanA->m_rr0 &= ~z80sio_channel::RR0_INTERRUPT_PENDING;
|
m_chanA->m_rr0 &= ~z80sio_channel::RR0_INTERRUPT_PENDING;
|
||||||
check_interrupts();
|
check_interrupts();
|
||||||
|
|
||||||
LOG(("Z80SIO \"%s\" : Interrupt Acknowledge Vector %02x\n", tag(), m_chanB->m_rr2));
|
//LOG(("%s %s \n",FUNCNAME, tag(), m_chanB->m_rr2));
|
||||||
|
|
||||||
return m_chanB->m_rr2;
|
return m_chanB->m_rr2;
|
||||||
}
|
}
|
||||||
@ -279,12 +276,11 @@ int z80sio_device::z80daisy_irq_ack()
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// z80daisy_irq_reti - return from interrupt
|
// z80daisy_irq_reti - return from interrupt
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void z80sio_device::z80daisy_irq_reti()
|
void z80sio_device::z80daisy_irq_reti()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
LOG(("Z80SIO \"%s\" Return from Interrupt\n", tag()));
|
LOG(("%s %s \n",FUNCNAME, tag()));
|
||||||
|
|
||||||
// loop over all interrupt sources
|
// loop over all interrupt sources
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
@ -306,9 +302,9 @@ void z80sio_device::z80daisy_irq_reti()
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// check_interrupts -
|
// check_interrupts -
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void z80sio_device::check_interrupts()
|
void z80sio_device::check_interrupts()
|
||||||
{
|
{
|
||||||
|
LOG(("%s %s \n",FUNCNAME, tag()));
|
||||||
int state = (z80daisy_irq_state() & Z80_DAISY_INT) ? ASSERT_LINE : CLEAR_LINE;
|
int state = (z80daisy_irq_state() & Z80_DAISY_INT) ? ASSERT_LINE : CLEAR_LINE;
|
||||||
m_out_int_cb(state);
|
m_out_int_cb(state);
|
||||||
}
|
}
|
||||||
@ -317,9 +313,10 @@ void z80sio_device::check_interrupts()
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// reset_interrupts -
|
// reset_interrupts -
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void z80sio_device::reset_interrupts()
|
void z80sio_device::reset_interrupts()
|
||||||
{
|
{
|
||||||
|
LOG(("%s %s \n",FUNCNAME, tag()));
|
||||||
|
// reset internal interrupt sources
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
m_int_state[i] = 0;
|
m_int_state[i] = 0;
|
||||||
@ -332,12 +329,13 @@ void z80sio_device::reset_interrupts()
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// trigger_interrupt - TODO: needs attention for SIO
|
// trigger_interrupt - TODO: needs attention for SIO
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void z80sio_device::trigger_interrupt(int index, int state)
|
void z80sio_device::trigger_interrupt(int index, int state)
|
||||||
{
|
{
|
||||||
UINT8 vector = m_chanB->m_wr2;
|
UINT8 vector = m_chanB->m_wr2;
|
||||||
int priority;
|
int priority;
|
||||||
|
|
||||||
|
LOG(("%s %s \n",FUNCNAME, tag()));
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if((m_variant == TYPE_I8274) || (m_variant == TYPE_UPD7201))
|
if((m_variant == TYPE_I8274) || (m_variant == TYPE_UPD7201))
|
||||||
{
|
{
|
||||||
@ -387,9 +385,6 @@ void z80sio_device::trigger_interrupt(int index, int state)
|
|||||||
vector = (m_chanB->m_wr2 & 0xf1) | (!index << 3) | (state << 1);
|
vector = (m_chanB->m_wr2 & 0xf1) | (!index << 3) | (state << 1);
|
||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
|
|
||||||
LOG(("Z80SIO \"%s\" Channel %c : Interrupt Request %u\n", tag(), 'A' + index, state));
|
|
||||||
|
|
||||||
// update vector register
|
// update vector register
|
||||||
m_chanB->m_rr2 = vector;
|
m_chanB->m_rr2 = vector;
|
||||||
|
|
||||||
@ -405,9 +400,9 @@ void z80sio_device::trigger_interrupt(int index, int state)
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// m1_r - interrupt acknowledge
|
// m1_r - interrupt acknowledge
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
int z80sio_device::m1_r()
|
int z80sio_device::m1_r()
|
||||||
{
|
{
|
||||||
|
LOG(("%s %s \n",FUNCNAME, tag()));
|
||||||
return z80daisy_irq_ack();
|
return z80daisy_irq_ack();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,14 +410,13 @@ int z80sio_device::m1_r()
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// cd_ba_r -
|
// cd_ba_r -
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
READ8_MEMBER( z80sio_device::cd_ba_r )
|
READ8_MEMBER( z80sio_device::cd_ba_r )
|
||||||
{
|
{
|
||||||
int ba = BIT(offset, 0);
|
int ba = BIT(offset, 0);
|
||||||
int cd = BIT(offset, 1);
|
int cd = BIT(offset, 1);
|
||||||
z80sio_channel *channel = ba ? m_chanB : m_chanA;
|
z80sio_channel *channel = ba ? m_chanB : m_chanA;
|
||||||
|
|
||||||
// LOG(("z80sio_device::cd_ba_r ba:%02x cd:%02x\n", ba, cd));
|
//LOG(("%s %s %c %s read\n",FUNCNAME, tag(), 'A' + ba ? 1 : 0 , cd ? "control" : "data" ));
|
||||||
|
|
||||||
return cd ? channel->control_read() : channel->data_read();
|
return cd ? channel->control_read() : channel->data_read();
|
||||||
}
|
}
|
||||||
@ -431,14 +425,13 @@ READ8_MEMBER( z80sio_device::cd_ba_r )
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// cd_ba_w -
|
// cd_ba_w -
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
WRITE8_MEMBER( z80sio_device::cd_ba_w )
|
WRITE8_MEMBER( z80sio_device::cd_ba_w )
|
||||||
{
|
{
|
||||||
int ba = BIT(offset, 0);
|
int ba = BIT(offset, 0);
|
||||||
int cd = BIT(offset, 1);
|
int cd = BIT(offset, 1);
|
||||||
z80sio_channel *channel = ba ? m_chanB : m_chanA;
|
z80sio_channel *channel = ba ? m_chanB : m_chanA;
|
||||||
|
|
||||||
LOG(("z80sio_device::cd_ba_w ba:%02x cd:%02x\n", ba, cd));
|
LOG(("%s %s %c %s write\n",FUNCNAME, tag(), 'A' + ba ? 1 : 0 , cd ? "control" : "data" ));
|
||||||
|
|
||||||
if (cd)
|
if (cd)
|
||||||
channel->control_write(data);
|
channel->control_write(data);
|
||||||
@ -450,14 +443,13 @@ WRITE8_MEMBER( z80sio_device::cd_ba_w )
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// ba_cd_r -
|
// ba_cd_r -
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
READ8_MEMBER( z80sio_device::ba_cd_r )
|
READ8_MEMBER( z80sio_device::ba_cd_r )
|
||||||
{
|
{
|
||||||
int ba = BIT(offset, 1);
|
int ba = BIT(offset, 1);
|
||||||
int cd = BIT(offset, 0);
|
int cd = BIT(offset, 0);
|
||||||
z80sio_channel *channel = ba ? m_chanB : m_chanA;
|
z80sio_channel *channel = ba ? m_chanB : m_chanA;
|
||||||
|
|
||||||
// LOG(("z80sio_device::ba_cd_r ba:%02x cd:%02x\n", ba, cd));
|
//LOG(("%s %s %c %s read\n",FUNCNAME, tag(), 'A' + ba ? 1 : 0 , cd ? "control" : "data" ));
|
||||||
|
|
||||||
return cd ? channel->control_read() : channel->data_read();
|
return cd ? channel->control_read() : channel->data_read();
|
||||||
}
|
}
|
||||||
@ -466,14 +458,13 @@ READ8_MEMBER( z80sio_device::ba_cd_r )
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// ba_cd_w -
|
// ba_cd_w -
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
WRITE8_MEMBER( z80sio_device::ba_cd_w )
|
WRITE8_MEMBER( z80sio_device::ba_cd_w )
|
||||||
{
|
{
|
||||||
int ba = BIT(offset, 1);
|
int ba = BIT(offset, 1);
|
||||||
int cd = BIT(offset, 0);
|
int cd = BIT(offset, 0);
|
||||||
z80sio_channel *channel = ba ? m_chanB : m_chanA;
|
z80sio_channel *channel = ba ? m_chanB : m_chanA;
|
||||||
|
|
||||||
LOG(("z80sio_device::ba_cd_w ba:%02x cd:%02x\n", ba, cd));
|
LOG(("%s %s %c %s write\n",FUNCNAME, tag(), 'A' + ba ? 1 : 0 , cd ? "control" : "data" ));
|
||||||
|
|
||||||
if (cd)
|
if (cd)
|
||||||
channel->control_write(data);
|
channel->control_write(data);
|
||||||
@ -488,7 +479,6 @@ WRITE8_MEMBER( z80sio_device::ba_cd_w )
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// z80sio_channel - constructor
|
// z80sio_channel - constructor
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
z80sio_channel::z80sio_channel(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
z80sio_channel::z80sio_channel(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||||
: device_t(mconfig, Z80SIO_CHANNEL, "Z80 SIO channel", tag, owner, clock, "z80sio_channel", __FILE__),
|
: device_t(mconfig, Z80SIO_CHANNEL, "Z80 SIO channel", tag, owner, clock, "z80sio_channel", __FILE__),
|
||||||
device_serial_interface(mconfig, *this),
|
device_serial_interface(mconfig, *this),
|
||||||
@ -508,6 +498,7 @@ z80sio_channel::z80sio_channel(const machine_config &mconfig, const char *tag, d
|
|||||||
m_rts(0),
|
m_rts(0),
|
||||||
m_sync(0)
|
m_sync(0)
|
||||||
{
|
{
|
||||||
|
LOG(("%s\n",FUNCNAME));
|
||||||
// Reset all registers
|
// Reset all registers
|
||||||
m_rr0 = m_rr1 = m_rr2 = 0;
|
m_rr0 = m_rr1 = m_rr2 = 0;
|
||||||
m_wr0 = m_wr1 = m_wr2 = m_wr3 = m_wr4 = m_wr5 = m_wr6 = m_wr7 = 0;
|
m_wr0 = m_wr1 = m_wr2 = m_wr3 = m_wr4 = m_wr5 = m_wr6 = m_wr7 = 0;
|
||||||
@ -523,12 +514,12 @@ z80sio_channel::z80sio_channel(const machine_config &mconfig, const char *tag, d
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// start - channel startup
|
// start - channel startup
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void z80sio_channel::device_start()
|
void z80sio_channel::device_start()
|
||||||
{
|
{
|
||||||
LOG(("%s\n",FUNCNAME));
|
LOG(("%s\n",FUNCNAME));
|
||||||
m_uart = downcast<z80sio_device *>(owner());
|
m_uart = downcast<z80sio_device *>(owner());
|
||||||
m_index = m_uart->get_channel_index(this);
|
m_index = m_uart->get_channel_index(this);
|
||||||
|
m_variant = ((z80sio_device *)m_owner)->m_variant;
|
||||||
|
|
||||||
// state saving
|
// state saving
|
||||||
save_item(NAME(m_rr0));
|
save_item(NAME(m_rr0));
|
||||||
@ -558,6 +549,7 @@ void z80sio_channel::device_start()
|
|||||||
save_item(NAME(m_dtr));
|
save_item(NAME(m_dtr));
|
||||||
save_item(NAME(m_rts));
|
save_item(NAME(m_rts));
|
||||||
save_item(NAME(m_sync));
|
save_item(NAME(m_sync));
|
||||||
|
save_item(NAME(m_variant));
|
||||||
device_serial_interface::register_save_state(machine().save(), this);
|
device_serial_interface::register_save_state(machine().save(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -565,10 +557,11 @@ void z80sio_channel::device_start()
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// reset - reset channel status
|
// reset - reset channel status
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void z80sio_channel::device_reset()
|
void z80sio_channel::device_reset()
|
||||||
{
|
{
|
||||||
LOG(("%s\n", FUNCNAME));
|
LOG(("%s\n", FUNCNAME));
|
||||||
|
|
||||||
|
// Reset RS232 emulation
|
||||||
receive_register_reset();
|
receive_register_reset();
|
||||||
transmit_register_reset();
|
transmit_register_reset();
|
||||||
|
|
||||||
@ -596,15 +589,14 @@ void z80sio_channel::device_timer(emu_timer &timer, device_timer_id id, int para
|
|||||||
device_serial_interface::device_timer(timer, id, param, ptr);
|
device_serial_interface::device_timer(timer, id, param, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// tra_callback -
|
// tra_callback -
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void z80sio_channel::tra_callback()
|
void z80sio_channel::tra_callback()
|
||||||
{
|
{
|
||||||
if (!(m_wr5 & WR5_TX_ENABLE))
|
if (!(m_wr5 & WR5_TX_ENABLE))
|
||||||
{
|
{
|
||||||
|
LOG(("%" I64FMT "d %s() \"%s \"Channel %c transmit mark 1 m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5));
|
||||||
// transmit mark
|
// transmit mark
|
||||||
if (m_index == z80sio_device::CHANNEL_A)
|
if (m_index == z80sio_device::CHANNEL_A)
|
||||||
m_uart->m_out_txda_cb(1);
|
m_uart->m_out_txda_cb(1);
|
||||||
@ -613,6 +605,7 @@ void z80sio_channel::tra_callback()
|
|||||||
}
|
}
|
||||||
else if (m_wr5 & WR5_SEND_BREAK)
|
else if (m_wr5 & WR5_SEND_BREAK)
|
||||||
{
|
{
|
||||||
|
LOG(("%" I64FMT "d %s() \"%s \"Channel %c send break 1 m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5));
|
||||||
// transmit break
|
// transmit break
|
||||||
if (m_index == z80sio_device::CHANNEL_A)
|
if (m_index == z80sio_device::CHANNEL_A)
|
||||||
m_uart->m_out_txda_cb(0);
|
m_uart->m_out_txda_cb(0);
|
||||||
@ -621,11 +614,19 @@ void z80sio_channel::tra_callback()
|
|||||||
}
|
}
|
||||||
else if (!is_transmit_register_empty())
|
else if (!is_transmit_register_empty())
|
||||||
{
|
{
|
||||||
|
int db = transmit_register_get_data_bit();
|
||||||
|
|
||||||
|
LOG(("%" I64FMT "d %s() \"%s \"Channel %c transmit data bit %d m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, db, m_wr5));
|
||||||
// transmit data
|
// transmit data
|
||||||
if (m_index == z80sio_device::CHANNEL_A)
|
if (m_index == z80sio_device::CHANNEL_A)
|
||||||
m_uart->m_out_txda_cb(transmit_register_get_data_bit());
|
m_uart->m_out_txda_cb(db);
|
||||||
else
|
else
|
||||||
m_uart->m_out_txdb_cb(transmit_register_get_data_bit());
|
m_uart->m_out_txdb_cb(db);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG(("%" I64FMT "d %s() \"%s \"Channel %c Failed to transmit m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5));
|
||||||
|
logerror("%s \"%s \"Channel %c Failed to transmit\n", FUNCNAME, m_owner->tag(), 'A' + m_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -633,12 +634,12 @@ void z80sio_channel::tra_callback()
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// tra_complete -
|
// tra_complete -
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void z80sio_channel::tra_complete()
|
void z80sio_channel::tra_complete()
|
||||||
{
|
{
|
||||||
|
LOG(("%s %s\n",FUNCNAME, tag()));
|
||||||
if ((m_wr5 & WR5_TX_ENABLE) && !(m_wr5 & WR5_SEND_BREAK) && !(m_rr0 & RR0_TX_BUFFER_EMPTY))
|
if ((m_wr5 & WR5_TX_ENABLE) && !(m_wr5 & WR5_SEND_BREAK) && !(m_rr0 & RR0_TX_BUFFER_EMPTY))
|
||||||
{
|
{
|
||||||
LOG(("Z80SIO \"%s\" Channel %c : Transmit Data Byte '%02x'\n", m_owner->tag(), 'A' + m_index, m_tx_data));
|
LOG(("%" I64FMT "d %s() \"%s \"Channel %c Transmit Data Byte '%02x' m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_tx_data, m_wr5));
|
||||||
|
|
||||||
transmit_register_setup(m_tx_data);
|
transmit_register_setup(m_tx_data);
|
||||||
|
|
||||||
@ -650,6 +651,7 @@ void z80sio_channel::tra_complete()
|
|||||||
}
|
}
|
||||||
else if (m_wr5 & WR5_SEND_BREAK)
|
else if (m_wr5 & WR5_SEND_BREAK)
|
||||||
{
|
{
|
||||||
|
LOG(("%" I64FMT "d %s() \"%s \"Channel %c Transmit Break 0 m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5));
|
||||||
// transmit break
|
// transmit break
|
||||||
if (m_index == z80sio_device::CHANNEL_A)
|
if (m_index == z80sio_device::CHANNEL_A)
|
||||||
m_uart->m_out_txda_cb(0);
|
m_uart->m_out_txda_cb(0);
|
||||||
@ -658,6 +660,7 @@ void z80sio_channel::tra_complete()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
LOG(("%" I64FMT "d %s() \"%s \"Channel %c Transmit Mark 1 m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5));
|
||||||
// transmit mark
|
// transmit mark
|
||||||
if (m_index == z80sio_device::CHANNEL_A)
|
if (m_index == z80sio_device::CHANNEL_A)
|
||||||
m_uart->m_out_txda_cb(1);
|
m_uart->m_out_txda_cb(1);
|
||||||
@ -668,6 +671,7 @@ void z80sio_channel::tra_complete()
|
|||||||
// if transmit buffer is empty
|
// if transmit buffer is empty
|
||||||
if (m_rr0 & RR0_TX_BUFFER_EMPTY)
|
if (m_rr0 & RR0_TX_BUFFER_EMPTY)
|
||||||
{
|
{
|
||||||
|
LOG(("%" I64FMT "d %s() \"%s \"Channel %c Transmit buffer empty m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5));
|
||||||
// then all characters have been sent
|
// then all characters have been sent
|
||||||
m_rr1 |= RR1_ALL_SENT;
|
m_rr1 |= RR1_ALL_SENT;
|
||||||
|
|
||||||
@ -681,24 +685,34 @@ void z80sio_channel::tra_complete()
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// rcv_callback -
|
// rcv_callback -
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void z80sio_channel::rcv_callback()
|
void z80sio_channel::rcv_callback()
|
||||||
{
|
{
|
||||||
if (m_wr3 & WR3_RX_ENABLE)
|
if (m_wr3 & WR3_RX_ENABLE)
|
||||||
{
|
{
|
||||||
|
LOG(("%" I64FMT "d %s() \"%s \"Channel %c Received Data Bit %d\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_rxd));
|
||||||
receive_register_update_bit(m_rxd);
|
receive_register_update_bit(m_rxd);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG(("%" I64FMT "d %s() \"%s \"Channel %c Received Data Bit but receiver is disabled\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index));
|
||||||
|
logerror("Z80SIO %s() \"%s \"Channel %c Received data dit but receiver is disabled\n", __func__, m_owner->tag(), 'A' + m_index);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// rcv_complete -
|
// rcv_complete -
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void z80sio_channel::rcv_complete()
|
void z80sio_channel::rcv_complete()
|
||||||
{
|
{
|
||||||
|
UINT8 data;
|
||||||
|
|
||||||
receive_register_extract();
|
receive_register_extract();
|
||||||
receive_data(get_received_char());
|
data = get_received_char();
|
||||||
|
LOG(("%" I64FMT "d %s() \"%s \"Channel %c Received Data %02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, data));
|
||||||
|
receive_data(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -708,6 +722,7 @@ void z80sio_channel::rcv_complete()
|
|||||||
|
|
||||||
int z80sio_channel::get_clock_mode()
|
int z80sio_channel::get_clock_mode()
|
||||||
{
|
{
|
||||||
|
LOG(("%s %s\n",FUNCNAME, tag()));
|
||||||
int clocks = 1;
|
int clocks = 1;
|
||||||
|
|
||||||
switch (m_wr4 & WR4_CLOCK_RATE_MASK)
|
switch (m_wr4 & WR4_CLOCK_RATE_MASK)
|
||||||
@ -734,6 +749,7 @@ CR5 = m_wr5 and SR1 = m_rr1
|
|||||||
|
|
||||||
void z80sio_channel::set_rts(int state)
|
void z80sio_channel::set_rts(int state)
|
||||||
{
|
{
|
||||||
|
LOG(("%s(%d) \"%s\" Channel %c \n", FUNCNAME, state, m_owner->tag(), 'A' + m_index));
|
||||||
if (m_index == z80sio_device::CHANNEL_A)
|
if (m_index == z80sio_device::CHANNEL_A)
|
||||||
m_uart->m_out_rtsa_cb(state);
|
m_uart->m_out_rtsa_cb(state);
|
||||||
else
|
else
|
||||||
@ -742,6 +758,8 @@ void z80sio_channel::set_rts(int state)
|
|||||||
|
|
||||||
void z80sio_channel::update_rts()
|
void z80sio_channel::update_rts()
|
||||||
{
|
{
|
||||||
|
// LOG(("%s(%d) \"%s\" Channel %c \n", FUNCNAME, state, m_owner->tag(), 'A' + m_index));
|
||||||
|
LOG(("%s() \"%s\" Channel %c \n", FUNCNAME, m_owner->tag(), 'A' + m_index));
|
||||||
if (m_wr5 & WR5_RTS)
|
if (m_wr5 & WR5_RTS)
|
||||||
{
|
{
|
||||||
// when the RTS bit is set, the _RTS output goes low
|
// when the RTS bit is set, the _RTS output goes low
|
||||||
@ -764,6 +782,7 @@ void z80sio_channel::update_rts()
|
|||||||
|
|
||||||
device_serial_interface::stop_bits_t z80sio_channel::get_stop_bits()
|
device_serial_interface::stop_bits_t z80sio_channel::get_stop_bits()
|
||||||
{
|
{
|
||||||
|
LOG(("%s %s\n",FUNCNAME, tag()));
|
||||||
switch (m_wr4 & WR4_STOP_BITS_MASK)
|
switch (m_wr4 & WR4_STOP_BITS_MASK)
|
||||||
{
|
{
|
||||||
case WR4_STOP_BITS_1: return STOP_BITS_1;
|
case WR4_STOP_BITS_1: return STOP_BITS_1;
|
||||||
@ -781,6 +800,7 @@ device_serial_interface::stop_bits_t z80sio_channel::get_stop_bits()
|
|||||||
|
|
||||||
int z80sio_channel::get_rx_word_length()
|
int z80sio_channel::get_rx_word_length()
|
||||||
{
|
{
|
||||||
|
LOG(("%s %s\n",FUNCNAME, tag()));
|
||||||
int bits = 5;
|
int bits = 5;
|
||||||
|
|
||||||
switch (m_wr3 & WR3_RX_WORD_LENGTH_MASK)
|
switch (m_wr3 & WR3_RX_WORD_LENGTH_MASK)
|
||||||
@ -801,6 +821,7 @@ int z80sio_channel::get_rx_word_length()
|
|||||||
|
|
||||||
int z80sio_channel::get_tx_word_length()
|
int z80sio_channel::get_tx_word_length()
|
||||||
{
|
{
|
||||||
|
LOG(("%s %s\n",FUNCNAME, tag()));
|
||||||
int bits = 5;
|
int bits = 5;
|
||||||
|
|
||||||
switch (m_wr5 & WR5_TX_WORD_LENGTH_MASK)
|
switch (m_wr5 & WR5_TX_WORD_LENGTH_MASK)
|
||||||
@ -820,6 +841,7 @@ int z80sio_channel::get_tx_word_length()
|
|||||||
* Break/Abort latch. */
|
* Break/Abort latch. */
|
||||||
UINT8 z80sio_channel::do_sioreg_rr0()
|
UINT8 z80sio_channel::do_sioreg_rr0()
|
||||||
{
|
{
|
||||||
|
LOG(("%s %s\n",FUNCNAME, tag()));
|
||||||
return m_rr0;
|
return m_rr0;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -827,6 +849,7 @@ UINT8 z80sio_channel::do_sioreg_rr0()
|
|||||||
* codes for the I-Field in the SDLC Receive Mode. */
|
* codes for the I-Field in the SDLC Receive Mode. */
|
||||||
UINT8 z80sio_channel::do_sioreg_rr1()
|
UINT8 z80sio_channel::do_sioreg_rr1()
|
||||||
{
|
{
|
||||||
|
LOG(("%s %s\n",FUNCNAME, tag()));
|
||||||
return m_rr1;
|
return m_rr1;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -839,6 +862,7 @@ no interrupts are pending, the vector is modified with V3 = 0, V2 = 1, and
|
|||||||
V1 = 1. This register is read only through Channel B. */
|
V1 = 1. This register is read only through Channel B. */
|
||||||
UINT8 z80sio_channel::do_sioreg_rr2()
|
UINT8 z80sio_channel::do_sioreg_rr2()
|
||||||
{
|
{
|
||||||
|
LOG(("%s %s\n",FUNCNAME, tag()));
|
||||||
// channel B only
|
// channel B only
|
||||||
return m_index == z80sio_device::CHANNEL_B ? m_rr2 : 0;
|
return m_index == z80sio_device::CHANNEL_B ? m_rr2 : 0;
|
||||||
}
|
}
|
||||||
@ -853,6 +877,7 @@ UINT8 z80sio_channel::control_read()
|
|||||||
UINT8 data = 0;
|
UINT8 data = 0;
|
||||||
UINT8 reg = m_wr0 & WR0_REGISTER_MASK;
|
UINT8 reg = m_wr0 & WR0_REGISTER_MASK;
|
||||||
|
|
||||||
|
//LOG(("%s %s\n",FUNCNAME, tag()));
|
||||||
if (reg != 0)
|
if (reg != 0)
|
||||||
{
|
{
|
||||||
// mask out register index
|
// mask out register index
|
||||||
@ -866,16 +891,17 @@ UINT8 z80sio_channel::control_read()
|
|||||||
case REG_RR2_INTERRUPT_VECT: data = do_sioreg_rr2(); break;
|
case REG_RR2_INTERRUPT_VECT: data = do_sioreg_rr2(); break;
|
||||||
default:
|
default:
|
||||||
logerror("Z80SIO \"%s\" Channel %c : Unsupported RRx register:%02x\n", m_owner->tag(), 'A' + m_index, reg);
|
logerror("Z80SIO \"%s\" Channel %c : Unsupported RRx register:%02x\n", m_owner->tag(), 'A' + m_index, reg);
|
||||||
|
LOG(("%s %s unsupported register:%02x\n",FUNCNAME, tag(), reg));
|
||||||
}
|
}
|
||||||
//LOG(("Z80SIO \"%s\" Channel %c : Register R%d read '%02x'\n", m_owner->tag(), 'A' + m_index, reg, data));
|
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SIO CRC Initialization Code handling
|
/* SIO CRC Initialization Code handling - candidate for breaking out in a z80sio_base class
|
||||||
Handle the WR0 CRC Reset/Init bits separatelly, needed by derived devices separatelly from the commands */
|
Handle the WR0 CRC Reset/Init bits separatelly, needed by derived devices separatelly from the commands */
|
||||||
void z80sio_channel::do_sioreg_wr0_resets(UINT8 data)
|
void z80sio_channel::do_sioreg_wr0_resets(UINT8 data)
|
||||||
{
|
{
|
||||||
|
LOG(("%s %s\n",FUNCNAME, tag()));
|
||||||
switch (data & WR0_CRC_RESET_CODE_MASK)
|
switch (data & WR0_CRC_RESET_CODE_MASK)
|
||||||
{
|
{
|
||||||
case WR0_CRC_RESET_NULL:
|
case WR0_CRC_RESET_NULL:
|
||||||
@ -894,6 +920,7 @@ void z80sio_channel::do_sioreg_wr0_resets(UINT8 data)
|
|||||||
logerror("Z80SIO \"%s\" Channel %c : %s Wrong CRC reset/init command:%02x\n", m_owner->tag(), 'A' + m_index, FUNCNAME, data & WR0_CRC_RESET_CODE_MASK);
|
logerror("Z80SIO \"%s\" Channel %c : %s Wrong CRC reset/init command:%02x\n", m_owner->tag(), 'A' + m_index, FUNCNAME, data & WR0_CRC_RESET_CODE_MASK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void z80sio_channel::do_sioreg_wr0(UINT8 data)
|
void z80sio_channel::do_sioreg_wr0(UINT8 data)
|
||||||
{
|
{
|
||||||
m_wr0 = data;
|
m_wr0 = data;
|
||||||
@ -1033,7 +1060,6 @@ void z80sio_channel::do_sioreg_wr7(UINT8 data)
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// control_write - write control register
|
// control_write - write control register
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void z80sio_channel::control_write(UINT8 data)
|
void z80sio_channel::control_write(UINT8 data)
|
||||||
{
|
{
|
||||||
UINT8 reg = m_wr0 & WR0_REGISTER_MASK;
|
UINT8 reg = m_wr0 & WR0_REGISTER_MASK;
|
||||||
@ -1044,7 +1070,7 @@ void z80sio_channel::control_write(UINT8 data)
|
|||||||
m_wr0 &= ~WR0_REGISTER_MASK;
|
m_wr0 &= ~WR0_REGISTER_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(("Z80SIO control_write reg %02x, regmask %02x, WR0 %02x, data %02x\n", reg, WR0_REGISTER_MASK, m_wr0, data));
|
LOG(("\n%s(%02x) reg %02x\n", FUNCNAME, data, reg));
|
||||||
|
|
||||||
switch (reg)
|
switch (reg)
|
||||||
{
|
{
|
||||||
@ -1065,7 +1091,6 @@ void z80sio_channel::control_write(UINT8 data)
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// data_read - read data register
|
// data_read - read data register
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
UINT8 z80sio_channel::data_read()
|
UINT8 z80sio_channel::data_read()
|
||||||
{
|
{
|
||||||
UINT8 data = 0;
|
UINT8 data = 0;
|
||||||
@ -1097,7 +1122,6 @@ UINT8 z80sio_channel::data_read()
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// data_write - write data register
|
// data_write - write data register
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void z80sio_channel::data_write(UINT8 data)
|
void z80sio_channel::data_write(UINT8 data)
|
||||||
{
|
{
|
||||||
m_tx_data = data;
|
m_tx_data = data;
|
||||||
@ -1116,25 +1140,24 @@ void z80sio_channel::data_write(UINT8 data)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
LOG((" Transmitter %s, data byte dropped\n", m_wr5 & WR5_TX_ENABLE ? "not enabled" : "not emptied"));
|
||||||
m_rr0 &= ~RR0_TX_BUFFER_EMPTY;
|
m_rr0 &= ~RR0_TX_BUFFER_EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_rr1 &= ~RR1_ALL_SENT;
|
m_rr1 &= ~RR1_ALL_SENT;
|
||||||
|
|
||||||
LOG(("Z80SIO \"%s\" Channel %c : Data Register Write '%02x'\n", m_owner->tag(), 'A' + m_index, data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// receive_data - receive data word
|
// receive_data - receive data word
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void z80sio_channel::receive_data(UINT8 data)
|
void z80sio_channel::receive_data(UINT8 data)
|
||||||
{
|
{
|
||||||
LOG(("Z80SIO \"%s\" Channel %c : Receive Data Byte '%02x'\n", m_owner->tag(), 'A' + m_index, data));
|
LOG(("%s(%02x) %s:%c\n",FUNCNAME, data, tag(), 'A' + m_index));
|
||||||
|
|
||||||
if (m_rx_fifo == 2)
|
if (m_rx_fifo == 2)
|
||||||
{
|
{
|
||||||
|
LOG((" Overrun detected\n"));
|
||||||
// receive overrun error detected
|
// receive overrun error detected
|
||||||
m_rx_error |= RR1_RX_OVERRUN_ERROR;
|
m_rx_error |= RR1_RX_OVERRUN_ERROR;
|
||||||
|
|
||||||
@ -1171,7 +1194,6 @@ void z80sio_channel::receive_data(UINT8 data)
|
|||||||
if (m_rx_first)
|
if (m_rx_first)
|
||||||
{
|
{
|
||||||
m_uart->trigger_interrupt(m_index, INT_RECEIVE);
|
m_uart->trigger_interrupt(m_index, INT_RECEIVE);
|
||||||
|
|
||||||
m_rx_first = 0;
|
m_rx_first = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1180,6 +1202,9 @@ void z80sio_channel::receive_data(UINT8 data)
|
|||||||
case WR1_RX_INT_ALL:
|
case WR1_RX_INT_ALL:
|
||||||
m_uart->trigger_interrupt(m_index, INT_RECEIVE);
|
m_uart->trigger_interrupt(m_index, INT_RECEIVE);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
LOG(("No interrupt triggered\n"));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1190,7 +1215,7 @@ void z80sio_channel::receive_data(UINT8 data)
|
|||||||
|
|
||||||
WRITE_LINE_MEMBER( z80sio_channel::cts_w )
|
WRITE_LINE_MEMBER( z80sio_channel::cts_w )
|
||||||
{
|
{
|
||||||
LOG(("Z80SIO \"%s\" Channel %c : CTS %u\n", m_owner->tag(), 'A' + m_index, state));
|
LOG(("%s(%02x) %s:%c\n",FUNCNAME, state, tag(), 'A' + m_index));
|
||||||
|
|
||||||
if (m_cts != state)
|
if (m_cts != state)
|
||||||
{
|
{
|
||||||
@ -1382,6 +1407,7 @@ void z80sio_channel::update_serial()
|
|||||||
|
|
||||||
void z80sio_channel::set_dtr(int state)
|
void z80sio_channel::set_dtr(int state)
|
||||||
{
|
{
|
||||||
|
LOG(("%s(%d)\n", FUNCNAME, state));
|
||||||
m_dtr = state;
|
m_dtr = state;
|
||||||
|
|
||||||
if (m_index == z80sio_device::CHANNEL_A)
|
if (m_index == z80sio_device::CHANNEL_A)
|
||||||
|
@ -523,7 +523,6 @@ protected:
|
|||||||
devcb_write_line m_out_txdrqb_cb;
|
devcb_write_line m_out_txdrqb_cb;
|
||||||
|
|
||||||
int m_int_state[8]; // interrupt state
|
int m_int_state[8]; // interrupt state
|
||||||
|
|
||||||
int m_variant;
|
int m_variant;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user