Merge pull request #379 from JoakimLarsson/z80scc_m166_3

Z80scc m166 3
This commit is contained in:
R. Belmont 2015-10-13 16:33:22 -04:00
commit 4d9ab25ec8
4 changed files with 1780 additions and 1583 deletions

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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;
}; };