summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author R. Belmont <rb6502@users.noreply.github.com>2015-10-13 16:33:22 -0400
committer R. Belmont <rb6502@users.noreply.github.com>2015-10-13 16:33:22 -0400
commit4d9ab25ec85af9af40dfd3c2c2d32d894a560934 (patch)
tree9fb238ce321e3a29da4822dc41900140f928df60
parente17f57845f59f602a229f4ca260ee367a6c7a68c (diff)
parentc92193a0ec3f4b871d4e87e8ef27b60be22f7aca (diff)
Merge pull request #379 from JoakimLarsson/z80scc_m166_3
Z80scc m166 3
-rw-r--r--src/devices/machine/z80scc.c1705
-rw-r--r--src/devices/machine/z80scc.h635
-rw-r--r--src/devices/machine/z80sio.c678
-rw-r--r--src/devices/machine/z80sio.h353
4 files changed, 1784 insertions, 1587 deletions
diff --git a/src/devices/machine/z80scc.c b/src/devices/machine/z80scc.c
index 62b8c1c87b6..91221c8d339 100644
--- a/src/devices/machine/z80scc.c
+++ b/src/devices/machine/z80scc.c
@@ -1,5 +1,4 @@
-// license:BSD-3-Clause
-// copyright-holders: Joakim Larsson Edstrom
+// license:BSD-3-Clause copyright-holders: Joakim Larsson Edstrom
/***************************************************************************
Z80-SCC Serial Communications Controller emulation
@@ -74,7 +73,7 @@ TODO:
#include "z80scc.h"
//**************************************************************************
-// MACROS / CONSTANTS
+// MACROS / CONSTANTS
//**************************************************************************
#define VERBOSE 0
@@ -90,11 +89,11 @@ TODO:
#define FUNCNAME __PRETTY_FUNCTION__
#endif
-#define CHANA_TAG "cha"
-#define CHANB_TAG "chb"
+#define CHANA_TAG "cha"
+#define CHANB_TAG "chb"
//**************************************************************************
-// DEVICE DEFINITIONS
+// DEVICE DEFINITIONS
//**************************************************************************
// device type definition
const device_type Z80SCC = &device_creator<z80scc_device>;
@@ -109,7 +108,7 @@ const device_type SCC85233 = &device_creator<scc85233_device>;
const device_type SCC8523L = &device_creator<scc8523L_device>;
//-------------------------------------------------
-// device_mconfig_additions -
+// device_mconfig_additions -
//-------------------------------------------------
MACHINE_CONFIG_FRAGMENT( z80scc )
MCFG_DEVICE_ADD(CHANA_TAG, Z80SCC_CHANNEL, 0)
@@ -122,39 +121,39 @@ machine_config_constructor z80scc_device::device_mconfig_additions() const
}
//**************************************************************************
-// LIVE DEVICE
+// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
-// z80scc_device - constructor
+// z80scc_device - constructor
//-------------------------------------------------
z80scc_device::z80scc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT32 variant, const char *shortname, const char *source)
: device_t(mconfig, type, name, tag, owner, clock, shortname, source),
- device_z80daisy_interface(mconfig, *this),
- m_chanA(*this, CHANA_TAG),
- m_chanB(*this, CHANB_TAG),
- m_rxca(0),
- m_txca(0),
- m_rxcb(0),
- m_txcb(0),
- m_out_txda_cb(*this),
- m_out_dtra_cb(*this),
- m_out_rtsa_cb(*this),
- m_out_wrdya_cb(*this),
- m_out_synca_cb(*this),
- m_out_txdb_cb(*this),
- m_out_dtrb_cb(*this),
- m_out_rtsb_cb(*this),
- m_out_wrdyb_cb(*this),
- m_out_syncb_cb(*this),
- m_out_int_cb(*this),
- m_out_rxdrqa_cb(*this),
- m_out_txdrqa_cb(*this),
- m_out_rxdrqb_cb(*this),
- m_out_txdrqb_cb(*this),
- m_variant(variant)
-{
+ device_z80daisy_interface(mconfig, *this),
+ m_chanA(*this, CHANA_TAG),
+ m_chanB(*this, CHANB_TAG),
+ m_rxca(0),
+ m_txca(0),
+ m_rxcb(0),
+ m_txcb(0),
+ m_out_txda_cb(*this),
+ m_out_dtra_cb(*this),
+ m_out_rtsa_cb(*this),
+ m_out_wrdya_cb(*this),
+ m_out_synca_cb(*this),
+ m_out_txdb_cb(*this),
+ m_out_dtrb_cb(*this),
+ m_out_rtsb_cb(*this),
+ m_out_wrdyb_cb(*this),
+ m_out_syncb_cb(*this),
+ m_out_int_cb(*this),
+ m_out_rxdrqa_cb(*this),
+ m_out_txdrqa_cb(*this),
+ m_out_rxdrqb_cb(*this),
+ m_out_txdrqb_cb(*this),
+ m_variant(variant),
+ m_wr0_ptrbits(0){
for (int i = 0; i < 6; i++)
m_int_state[i] = 0;
}
@@ -199,7 +198,7 @@ scc80230_device::scc80230_device(const machine_config &mconfig, const char *tag,
: z80scc_device(mconfig, SCC80230, "SCC 80230", tag, owner, clock, TYPE_SCC80230, "scc80230", __FILE__){ }
scc8530_device::scc8530_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
- : z80scc_device(mconfig, SCC8530N, "SCC 8530", tag, owner, clock, TYPE_SCC8530, "scc8530", __FILE__){ }
+: z80scc_device(mconfig, SCC8530N, "SCC 8530", tag, owner, clock, TYPE_SCC8530, "scc8530", __FILE__){ }
scc85C30_device::scc85C30_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: z80scc_device(mconfig, SCC85C30, "SCC 85C30", tag, owner, clock, TYPE_SCC85C30, "scc85C30", __FILE__){ }
@@ -214,12 +213,12 @@ scc8523L_device::scc8523L_device(const machine_config &mconfig, const char *tag,
: z80scc_device(mconfig, SCC8523L, "SCC 8523L", tag, owner, clock, TYPE_SCC8523L, "scc8523L", __FILE__){ }
//-------------------------------------------------
-// device_start - device-specific startup
+// device_start - device-specific startup
//-------------------------------------------------
void z80scc_device::device_start()
{
- LOG(("%s\n", FUNCNAME));
+ LOG(("%s\n", FUNCNAME));
// resolve callbacks
m_out_txda_cb.resolve_safe();
m_out_dtra_cb.resolve_safe();
@@ -247,16 +246,18 @@ void z80scc_device::device_start()
// state saving
save_item(NAME(m_int_state));
+
+ LOG((" - SCC variant %02x\n", m_variant));
}
//-------------------------------------------------
-// device_reset - device-specific reset
+// device_reset - device-specific reset
//-------------------------------------------------
void z80scc_device::device_reset()
{
- LOG(("%s %s \n",FUNCNAME, tag()));
+ LOG(("%s %s \n",FUNCNAME, tag()));
m_chanA->reset();
m_chanB->reset();
@@ -268,7 +269,7 @@ Each of the SCC's two channels contain three sources of interrupts, making a tot
sources. These three sources of interrupts are: 1) Receiver, 2) Transmitter, and 3) External/Status
conditions. In addition, there are several conditions that may cause these interrupts.*/
//-------------------------------------------------
-// z80daisy_irq_state - get interrupt status
+// z80daisy_irq_state - get interrupt status
//-------------------------------------------------
int z80scc_device::z80daisy_irq_state()
@@ -276,9 +277,9 @@ int z80scc_device::z80daisy_irq_state()
int state = 0;
int i;
- LOG(("Z80SCC \"%s\" : Interrupt State A:%d%d%d%d B:%d%d%d%d\n", tag(),
- 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]));
+ 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[4], m_int_state[5]));
// loop over all interrupt sources
for (i = 0; i < 6; i++)
@@ -292,21 +293,21 @@ int z80scc_device::z80daisy_irq_state()
state |= m_int_state[i];
}
- LOG(("Z80SCC \"%s\" : Interrupt State %u\n", tag(), state));
+ LOG(("Interrupt State %u\n", state));
return state;
}
//-------------------------------------------------
-// z80daisy_irq_ack - interrupt acknowledge
+// z80daisy_irq_ack - interrupt acknowledge
//-------------------------------------------------
int z80scc_device::z80daisy_irq_ack()
{
int i;
- LOG(("Z80SCC \"%s\" Interrupt Acknowledge\n", tag()));
+ LOG(("%s %s - needs fixing for SCC\n",FUNCNAME, tag()));
// loop over all interrupt sources
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
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();
- 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;
}
@@ -332,14 +333,14 @@ int z80scc_device::z80daisy_irq_ack()
//-------------------------------------------------
-// z80daisy_irq_reti - return from interrupt
+// z80daisy_irq_reti - return from interrupt
//-------------------------------------------------
void z80scc_device::z80daisy_irq_reti()
{
int i;
- LOG(("Z80SCC \"%s\" Return from Interrupt\n", tag()));
+ LOG(("%s %s \n",FUNCNAME, tag()));
// loop over all interrupt sources
for (i = 0; i < 6; i++)
@@ -359,30 +360,31 @@ void z80scc_device::z80daisy_irq_reti()
//-------------------------------------------------
-// check_interrupts -
+// check_interrupts -
//-------------------------------------------------
void z80scc_device::check_interrupts()
{
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);
}
//-------------------------------------------------
-// reset_interrupts -
+// 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++)
{
m_int_state[i] = 0;
}
- // check external interrupt sources
+ // check external interrupt sources
check_interrupts();
}
@@ -392,124 +394,126 @@ UINT8 z80scc_device::modify_vector(UINT8 vec, int i, UINT8 src)
Interrupt Vector Modification
V3 V2 V1 Status High/Status Low =0
V4 V5 V6 Status High/Status Low =1
- 0 0 0 Ch B Transmit Buffer Empty
- 0 0 1 Ch B External/Status Change
- 0 1 0 Ch B Receive Char. Available
- 0 1 1 Ch B Special Receive Condition
- 1 0 0 Ch A Transmit Buffer Empty
- 1 0 1 Ch A External/Status Change
- 1 1 0 Ch A Receive Char. Available
- 1 1 1 Ch A Special Receive Condition
+ 0 0 0 Ch B Transmit Buffer Empty
+ 0 0 1 Ch B External/Status Change
+ 0 1 0 Ch B Receive Char. Available
+ 0 1 1 Ch B Special Receive Condition
+ 1 0 0 Ch A Transmit Buffer Empty
+ 1 0 1 Ch A External/Status Change
+ 1 1 0 Ch A Receive Char. Available
+ 1 1 1 Ch A Special Receive Condition
*/
// Add channel offset according to table above
- src |= (i == CHANNEL_A ? 0x04 : 0x00 );
+ src |= (i == CHANNEL_A ? 0x04 : 0x00 );
- // Modify vector according to Hi/lo bit of WR9
- if (m_chanA->m_wr9 & z80scc_channel::WR9_BIT_SHSL) // Affect V4-V6
- {
- vec |= src << 4;
- }
- else // Affect V1-V3
- {
- vec |= src << 1;
- }
- return vec;
+ // Modify vector according to Hi/lo bit of WR9
+ if (m_chanA->m_wr9 & z80scc_channel::WR9_BIT_SHSL) // Affect V4-V6
+ {
+ vec |= src << 4;
+ }
+ else // Affect V1-V3
+ {
+ vec |= src << 1;
+ }
+ return vec;
}
//-------------------------------------------------
-// trigger_interrupt -
+// trigger_interrupt -
//-------------------------------------------------
void z80scc_device::trigger_interrupt(int index, int state)
{
UINT8 vector = m_chanB->m_wr2;
- UINT8 source = 0;
+ UINT8 source = 0;
int priority;
- int prio_level = 0;
+ int prio_level = 0;
- /* 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))
- {
- LOG(("Master Interrupt Enable is not set, blocking attempt to interrupt\n"));
- return;
- }
+ LOG(("%s %s:%c %d \n",FUNCNAME, tag(), 'A' + index, state));
- switch(state)
+ /* 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))
{
- case z80scc_channel::INT_RECEIVE:
- /*The sources of receive interrupts consist of Receive Character Available and Special Receive Condition.
- The Special Receive Condition can be subdivided into Receive Overrun, Framing Error (Asynchronous) or
- End of Frame (SDLC). In addition, a parity error can be a special receive condition by programming*/
- source = 2;
- prio_level = 2;
- break;
- case z80scc_channel::INT_TRANSMIT:
- /*The NMOS/CMOS version of the SCC only has a one byte deep transmit buffer. The status of the
- transmit buffer can be determined through TBE bit in RR0, bit D2, which shows whether the
- transmit buffer is empty or not. After a hardware reset (including a hardware reset by software), or
- a channel reset, this bit is set to 1.
- While transmit interrupts are enabled, the NMOS/CMOS version sets the Transmit Interrupt Pending
- (TxIP) bit whenever the transmit buffer becomes empty. This means that the transmit buffer
- must be full before the TxIP can be set. Thus, when transmit interrupts are first enabled, the TxIP
- will not be set until after the first character is written to the NMOS/CMOS.*/
- source = 0;
- prio_level = 1;
- break;
- case z80scc_channel::INT_SPECIAL:
- /*This mode allows the receiver to interrupt only on
- characters with a special receive condition. When an interrupt occurs, the data containing the error
- is held in the Receive FIFO until an Error Reset command is issued. When using this mode in conjunction
- with a DMA, the DMA is initialized and enabled before any characters have been
- received by the ESCC. This eliminates the time-critical section of code required in the Receive
- Interrupt on First Character or Special Condition mode. Hence, all data can be transferred via the
- DMA so that the CPU need not handle the first received character as a special case. In SDLC
- mode, if the SDLC Frame Status FIFO is enabled and an EOF is received, an interrupt with vector
- for receive data available is generated and the Receive FIFO is not locked.*/
- source = 3;
- prio_level = 0;
- break;
- default:
- logerror("Attempt to trigger interrupt of unknown origin blocked: %02x on channel %c\n", state, 'A' + index);
- return;
- }
-
- // Vector modification requested?
- if (m_chanA->m_wr9 & z80scc_channel::WR9_BIT_VIS)
- {
- vector = modify_vector(vector, index, source);
- }
-
- LOG(("Z80SCC \"%s\" Channel %c : Interrupt Request %u\n", tag(), 'A' + index, state));
+ LOG(("Master Interrupt Enable is not set, blocking attempt to interrupt\n"));
+ return;
+ }
+
+ switch(state)
+ {
+ case z80scc_channel::INT_RECEIVE:
+ /*The sources of receive interrupts consist of Receive Character Available and Special Receive Condition.
+ The Special Receive Condition can be subdivided into Receive Overrun, Framing Error (Asynchronous) or
+ End of Frame (SDLC). In addition, a parity error can be a special receive condition by programming*/
+ source = 2;
+ prio_level = 2;
+ break;
+ case z80scc_channel::INT_TRANSMIT:
+ /*The NMOS/CMOS version of the SCC only has a one byte deep transmit buffer. The status of the
+ transmit buffer can be determined through TBE bit in RR0, bit D2, which shows whether the
+ transmit buffer is empty or not. After a hardware reset (including a hardware reset by software), or
+ a channel reset, this bit is set to 1.
+ While transmit interrupts are enabled, the NMOS/CMOS version sets the Transmit Interrupt Pending
+ (TxIP) bit whenever the transmit buffer becomes empty. This means that the transmit buffer
+ must be full before the TxIP can be set. Thus, when transmit interrupts are first enabled, the TxIP
+ will not be set until after the first character is written to the NMOS/CMOS.*/
+ source = 0;
+ prio_level = 1;
+ break;
+ case z80scc_channel::INT_SPECIAL:
+ /*This mode allows the receiver to interrupt only on
+ characters with a special receive condition. When an interrupt occurs, the data containing the error
+ is held in the Receive FIFO until an Error Reset command is issued. When using this mode in conjunction
+ with a DMA, the DMA is initialized and enabled before any characters have been
+ received by the ESCC. This eliminates the time-critical section of code required in the Receive
+ Interrupt on First Character or Special Condition mode. Hence, all data can be transferred via the
+ DMA so that the CPU need not handle the first received character as a special case. In SDLC
+ mode, if the SDLC Frame Status FIFO is enabled and an EOF is received, an interrupt with vector
+ for receive data available is generated and the Receive FIFO is not locked.*/
+ source = 3;
+ prio_level = 0;
+ break;
+ default:
+ logerror("Attempt to trigger interrupt of unknown origin blocked: %02x on channel %c\n", state, 'A' + index);
+ return;
+ }
+
+ // Vector modification requested?
+ if (m_chanA->m_wr9 & z80scc_channel::WR9_BIT_VIS)
+ {
+ vector = modify_vector(vector, index, source);
+ }
+
+ //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?
m_chanB->m_wr2 = vector;
- /* Check the interrupt source and build the vector modification */
- /*Interrupt Source Priority order
- Channel A Receive
- Channel A Transmit
- Channel A External/Status
- Channel B Receive
- Channel B Transmit
- Channel B External/Status
- */
- // Add channel offset to priority according to table above
- priority = prio_level + (index == CHANNEL_A ? 3 : 0 );
-
+ /* Check the interrupt source and build the vector modification */
+ /*Interrupt Source Priority order
+ Channel A Receive
+ Channel A Transmit
+ Channel A External/Status
+ Channel B Receive
+ Channel B Transmit
+ Channel B External/Status
+ */
+ // Add channel offset to priority according to table above
+ priority = prio_level + (index == CHANNEL_A ? 3 : 0 );
+
// trigger interrupt
m_int_state[priority] |= Z80_DAISY_INT;
-
- // Based on the fact that prio levels are aligned with the bitorder of rr3 we can do this...
+
+ // Based on the fact that prio levels are aligned with the bitorder of rr3 we can do this...
m_chanA->m_rr3 |= (prio_level << (index == CHANNEL_A ? 3 : 0 ));
-
+
// check for interrupt
check_interrupts();
}
//-------------------------------------------------
-// m1_r - interrupt acknowledge
+// m1_r - interrupt acknowledge
//-------------------------------------------------
int z80scc_device::m1_r()
@@ -519,7 +523,7 @@ int z80scc_device::m1_r()
//-------------------------------------------------
-// cd_ba_r - Universal Bus read
+// cd_ba_r - Universal Bus read
//-------------------------------------------------
READ8_MEMBER( z80scc_device::cd_ba_r )
{
@@ -527,34 +531,34 @@ READ8_MEMBER( z80scc_device::cd_ba_r )
int cd = BIT(offset, 1);
z80scc_channel *channel = ba ? m_chanB : m_chanA;
- /* Expell non-Universal Bus variants */
- if ( !(m_variant & SET_Z85X3X))
- {
- logerror("Z80SCC cd_ba_r not supported by this device variant, you should probably use combinations of c*_r/w and d*_r/w (see z80scc.h)\n");
- return 0;
- }
-
- // LOG(("z80scc_device::cd_ba_r ba:%02x cd:%02x\n", ba, cd));
+ /* Expell non-Universal Bus variants */
+ if ( !(m_variant & SET_Z85X3X))
+ {
+ logerror("Z80SCC cd_ba_r not supported by this device variant, you should probably use combinations of c*_r/w and d*_r/w (see z80scc.h)\n");
+ return 0;
+ }
+
+ // LOG(("z80scc_device::cd_ba_r ba:%02x cd:%02x\n", ba, cd));
return cd ? channel->control_read() : channel->data_read();
}
//-------------------------------------------------
-// cd_ba_w - Universal Bus write
+// cd_ba_w - Universal Bus write
//-------------------------------------------------
WRITE8_MEMBER( z80scc_device::cd_ba_w )
{
int ba = BIT(offset, 0);
int cd = BIT(offset, 1);
z80scc_channel *channel = ba ? m_chanB : m_chanA;
-
- /* Expell non-Universal Bus variants */
- if ( !(m_variant & SET_Z85X3X) )
- {
- logerror("Z80SCC cd_ba_w not supported by this device variant, you should probably use combinations of c*_r/w and d*_r/w (see z80scc.h)\n");
- return;
- }
-
- // LOG(("z80scc_device::cd_ba_w ba:%02x cd:%02x\n", ba, cd));
+
+ /* Expell non-Universal Bus variants */
+ if ( !(m_variant & SET_Z85X3X) )
+ {
+ logerror("Z80SCC cd_ba_w not supported by this device variant, you should probably use combinations of c*_r/w and d*_r/w (see z80scc.h)\n");
+ return;
+ }
+
+ // LOG(("z80scc_device::cd_ba_w ba:%02x cd:%02x\n", ba, cd));
if (cd)
channel->control_write(data);
else
@@ -563,7 +567,7 @@ WRITE8_MEMBER( z80scc_device::cd_ba_w )
//-------------------------------------------------
-// ba_cd_r - Universal Bus read
+// ba_cd_r - Universal Bus read
//-------------------------------------------------
READ8_MEMBER( z80scc_device::ba_cd_r )
@@ -571,21 +575,21 @@ READ8_MEMBER( z80scc_device::ba_cd_r )
int ba = BIT(offset, 1);
int cd = BIT(offset, 0);
z80scc_channel *channel = ba ? m_chanB : m_chanA;
-
- /* Expell non-Universal Bus variants */
- if ( !(m_variant & SET_Z85X3X) )
- {
- logerror("Z80SCC ba_cd_r not supported by this device variant, you should probably use combinations of c*_r/w and d*_r/w (see z80scc.h)\n");
- return 0;
- }
-
- // LOG(("z80scc_device::ba_cd_r ba:%02x cd:%02x\n", ba, cd));
+
+ /* Expell non-Universal Bus variants */
+ if ( !(m_variant & SET_Z85X3X) )
+ {
+ logerror("Z80SCC ba_cd_r not supported by this device variant, you should probably use combinations of c*_r/w and d*_r/w (see z80scc.h)\n");
+ return 0;
+ }
+
+ // LOG(("z80scc_device::ba_cd_r ba:%02x cd:%02x\n", ba, cd));
return cd ? channel->control_read() : channel->data_read();
}
//-------------------------------------------------
-// ba_cd_w -
+// ba_cd_w -
//-------------------------------------------------
WRITE8_MEMBER( z80scc_device::ba_cd_w )
@@ -593,15 +597,16 @@ WRITE8_MEMBER( z80scc_device::ba_cd_w )
int ba = BIT(offset, 1);
int cd = BIT(offset, 0);
z80scc_channel *channel = ba ? m_chanB : m_chanA;
+
+ /* Expell non-Universal Bus variants */
+ if ( !(m_variant & SET_Z85X3X) )
+ {
+ logerror("Z80SCC ba_cd_w not supported by this device variant, you should probably use combinations of c*_r/w and d*_r/w (see z80scc.h)\n");
+ return;
+ }
+
+ LOG(("z80scc_device::ba_cd_w ba:%02x cd:%02x\n", ba, cd));
- /* Expell non-Universal Bus variants */
- if ( !(m_variant & SET_Z85X3X) )
- {
- logerror("Z80SCC ba_cd_w not supported by this device variant, you should probably use combinations of c*_r/w and d*_r/w (see z80scc.h)\n");
- return;
- }
-
- LOG(("z80scc_device::ba_cd_w ba:%02x cd:%02x\n", ba, cd));
if (cd)
channel->control_write(data);
else
@@ -609,23 +614,38 @@ WRITE8_MEMBER( z80scc_device::ba_cd_w )
}
//**************************************************************************
-// SCC CHANNEL
+// SCC CHANNEL
//**************************************************************************
//-------------------------------------------------
-// SCC_channel - constructor
+// SCC_channel - constructor
//-------------------------------------------------
z80scc_channel::z80scc_channel(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
- : z80sio_channel( mconfig, tag, owner, clock)
-{
- // Reset all SCC specific registers; z80sio_channel:: manages the base registers
- m_rr0 = m_rr1 = m_rr2 =
- m_rr3 = m_rr4 = m_rr5 = m_rr6 = m_rr7 = m_rr8 = m_rr9 =
- m_rr10 = m_rr11 = m_rr12 = m_rr13 = m_rr14 = m_rr15 = 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;
-
+ : 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)
+{
+ LOG(("%s\n",FUNCNAME));
+
+ // Reset all registers
+ m_rr0 = m_rr1 = m_rr2 = m_rr3 = m_rr4 = m_rr5 = m_rr6 = m_rr7 = m_rr8
+ = m_rr9 = m_rr10 = m_rr11 = m_rr12 = m_rr13 = m_rr14 = m_rr15 = 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
{
m_rx_data_fifo[i] = 0;
@@ -635,22 +655,21 @@ z80scc_channel::z80scc_channel(const machine_config &mconfig, const char *tag, d
//-------------------------------------------------
-// start - channel startup
+// start - channel startup
//-------------------------------------------------
void z80scc_channel::device_start()
{
+ LOG(("%s\n", FUNCNAME));
m_uart = downcast<z80scc_device *>(owner());
- LOG(("%s\n", FUNCNAME));
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_rx_fifo_wp = m_rx_fifo_rp = 0;
+ 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;
+
// 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_rr1));
save_item(NAME(m_rr2));
@@ -667,7 +686,6 @@ void z80scc_channel::device_start()
save_item(NAME(m_rr13));
save_item(NAME(m_rr14));
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_wr1));
save_item(NAME(m_wr2));
@@ -701,50 +719,53 @@ void z80scc_channel::device_start()
save_item(NAME(m_dtr));
save_item(NAME(m_rts));
save_item(NAME(m_sync));
- save_item(NAME(m_ph));
+
device_serial_interface::register_save_state(machine().save(), this);
}
//-------------------------------------------------
-// reset - reset channel status
+// reset - reset channel status
//-------------------------------------------------
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();
transmit_register_reset();
- // Soft/Channel Reset values according to SCC users manual
- m_wr0 = 0x00;
- m_wr1 &= 0x24;
- m_wr3 &= 0x01;
- m_wr4 |= 0x04;
- m_wr5 &= 0x61;
- if (m_variant & (z80scc_device::TYPE_SCC85C30 | SET_ESCC))
- m_wr7 = 0x20;
- m_wr9 &= 0xdf; // WR9 has a different hard reset value
- m_wr10 &= 0x60; // WR10 has a different hard reset value
- m_wr11 &= 0xff; // WR11 has a different hard reset value
- m_wr14 &= 0xc3; // WR14 has a different hard reset value
- m_wr14 |= 0x20;
- m_wr15 = 0xf8;
- m_rr0 &= 0xfc;
- m_rr0 |= 0x44;
- m_rr1 &= 0x07;
- m_rr1 |= 0x06;
- m_rr3 = 0x00;
- m_rr10 &= 0x40;
-
-#if 0 // old reset code
+ // Soft/Channel Reset values according to SCC users manual
+ m_wr0 = 0x00;
+ m_wr1 &= 0x24;
+ m_wr3 &= 0x01;
+ m_wr4 |= 0x04;
+ m_wr5 &= 0x61;
+ if (m_uart->m_variant & (z80scc_device::TYPE_SCC85C30 | SET_ESCC))
+ m_wr7 = 0x20;
+ m_wr9 &= 0xdf; // WR9 has a different hard reset value
+ m_wr10 &= 0x60; // WR10 has a different hard reset value
+ m_wr11 &= 0xff; // WR11 has a different hard reset value
+ m_wr14 &= 0xc3; // WR14 has a different hard reset value
+ m_wr14 |= 0x20;
+ m_wr15 = 0xf8;
+ m_rr0 &= 0xfc;
+ m_rr0 |= 0x44;
+ m_rr1 &= 0x07;
+ m_rr1 |= 0x06;
+ m_rr3 = 0x00;
+ m_rr10 &= 0x40;
+
+#if 1 // old reset code
+ // disable receiver
+ m_wr3 &= ~WR3_RX_ENABLE;
+
// disable transmitter
m_wr5 &= ~WR5_TX_ENABLE;
m_rr0 |= RR0_TX_BUFFER_EMPTY;
#endif
- // TODO: check dependencies on RR1_ALL_SENT and (re)move this setting
+ // TODO: check dependencies on RR1_ALL_SENT and (re)move this setting
m_rr1 |= RR1_ALL_SENT; // It is a don't care in the SCC user manual
// reset external lines TODO: check relation to control bits and reset
@@ -765,14 +786,14 @@ void z80scc_channel::device_timer(emu_timer &timer, device_timer_id id, int para
//-------------------------------------------------
-// tra_callback -
+// tra_callback -
//-------------------------------------------------
void z80scc_channel::tra_callback()
{
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));
+ 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
if (m_index == z80scc_device::CHANNEL_A)
m_uart->m_out_txda_cb(1);
@@ -781,7 +802,7 @@ void z80scc_channel::tra_callback()
}
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));
+ 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
if (m_index == z80scc_device::CHANNEL_A)
m_uart->m_out_txda_cb(0);
@@ -790,32 +811,32 @@ void z80scc_channel::tra_callback()
}
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));
+ 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
if (m_index == z80scc_device::CHANNEL_A)
m_uart->m_out_txda_cb(db);
else
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);
- }
+ 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);
+ }
}
//-------------------------------------------------
-// tra_complete -
+// tra_complete -
//-------------------------------------------------
void z80scc_channel::tra_complete()
{
if ((m_wr5 & WR5_TX_ENABLE) && !(m_wr5 & WR5_SEND_BREAK) && !(m_rr0 & RR0_TX_BUFFER_EMPTY))
{
- 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));
+ 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);
@@ -827,7 +848,7 @@ void z80scc_channel::tra_complete()
}
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));
+ 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
if (m_index == z80scc_device::CHANNEL_A)
m_uart->m_out_txda_cb(0);
@@ -836,7 +857,7 @@ void z80scc_channel::tra_complete()
}
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));
+ 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
if (m_index == z80scc_device::CHANNEL_A)
m_uart->m_out_txda_cb(1);
@@ -847,7 +868,7 @@ void z80scc_channel::tra_complete()
// if transmit buffer is 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));
+ 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
m_rr1 |= RR1_ALL_SENT;
@@ -859,41 +880,42 @@ void z80scc_channel::tra_complete()
//-------------------------------------------------
-// rcv_callback -
+// rcv_callback -
//-------------------------------------------------
void z80scc_channel::rcv_callback()
{
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);
}
- 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("Z80SCC %s() \"%s \"Channel %c Received data dit but receiver is disabled\n", __func__, m_owner->tag(), 'A' + m_index);
- }
+#if 1
+ 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("Z80SCC %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 z80scc_channel::rcv_complete()
{
- UINT8 data;
+ UINT8 data;
receive_register_extract();
- data = get_received_char();
- LOG(("%" I64FMT "d %s() \"%s \"Channel %c Received Data %c\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, data));
+ data = get_received_char();
+ LOG(("%" I64FMT "d %s() \"%s \"Channel %c Received Data %c\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, data));
receive_data(data);
}
//-------------------------------------------------
-// get_clock_mode - get clock divisor
+// get_clock_mode - get clock divisor
//-------------------------------------------------
int z80scc_channel::get_clock_mode()
@@ -902,10 +924,10 @@ int z80scc_channel::get_clock_mode()
switch (m_wr4 & WR4_CLOCK_RATE_MASK)
{
- case WR4_CLOCK_RATE_X1: clocks = 1; break;
- case WR4_CLOCK_RATE_X16: clocks = 16; break;
- case WR4_CLOCK_RATE_X32: clocks = 32; break;
- case WR4_CLOCK_RATE_X64: clocks = 64; break;
+ case WR4_CLOCK_RATE_X1: clocks = 1; break;
+ case WR4_CLOCK_RATE_X16: clocks = 16; break;
+ case WR4_CLOCK_RATE_X32: clocks = 32; break;
+ case WR4_CLOCK_RATE_X64: clocks = 64; break;
}
return clocks;
@@ -924,7 +946,7 @@ TODO:
*/
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)
m_uart->m_out_rtsa_cb(state);
else
@@ -933,7 +955,7 @@ void z80scc_channel::set_rts(int state)
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)
{
// when the RTS bit is set, the _RTS output goes low
@@ -951,7 +973,7 @@ void z80scc_channel::update_rts()
}
//-------------------------------------------------
-// get_stop_bits - get number of stop bits
+// get_stop_bits - get number of stop bits
//-------------------------------------------------
device_serial_interface::stop_bits_t z80scc_channel::get_stop_bits()
@@ -968,7 +990,7 @@ device_serial_interface::stop_bits_t z80scc_channel::get_stop_bits()
//-------------------------------------------------
-// get_rx_word_length - get receive word length
+// get_rx_word_length - get receive word length
//-------------------------------------------------
int z80scc_channel::get_rx_word_length()
@@ -977,10 +999,10 @@ int z80scc_channel::get_rx_word_length()
switch (m_wr3 & WR3_RX_WORD_LENGTH_MASK)
{
- case WR3_RX_WORD_LENGTH_5: bits = 5; break;
- case WR3_RX_WORD_LENGTH_6: bits = 6; break;
- case WR3_RX_WORD_LENGTH_7: bits = 7; break;
- case WR3_RX_WORD_LENGTH_8: bits = 8; break;
+ case WR3_RX_WORD_LENGTH_5: bits = 5; break;
+ case WR3_RX_WORD_LENGTH_6: bits = 6; break;
+ case WR3_RX_WORD_LENGTH_7: bits = 7; break;
+ case WR3_RX_WORD_LENGTH_8: bits = 8; break;
}
return bits;
@@ -988,7 +1010,7 @@ int z80scc_channel::get_rx_word_length()
//-------------------------------------------------
-// get_tx_word_length - get transmit word length
+// get_tx_word_length - get transmit word length
//-------------------------------------------------
int z80scc_channel::get_tx_word_length()
@@ -997,15 +1019,34 @@ int z80scc_channel::get_tx_word_length()
switch (m_wr5 & WR5_TX_WORD_LENGTH_MASK)
{
- case WR5_TX_WORD_LENGTH_5: bits = 5; break;
- case WR5_TX_WORD_LENGTH_6: bits = 6; break;
- case WR5_TX_WORD_LENGTH_7: bits = 7; break;
- case WR5_TX_WORD_LENGTH_8: bits = 8; break;
+ case WR5_TX_WORD_LENGTH_5: bits = 5; break;
+ case WR5_TX_WORD_LENGTH_6: bits = 6; break;
+ case WR5_TX_WORD_LENGTH_7: bits = 7; break;
+ case WR5_TX_WORD_LENGTH_8: bits = 8; break;
}
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:
"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
@@ -1014,26 +1055,26 @@ on the state of the Status High/Status Low bit in WR9 and independent of the sta
in WR9."*/
UINT8 z80scc_channel::do_sccreg_rr2()
{
- LOG(("Z80SCC %s()\n", __func__));
+ LOG(("Z80SCC %s()\n", __func__));
- // Assume the unmodified in polled mode
- m_rr2 = m_uart->m_chanA->m_wr2;
+ // Assume the unmodified in polled mode
+ m_rr2 = m_uart->m_chanA->m_wr2;
- // If we are chan B we have to modify the vector regardless of the VIS bit
+ // If we are chan B we have to modify the vector regardless of the VIS bit
if (m_index == z80scc_device::CHANNEL_B)
+ {
+ // loop over all interrupt sources
+ for (int i = 0; i < 6; i++)
{
- // loop over all interrupt sources
- for (int i = 0; i < 6; i++)
- {
- // find the first channel with an interrupt requested
- if (m_uart->m_int_state[i] & Z80_DAISY_INT)
- {
- m_rr2 = m_uart->modify_vector(m_rr2, i < 3 ? z80scc_device::CHANNEL_A : z80scc_device::CHANNEL_B, i & 3);
- break;
- }
- }
+ // find the first channel with an interrupt requested
+ if (m_uart->m_int_state[i] & Z80_DAISY_INT)
+ {
+ m_rr2 = m_uart->modify_vector(m_rr2, i < 3 ? z80scc_device::CHANNEL_A : z80scc_device::CHANNEL_B, i & 3);
+ break;
+ }
}
- return m_rr2;
+ }
+ return m_rr2;
}
/* From Zilog SCC/ESCC USers manual, UM010902-0609:
@@ -1043,8 +1084,8 @@ B, all 0s are returned. The two unused bits are always returned as 0. Figure dis
*/
UINT8 z80scc_channel::do_sccreg_rr3()
{
- LOG(("Z80SCC %s()\n", __func__));
- return m_rr3; // TODO Update all bits of this status register
+ LOG(("Z80SCC %s()\n", __func__));
+ return m_rr3; // TODO Update all bits of this status register
}
@@ -1054,11 +1095,11 @@ UINT8 z80scc_channel::do_sccreg_rr3()
a read to this location returns an image of RR0.*/
UINT8 z80scc_channel::do_sccreg_rr4()
{
- LOG(("Z80SCC %s()\n", __func__));
- if (m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
- return (BIT(m_wr7, 6) ? m_wr4 : m_rr0);
- else
- return m_rr0;
+ LOG(("Z80SCC %s()\n", __func__));
+ if (m_uart->m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
+ return (BIT(m_wr7, 6) ? m_wr4 : m_rr0);
+ else
+ return m_rr0;
}
/* (ESCC and 85C30 Only) */
@@ -1067,11 +1108,11 @@ UINT8 z80scc_channel::do_sccreg_rr4()
a read to this register returns an image of RR1.*/
UINT8 z80scc_channel::do_sccreg_rr5()
{
- LOG(("Z80SCC %s()\n", __func__));
- if (m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
- return BIT(m_wr7, 6) ? m_wr5 : m_rr1;
- else
- return m_rr1;
+ LOG(("Z80SCC %s()\n", __func__));
+ if (m_uart->m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
+ return BIT(m_wr7, 6) ? m_wr5 : m_rr1;
+ else
+ return m_rr1;
}
/* (not on NMOS)
@@ -1082,13 +1123,13 @@ UINT8 z80scc_channel::do_sccreg_rr5()
On the NMOS version, a read to this register location returns an image of RR2.*/
UINT8 z80scc_channel::do_sccreg_rr6()
{
- LOG(("Z80SCC %s()\n", __func__));
- if (!(m_variant & (SET_NMOS)))
- {
- logerror("Z80SCC %s() not implemented feature\n", __func__);
- return 0;
- }
- return m_rr2;
+ LOG(("Z80SCC %s()\n", __func__));
+ if (!(m_uart->m_variant & (SET_NMOS)))
+ {
+ logerror("Z80SCC %s() not implemented feature\n", __func__);
+ return 0;
+ }
+ return m_rr2;
}
/* (not on NMOS)
@@ -1101,12 +1142,12 @@ UINT8 z80scc_channel::do_sccreg_rr6()
RR7, RR6, RR1.*/
UINT8 z80scc_channel::do_sccreg_rr7()
{
- LOG(("Z80SCC %s()\n", __func__));
- if (!(m_variant & (SET_NMOS)))
- {
- logerror("Z80SCC %s() not implemented feature\n", __func__);
- return 0;
- }
+ LOG(("Z80SCC %s()\n", __func__));
+ if (!(m_uart->m_variant & (SET_NMOS)))
+ {
+ logerror("Z80SCC %s() not implemented feature\n", __func__);
+ return 0;
+ }
return m_rr3;
}
@@ -1114,7 +1155,7 @@ UINT8 z80scc_channel::do_sccreg_rr7()
/* RR8 is the Receive Data register. */
UINT8 z80scc_channel::do_sccreg_rr8()
{
- return data_read():
+ return data_read():
}
#endif
@@ -1124,19 +1165,19 @@ UINT8 z80scc_channel::do_sccreg_rr8()
of RR13. TODO: Check what is returned if Extended Read option is turned off */
UINT8 z80scc_channel::do_sccreg_rr9()
{
- LOG(("Z80SCC %s()\n", __func__));
- if (m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
- return BIT(m_wr7, 6) ? m_wr3 : m_rr13;
- else
- return m_rr13;
+ LOG(("Z80SCC %s()\n", __func__));
+ if (m_uart->m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
+ return BIT(m_wr7, 6) ? m_wr3 : m_rr13;
+ else
+ return m_rr13;
}
/* RR10 contains some SDLC related miscellaneous status bits. Unused bits are always 0. */
UINT8 z80scc_channel::do_sccreg_rr10()
{
- LOG(("Z80SCC %s()\n", __func__));
- logerror("Z80SCC %s() not implemented feature\n", __func__);
- return m_rr10;
+ LOG(("Z80SCC %s()\n", __func__));
+ logerror("Z80SCC %s() not implemented feature\n", __func__);
+ return m_rr10;
}
/* (ESCC and 85C30 Only)
@@ -1145,25 +1186,25 @@ UINT8 z80scc_channel::do_sccreg_rr10()
On the NMOS/CMOS version, a read to this location returns an image of RR15.*/
UINT8 z80scc_channel::do_sccreg_rr11()
{
- LOG(("Z80SCC %s()\n", __func__));
- if (m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
- return BIT(m_wr7, 6) ? m_wr10 : m_rr15;
- else
- return m_rr15;
+ LOG(("Z80SCC %s()\n", __func__));
+ if (m_uart->m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
+ return BIT(m_wr7, 6) ? m_wr10 : m_rr15;
+ else
+ return m_rr15;
}
/*
RR12 returns the value stored in WR12, the lower byte of the time constant, for the BRG.*/
UINT8 z80scc_channel::do_sccreg_rr12()
{
- return m_wr12;
+ return m_wr12;
}
/*
RR13 returns the value stored in WR13, the upper byte of the time constant for the BRG. */
UINT8 z80scc_channel::do_sccreg_rr13()
{
- return m_wr13;
+ return m_wr13;
}
/* (ESCC and 85C30 Only)
@@ -1172,11 +1213,11 @@ Extended Read option has been enabled. Otherwise, this register returns an image
On the NMOS/CMOS version, a read to this location returns an image of RR10.*/
UINT8 z80scc_channel::do_sccreg_rr14()
{
- LOG(("Z80SCC %s()\n", __func__));
- if (m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
- return BIT(m_wr7, 6) ? m_wr7 : m_rr10;
- else
- return m_rr10;
+ LOG(("Z80SCC %s()\n", __func__));
+ if (m_uart->m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
+ return BIT(m_wr7, 6) ? m_wr7 : m_rr10;
+ else
+ return m_rr10;
}
/*
@@ -1184,25 +1225,23 @@ UINT8 z80scc_channel::do_sccreg_rr14()
always returned as Os. */
UINT8 z80scc_channel::do_sccreg_rr15()
{
- LOG(("Z80SCC %s()\n", __func__));
- logerror("Z80SCC %s() not implemented feature\n", __func__);
- return m_wr15 & 0xf5; // Mask out the used bits
+ LOG(("Z80SCC %s()\n", __func__));
+ logerror("Z80SCC %s() not implemented feature\n", __func__);
+ return m_wr15 & 0xf5; // Mask out the used bits
}
//-------------------------------------------------
-// control_read - read control register
+// control_read - read control register
//-------------------------------------------------
UINT8 z80scc_channel::control_read()
{
UINT8 data = 0;
- int reg = m_wr0;
- int regmask = (WR0_REGISTER_MASK | m_ph);
-
- // LOG(("%s(%02x) reg %02x, regmask %02x, WR0 %02x\n", __func__, data, reg, regmask, m_wr0));
-
- m_ph = 0; // The "Point High" command is only valid for one access
+ int reg = m_uart->m_wr0_ptrbits; //m_wr0;
+ int regmask = (WR0_REGISTER_MASK | (m_uart->m_wr0_ptrbits & WR0_POINT_HIGH));
- reg &= regmask;
+ // LOG(("%s(%02x) reg %02x, regmask %02x, WR0 %02x\n", __func__, data, reg, regmask, m_wr0));
+ m_uart->m_wr0_ptrbits = 0;
+ reg &= regmask;
if (reg != 0)
{
@@ -1210,152 +1249,218 @@ UINT8 z80scc_channel::control_read()
m_wr0 &= ~regmask;
}
- /* TODO. Sort out 80X30 limitations in register access */
+ /* TODO. Sort out 80X30 limitations in register access */
switch (reg)
{
- case REG_RR0_STATUS: data = do_sioreg_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_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_sccreg_rr1(); break;
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 */
case REG_RR3_INTERUPPT_PEND: data = do_sccreg_rr3(); break;
- case REG_RR4_WR4_OR_RR0: data = do_sccreg_rr4(); break;
- case REG_RR5_WR5_OR_RR0: data = do_sccreg_rr5(); break;
- case REG_RR6_LSB_OR_RR2: data = do_sccreg_rr6(); break;
- case REG_RR7_MSB_OR_RR3: data = do_sccreg_rr7(); break;
+ case REG_RR4_WR4_OR_RR0: data = do_sccreg_rr4(); break;
+ case REG_RR5_WR5_OR_RR0: data = do_sccreg_rr5(); break;
+ case REG_RR6_LSB_OR_RR2: data = do_sccreg_rr6(); break;
+ case REG_RR7_MSB_OR_RR3: data = do_sccreg_rr7(); break;
/* registers 8-15 are specific to SCC */
- case REG_RR8_RECEIVE_DATA: data = data_read(); break;
- case REG_RR9_WR3_OR_RR13: data = do_sccreg_rr9(); break;
- case REG_RR10_MISC_STATUS: data = do_sccreg_rr10(); break;
- case REG_RR11_WR10_OR_RR15: data = do_sccreg_rr11(); break;
- case REG_RR12_LO_TIME_CONST: data = do_sccreg_rr12(); break;
- case REG_RR13_HI_TIME_CONST: data = do_sccreg_rr13(); 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_RR8_RECEIVE_DATA: data = data_read(); break;
+ case REG_RR9_WR3_OR_RR13: data = do_sccreg_rr9(); break;
+ case REG_RR10_MISC_STATUS: data = do_sccreg_rr10(); break;
+ case REG_RR11_WR10_OR_RR15: data = do_sccreg_rr11(); break;
+ case REG_RR12_LO_TIME_CONST: data = do_sccreg_rr12(); break;
+ case REG_RR13_HI_TIME_CONST: data = do_sccreg_rr13(); break;
+ case REG_RR14_WR7_OR_R10: data = do_sccreg_rr14(); break;
+ case REG_RR15_WR15_EXT_STAT: data = do_sccreg_rr15(); break;
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;
}
+/* 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)
{
- m_wr0 = data;
+ m_wr0 = data;
+ m_uart->m_wr0_ptrbits = data & WR0_REGISTER_MASK;
- /* Sort out SCC specific behaviours from legacy SIO behaviour */
- /* WR0_Z_* are Z80X30 specific commands */
- switch (data & WR0_COMMAND_MASK)
+ /* Sort out SCC specific behaviours from legacy SIO behaviour */
+ /* WR0_Z_* are Z80X30 specific commands */
+ switch (data & WR0_COMMAND_MASK)
{
- case WR0_POINT_HIGH:
- /*This command effectively adds eight to the Register Pointer (D2-D0) by allowing
- WR8 through WR15 to be accessed. The Point High command and the Register
- Pointer bits are written simultaneously. This command is used in the Z85X30
- 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
- addressing*/
- if (m_variant & SET_Z85X3X)
- {
- LOG(("Z80SCC \"%s\" %s Channel %c : %s - Point High command\n", m_owner->tag(), __func__, 'A' + m_index, __func__));
- m_ph = 8;
- }
- else
- LOG(("Z80SCC \"%s\" %s Channel %c : %s - NULL command 2\n", m_owner->tag(), __func__, 'A' + m_index, __func__));
- break;
- 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,
- for example), the status bits in RR0 are latched. This command re-enables the bits
- and allows interrupts to occur again as a result of a status change. Latching the
- status bits captures short pulses until the CPU has time to read the change.
- The SCC contains simple queueing logic associated with most of the external status
- bits in RR0. If another External/Status condition changes while a previous condition
- is still pending (Reset External/Status Interrupt has not yet been issued) and this
- condition persists until after the command is issued, this second change causes another
- External/Status interrupt. However, if this second status change does not persist
- (there are two transitions), another interrupt is not generated. Exceptions to this
- rule are detailed in the RR0 description.*/
- do_sioreg_wr0(data);
- if (!m_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__));
- break;
- case WR0_RESET_HIGHEST_IUS:
- /* 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
- daisy chain (even in systems without an external daisy chain) and is the last operation in
- 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));
- break;
- case WR0_ERROR_RESET:
- /*Error Reset Command (110). This command resets the error bits in RR1. If interrupt on first Rx
- Character or Interrupt on Special Condition modes is selected and a special condition exists, the
- 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
- Receive FIFO, the data is lost */
- LOG(("Z80SCC \"%s\" %s Channel %c : WR0_ERROR_RESET\n", m_owner->tag(), __func__, 'A' + m_index));
- do_sioreg_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.
- break;
- case WR0_SEND_ABORT:
- 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 */
- case WR0_NULL:
- case WR0_ENABLE_INT_NEXT_RX:
- case WR0_RESET_TX_INT:
- default:
- do_sioreg_wr0(data);
+ case WR0_POINT_HIGH:
+ /*This command effectively adds eight to the Register Pointer (D2-D0) by allowing
+ WR8 through WR15 to be accessed. The Point High command and the Register
+ Pointer bits are written simultaneously. This command is used in the Z85X30
+ 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
+ addressing*/
+ if (m_uart->m_variant & SET_Z85X3X)
+ {
+ LOG(("Z80SCC \"%s\" %s: %c : %s - Point High command\n", m_owner->tag(), __func__, 'A' + m_index, __func__));
+ //m_ph = 8;
+ m_uart->m_wr0_ptrbits |= 8;
}
- do_sioreg_wr0_resets(data);
- if ( m_variant & SET_Z80X30) // TODO: Implement adress decoding for Z80X30 using the shift logic described below
+ else
+ LOG(("Z80SCC \"%s\" %s: %c : %s - NULL command 2\n", m_owner->tag(), __func__, 'A' + m_index, __func__));
+ break;
+ 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,
+ for example), the status bits in RR0 are latched. This command re-enables the bits
+ and allows interrupts to occur again as a result of a status change. Latching the
+ status bits captures short pulses until the CPU has time to read the change.
+ The SCC contains simple queueing logic associated with most of the external status
+ bits in RR0. If another External/Status condition changes while a previous condition
+ is still pending (Reset External/Status Interrupt has not yet been issued) and this
+ condition persists until after the command is issued, this second change causes another
+ External/Status interrupt. However, if this second status change does not persist
+ (there are two transitions), another interrupt is not generated. Exceptions to this
+ rule are detailed in the RR0 description.*/
+ // do_sccreg_wr0(data);
+ if (!m_zc)
{
- /*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
- decoded to form the register address. It is placed in this register to simplify programming when the
- current state of the Shift Right/Shift Left bit is not known.
- A hardware reset forces Shift Left mode where the address is decoded from AD5-AD1. In Shift
- Right mode, the address is decoded from AD4-AD0. The Shift Right/Shift Left bit is written via a
- command to make the software writing to WR0 independent of the state of the Shift Right/Shift
- Left bit.
- While in the Shift Left mode, the register address is placed on AD4-AD1 and the Channel Select
- bit, A/B, is decoded from AD5. The register map for this case is listed in Table on page 21. In
- Shift Right mode, the register address is again placed on AD4-AD1 but the channel select A/B is
- decoded from AD0. The register map for this case is listed in Table on page 23.
- Because the Z80X30 does not contain 16 read registers, the decoding of the read registers is not
- complete; this is listed in Table on page 21 and Table on page 23 by parentheses around the register
- name. These addresses may also be used to access the read registers. Also, note that the
- Z80X30 contains only one WR2 and WR9; these registers may be written from either channel.
- Shift Left Mode is used when Channel A and B are to be programmed differently. This allows the
- software to sequence through the registers of one channel at a time. The Shift Right Mode is used
- when the channels are programmed the same. By incrementing the address, the user can program
- the same data value into both the Channel A and Channel B register.*/
- switch(data & WR0_Z_SHIFT_MASK)
- {
- 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__));
- break;
- 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__));
- break;
- default:
- break;
- // LOG(("Z80SCC \"%s\" Channel %c : %s - Null commands\n", m_owner->tag(), 'A' + m_index, __func__));
- }
+ m_rr0 |= RR0_ZC;
}
+ LOG(("Z80SCC \"%s\" %s: %c : %s - Reset External/Status Interrupt\n", m_owner->tag(), __func__, 'A' + m_index, __func__));
+ break;
+ case WR0_RESET_HIGHEST_IUS:
+ /* 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
+ daisy chain (even in systems without an external daisy chain) and is the last operation in
+ an interrupt service routine.TODO: Implement internal Daisychain */
+ LOG(("Z80SCC \"%s\" %s: %c : Reset Highest IUS\n", m_owner->tag(), __func__, 'A' + m_index));
+ break;
+ case WR0_ERROR_RESET:
+ /*Error Reset Command (110). This command resets the error bits in RR1. If interrupt on first Rx
+ Character or Interrupt on Special Condition modes is selected and a special condition exists, the
+ 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
+ Receive FIFO, the data is lost */
+ LOG(("Z80SCC \"%s\" %s: %c : WR0_ERROR_RESET\n", m_owner->tag(), __func__, 'A' + m_index));
+ //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.
+ break;
+ case WR0_SEND_ABORT:
+ 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 */
+ case WR0_NULL:
+ LOG(("Z80SCC \"%s\" Channel %c : Null\n", m_owner->tag(), 'A' + m_index));
+ break;
+ 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:
+ // 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:
+ break;
+ // do_sioreg_wr0(data);
+ }
+ do_sccreg_wr0_resets(data);
+
+ 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
+ edge of /AS. The Shift Right/Shift Left bit in the Channel B WR0 controls which bits are
+ decoded to form the register address. It is placed in this register to simplify programming when the
+ current state of the Shift Right/Shift Left bit is not known.
+ A hardware reset forces Shift Left mode where the address is decoded from AD5-AD1. In Shift
+ Right mode, the address is decoded from AD4-AD0. The Shift Right/Shift Left bit is written via a
+ command to make the software writing to WR0 independent of the state of the Shift Right/Shift
+ Left bit.
+ While in the Shift Left mode, the register address is placed on AD4-AD1 and the Channel Select
+ bit, A/B, is decoded from AD5. The register map for this case is listed in Table on page 21. In
+ Shift Right mode, the register address is again placed on AD4-AD1 but the channel select A/B is
+ decoded from AD0. The register map for this case is listed in Table on page 23.
+ Because the Z80X30 does not contain 16 read registers, the decoding of the read registers is not
+ complete; this is listed in Table on page 21 and Table on page 23 by parentheses around the register
+ name. These addresses may also be used to access the read registers. Also, note that the
+ Z80X30 contains only one WR2 and WR9; these registers may be written from either channel.
+ Shift Left Mode is used when Channel A and B are to be programmed differently. This allows the
+ software to sequence through the registers of one channel at a time. The Shift Right Mode is used
+ when the channels are programmed the same. By incrementing the address, the user can program
+ the same data value into both the Channel A and Channel B register.*/
+ switch(data & WR0_Z_SHIFT_MASK)
+ {
+ case WR0_Z_SEL_SHFT_LEFT:
+ LOG(("Z80SCC \"%s\": %c : %s - Shift Left Addressing Mode - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
+ break;
+ case WR0_Z_SEL_SHFT_RIGHT:
+ LOG(("Z80SCC \"%s\": %c : %s - Shift Right Addressing Mode - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
+ break;
+ default:
+ break;
+ // LOG(("Z80SCC \"%s\": %c : %s - Null commands\n", m_owner->tag(), 'A' + m_index, __func__));
+ }
+ }
}
/* Write Register 1 is the control register for the various SCC interrupt and Wait/Request modes.*/
void z80scc_channel::do_sccreg_wr1(UINT8 data)
{
- LOG(("Z80SCC \"%s\" Channel %c : %s - %02x\n", m_owner->tag(), 'A' + m_index, __func__, data));
- /* TODO: Sort out SCC specific behaviours from legacy SIO behaviours:
- - Channel B only bits vs
- - Parity Is Special Condition, bit2 */
- do_sioreg_wr1(data & ~0x40); // Lets SIO code handle it for now but mask out dangerous bits
- m_uart->check_interrupts();
+ 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:
+ - Channel B only bits vs
+ - Parity Is Special Condition, bit2 */
+ 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();
}
/*WR2 is the interrupt vector register. Only one vector register exists in the SCC, and it can be
@@ -1363,23 +1468,61 @@ 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.*/
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));
- m_wr2 = 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 */
+ LOG(("%s(%d) Setting the interrupt vector\n", FUNCNAME, data));
+ m_wr2 = 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->check_interrupts();
+}
- m_uart->check_interrupts();
+void z80scc_channel::do_sccreg_wr3(UINT8 data)
+{
+ 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()));
}
-/*
- * NOTE: Register WR3-WR7 are identical to the Z80SIO so handled by z80sio.c
- */
+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 */
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));
- data_write(data);
+ LOG(("%s(%d) \"%s\": %c : Transmit Buffer read %02x\n", FUNCNAME, data, m_owner->tag(), 'A' + m_index, data));
+ data_write(data);
}
/*WR9 is the Master Interrupt Control register and contains the Reset command bits. Only one WR9
@@ -1388,38 +1531,38 @@ 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.*/
void z80scc_channel::do_sccreg_wr9(UINT8 data)
{
- if (m_variant & SET_Z80X30)
- {
- m_uart->m_chanA->m_wr9 = data;
- m_uart->m_chanB->m_wr9 = data;
- }
- else
- m_wr9 = data;
+ if (m_uart->m_variant & SET_Z80X30)
+ {
+ m_uart->m_chanA->m_wr9 = data;
+ m_uart->m_chanB->m_wr9 = data;
+ }
+ else
+ m_wr9 = data;
- switch (data & WR9_CMD_MASK)
- {
- case WR9_CMD_NORESET:
- LOG(("Z80SCC \"%s\" Channel %c : Master Interrupt Control - No reset %02x\n", m_owner->tag(), 'A' + m_index, data));
- break;
- 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));
- m_uart->m_chanB->reset();
- break;
- 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));
- m_uart->m_chanA->reset();
- break;
- case WR9_CMD_HW_RESET:
- LOG(("Z80SCC \"%s\" Channel %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
- 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 */
- if (data & (WR9_BIT_MIE | WR9_BIT_IACK | WR9_BIT_SHSL | WR9_BIT_DLC | WR9_BIT_NV))
- logerror("Z80SCC: SCC Interrupt system not yet implemented, please be patient!\n");
- m_uart->device_reset();
- default:
- logerror("Z80SCC Code is broken in WR9, please report!\n");
- }
+ switch (data & WR9_CMD_MASK)
+ {
+ case WR9_CMD_NORESET:
+ LOG(("Z80SCC \"%s\": %c : Master Interrupt Control - No reset %02x\n", m_owner->tag(), 'A' + m_index, data));
+ break;
+ case WR9_CMD_CHNB_RESET:
+ LOG(("Z80SCC \"%s\": %c : Master Interrupt Control - Channel B reset %02x\n", m_owner->tag(), 'A' + m_index, data));
+ m_uart->m_chanB->reset();
+ break;
+ case WR9_CMD_CHNA_RESET:
+ LOG(("Z80SCC \"%s\": %c : Master Interrupt Control - Channel A reset %02x\n", m_owner->tag(), 'A' + m_index, data));
+ m_uart->m_chanA->reset();
+ break;
+ case WR9_CMD_HW_RESET:
+ 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
+ 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 */
+ if (data & (WR9_BIT_MIE | WR9_BIT_IACK | WR9_BIT_SHSL | WR9_BIT_DLC | WR9_BIT_NV))
+ logerror("Z80SCC: SCC Interrupt system not yet implemented, please be patient!\n");
+ m_uart->device_reset();
+ default:
+ logerror("Z80SCC Code is broken in WR9, please report!\n");
+ }
}
/* WR10 contains miscellaneous control bits for both the receiver and the transmitter. Bit positions
@@ -1427,8 +1570,8 @@ for WR10 are displayed in Figure . On the ESCC and 85C30 with the Extended Read
enabled, this register may be read as RR11.*/
void z80scc_channel::do_sccreg_wr10(UINT8 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));
+ m_wr10 = 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
@@ -1436,110 +1579,110 @@ receive and transmit clocks, the type of signal on the /SYNC and /RTxC pins, and
the /TRxC pin.*/
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));
- 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
- to 0, the SCC expects a TTL-compatible signal as an input to this pin. If this bit is set to 1, the SCC
- connects a high-gain amplifier between the /RTxC and /SYNC pins in expectation of a quartz
- crystal being placed across the pins.
- The output of this oscillator is available for use as a clocking source. In this mode of operation, the
- /SYNC pin is unavailable for other use. The /SYNC signal is forced to zero internally. A hardware
- reset forces /NO XTAL. (At least 20 ms should be allowed after this bit is set to allow the oscillator
- to stabilize.)*/
- LOG((" Clock type %s\n", data & WR11_RCVCLK_TYPE ? "Crystal oscillator between RTxC and /SYNC pins" : "TTL level on RTxC pin"));
- /*Bits 6 and 5: Receiver Clock select bits 1 and 0
- These bits determine the source of the receive clock as listed below. They do not
- interfere with any of the modes of operation in the SCC, but simply control a multiplexer just
- before the internal receive clock input. A hardware reset forces the receive clock to come from the
- /RTxC pin.*/
- LOG((" Receive clock source is: "));
- switch (data & WR11_RCVCLK_SRC_MASK)
- {
- case WR11_RCVCLK_SRC_RTXC: LOG(("RTxC\n")); break;
- case WR11_RCVCLK_SRC_TRXC: LOG(("TRxC\n")); break;
- case WR11_RCVCLK_SRC_BR: LOG(("Baudrate Generator\n")); break;
- case WR11_RCVCLK_SRC_DPLL: LOG(("DPLL\n")); break;
- default: logerror("Wrong!\n");/* Will not happen unless someone messes with the mask */
- }
- /*Bits 4 and 3: Transmit Clock select bits 1 and 0.
- These bits determine the source of the transmit clock as listed in Table . They do not interfere with
- any of the modes of operation of the SCC, but simply control a multiplexer just before the internal
- transmit clock input. The DPLL output that is used to feed the transmitter in FM modes lags by 90
- degrees the output of the DPLL used by the receiver. This makes the received and transmitted bit
- cells occur simultaneously, neglecting delays. A hardware reset selects the /TRxC pin as the
- source of the transmit clocks.*/
- LOG((" Transmit clock source is: "));
- switch (data & WR11_TRACLK_SRC_MASK)
- {
- case WR11_TRACLK_SRC_RTXC: LOG(("RTxC\n")); break;
- case WR11_TRACLK_SRC_TRXC: LOG(("TRxC\n")); break;
- case WR11_TRACLK_SRC_BR: LOG(("Baudrate Generator\n")); break;
- case WR11_TRACLK_SRC_DPLL: LOG(("DPLL\n")); break;
- default: logerror("Wrong!\n");/* Will not happen unless someone messes with the mask */
- }
- /* Bit 2: TRxC Pin I/O control bit
- This bit determines the direction of the /TRxC pin. If this bit is set to 1, the /TRxC pin is an output
- and carries the signal selected by D1 and D0 of this register. However, if either the receive or the
- transmit clock is programmed to come from the /TRxC pin, /TRxC is an input, regardless of the
- state of this bit. The /TRxC pin is also an input if this bit is set to 0. A hardware reset forces this bit
- to 0.*/
- LOG((" TRxC pin is %s\n", data & WR11_TRXC_DIRECTION ? "Output" : "Input"));
- /*Bits 1 and 0: /TRxC Output Source select bits 1 and 0
- These bits determine the signal to be echoed out of the SCC via the /TRxC pin as listed in Table
- on page 167. No signal is produced if /TRxC has been programmed as the source of either the
- receive or the transmit clock. If /TRxC O/I (bit 2) is set to 0, these bits are ignored.
- If the XTAL oscillator output is programmed to be echoed, and the XTAL oscillator is not enabled,
- the /TRxC pin goes High. The DPLL signal that is echoed is the DPLL signal used by the receiver.
- Hardware reset selects the XTAL oscillator as the output source*/
- LOG((" TRxC clock source is: "));
- switch (data & WR11_TRXSRC_SRC_MASK)
- {
- case WR11_TRXSRC_SRC_XTAL: LOG(("the Oscillator\n")); break;
- case WR11_TRXSRC_SRC_TRA: LOG(("Transmit clock\n")); break;
- case WR11_TRXSRC_SRC_BR: LOG(("Baudrate Generator\n")); break;
- case WR11_TRXSRC_SRC_DPLL: LOG(("DPLL\n")); break;
- default: logerror("Wrong!\n");/* Will not happen unless someone messes with the mask */
- }
+ LOG(("Z80SCC \"%s\": %c : %s Clock Mode Control %02x - not implemented \n", m_owner->tag(), 'A' + m_index, __func__, 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
+ to 0, the SCC expects a TTL-compatible signal as an input to this pin. If this bit is set to 1, the SCC
+ connects a high-gain amplifier between the /RTxC and /SYNC pins in expectation of a quartz
+ crystal being placed across the pins.
+ The output of this oscillator is available for use as a clocking source. In this mode of operation, the
+ /SYNC pin is unavailable for other use. The /SYNC signal is forced to zero internally. A hardware
+ reset forces /NO XTAL. (At least 20 ms should be allowed after this bit is set to allow the oscillator
+ to stabilize.)*/
+ LOG((" Clock type %s\n", data & WR11_RCVCLK_TYPE ? "Crystal oscillator between RTxC and /SYNC pins" : "TTL level on RTxC pin"));
+ /*Bits 6 and 5: Receiver Clock select bits 1 and 0
+ These bits determine the source of the receive clock as listed below. They do not
+ interfere with any of the modes of operation in the SCC, but simply control a multiplexer just
+ before the internal receive clock input. A hardware reset forces the receive clock to come from the
+ /RTxC pin.*/
+ LOG((" Receive clock source is: "));
+ switch (data & WR11_RCVCLK_SRC_MASK)
+ {
+ case WR11_RCVCLK_SRC_RTXC: LOG(("RTxC\n")); break;
+ case WR11_RCVCLK_SRC_TRXC: LOG(("TRxC\n")); break;
+ case WR11_RCVCLK_SRC_BR: LOG(("Baudrate Generator\n")); break;
+ case WR11_RCVCLK_SRC_DPLL: LOG(("DPLL\n")); break;
+ default: logerror("Wrong!\n");/* Will not happen unless someone messes with the mask */
+ }
+ /*Bits 4 and 3: Transmit Clock select bits 1 and 0.
+ These bits determine the source of the transmit clock as listed in Table . They do not interfere with
+ any of the modes of operation of the SCC, but simply control a multiplexer just before the internal
+ transmit clock input. The DPLL output that is used to feed the transmitter in FM modes lags by 90
+ degrees the output of the DPLL used by the receiver. This makes the received and transmitted bit
+ cells occur simultaneously, neglecting delays. A hardware reset selects the /TRxC pin as the
+ source of the transmit clocks.*/
+ LOG((" Transmit clock source is: "));
+ switch (data & WR11_TRACLK_SRC_MASK)
+ {
+ case WR11_TRACLK_SRC_RTXC: LOG(("RTxC\n")); break;
+ case WR11_TRACLK_SRC_TRXC: LOG(("TRxC\n")); break;
+ case WR11_TRACLK_SRC_BR: LOG(("Baudrate Generator\n")); break;
+ case WR11_TRACLK_SRC_DPLL: LOG(("DPLL\n")); break;
+ default: logerror("Wrong!\n");/* Will not happen unless someone messes with the mask */
+ }
+ /* Bit 2: TRxC Pin I/O control bit
+ This bit determines the direction of the /TRxC pin. If this bit is set to 1, the /TRxC pin is an output
+ and carries the signal selected by D1 and D0 of this register. However, if either the receive or the
+ transmit clock is programmed to come from the /TRxC pin, /TRxC is an input, regardless of the
+ state of this bit. The /TRxC pin is also an input if this bit is set to 0. A hardware reset forces this bit
+ to 0.*/
+ LOG((" TRxC pin is %s\n", data & WR11_TRXC_DIRECTION ? "Output" : "Input"));
+ /*Bits 1 and 0: /TRxC Output Source select bits 1 and 0
+ These bits determine the signal to be echoed out of the SCC via the /TRxC pin as listed in Table
+ on page 167. No signal is produced if /TRxC has been programmed as the source of either the
+ receive or the transmit clock. If /TRxC O/I (bit 2) is set to 0, these bits are ignored.
+ If the XTAL oscillator output is programmed to be echoed, and the XTAL oscillator is not enabled,
+ the /TRxC pin goes High. The DPLL signal that is echoed is the DPLL signal used by the receiver.
+ Hardware reset selects the XTAL oscillator as the output source*/
+ LOG((" TRxC clock source is: "));
+ switch (data & WR11_TRXSRC_SRC_MASK)
+ {
+ case WR11_TRXSRC_SRC_XTAL: LOG(("the Oscillator\n")); break;
+ case WR11_TRXSRC_SRC_TRA: LOG(("Transmit clock\n")); break;
+ case WR11_TRXSRC_SRC_BR: LOG(("Baudrate Generator\n")); break;
+ case WR11_TRXSRC_SRC_DPLL: LOG(("DPLL\n")); break;
+ default: logerror("Wrong!\n");/* Will not happen unless someone messes with the mask */
+ }
}
/*WR12 contains the lower byte of the time constant for the baud rate generator. The time constant
-can be changed at any time, but the new value does not take effect until the next time the time constant
-is loaded into the down counter. No attempt is made to synchronize the loading of the time
-constant into WR12 and WR13 with the clock driving the down counter. For this reason, it is
-advisable to disable the baud rate generator while the new time constant is loaded into WR12 and
-WR13. Ordinarily, this is done anyway to prevent a load of the down counter between the writing
-of the upper and lower bytes of the time constant.
-The formula for determining the appropriate time constant for a given baud is shown below, with
-the desired rate in bits per second and the BR clock period in seconds. This formula is derived
-because the counter decrements from N down to zero-plus-one-cycle for reloading the time constant.
-This is then fed to a toggle flip-flop to make the output a square wave.
-
- Time Constant = Clock Frequency / (2 * Desired Rate * Baud Rate Clock Period) - 2
-
+ can be changed at any time, but the new value does not take effect until the next time the time constant
+ is loaded into the down counter. No attempt is made to synchronize the loading of the time
+ constant into WR12 and WR13 with the clock driving the down counter. For this reason, it is
+ advisable to disable the baud rate generator while the new time constant is loaded into WR12 and
+ WR13. Ordinarily, this is done anyway to prevent a load of the down counter between the writing
+ of the upper and lower bytes of the time constant.
+ The formula for determining the appropriate time constant for a given baud is shown below, with
+ the desired rate in bits per second and the BR clock period in seconds. This formula is derived
+ because the counter decrements from N down to zero-plus-one-cycle for reloading the time constant.
+ This is then fed to a toggle flip-flop to make the output a square wave.
+
+ Time Constant = Clock Frequency / (2 * Desired Rate * Baud Rate Clock Period) - 2
+
*/
void z80scc_channel::do_sccreg_wr12(UINT8 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));
+ m_wr12 = 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. */
void z80scc_channel::do_sccreg_wr13(UINT8 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));
+ m_wr13 = 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));
}
/*
WR14 contains some miscellaneous control bits */
void z80scc_channel::do_sccreg_wr14(UINT8 data)
{
- switch (data & WR14_DPLL_CMD_MASK)
- {
- 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));
- break;
- case WR14_CMD_ESM:
+ switch (data & WR14_DPLL_CMD_MASK)
+ {
+ case WR14_CMD_NULL:
+ LOG(("Z80SCC \"%s\": %c : %s Misc Control Bits Null Command %02x\n", m_owner->tag(), 'A' + m_index, __func__, data));
+ break;
+ 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
incoming data stream. The action taken by the DPLL upon receipt of this command depends on the operating mode of
the DPLL. In NRZI mode, the output of the DPLL is High while the DPLL is waiting for an edge in the incoming data
@@ -1559,175 +1702,197 @@ 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
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.*/
- LOG(("Z80SCC \"%s\" Channel %c : %s Misc Control Bits Enter Search Mode Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
- break;
- case WR14_CMD_RMC:
-/* 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__));
- break;
- 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.*/
- LOG(("Z80SCC \"%s\" Channel %c : %s Misc Control Bits Disable DPLL Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
- break;
- case WR14_CMD_SS_BGR:
-/* 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__));
- break;
- 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
- 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__));
- break;
- 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
- 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__));
- break;
- 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.*/
- LOG(("Z80SCC \"%s\" Channel %c : %s Mics Control Bits Set NRZI Mode Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
- break;
- default:
- logerror("Z80SCC \"%s\" Channel %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
- m_wr14 = data;
+ LOG(("Z80SCC \"%s\": %c : %s Misc Control Bits Enter Search Mode Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
+ break;
+ case WR14_CMD_RMC:
+ /* Issuing this command disables the DPLL, resets the clock missing latches in RR10, and forces a continuous Search mode state */
+ LOG(("Z80SCC \"%s\": %c : %s Misc Control Bits Reset Missing Clocks Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
+ break;
+ 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.*/
+ LOG(("Z80SCC \"%s\": %c : %s Misc Control Bits Disable DPLL Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
+ break;
+ case WR14_CMD_SS_BGR:
+ /* Issuing this command forces the clock for the DPLL to come from the output of the BRG. */
+ LOG(("Z80SCC \"%s\": %c : %s Misc Control Bits Baudrate Generator Input DPLL Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
+ break;
+ 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
+ the state of the XTAL/no XTAL bit in WR11. This mode is selected by a channel or hardware reset*/
+ LOG(("Z80SCC \"%s\": %c : %s Misc Control Bits RTxC Input DPLL Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
+ break;
+ 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
+ data. (Manchester is decoded by placing the receiver in NRZ mode while the DPLL is in FM mode.)*/
+ LOG(("Z80SCC \"%s\": %c : %s Misc Control Bits Set FM Mode Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
+ break;
+ 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.*/
+ LOG(("Z80SCC \"%s\": %c : %s Mics Control Bits Set NRZI Mode Command - not implemented\n", m_owner->tag(), 'A' + m_index, __func__));
+ break;
+ default:
+ 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
+ m_wr14 = data;
}
/* WR15 is the External/Status Source Control register. If the External/Status interrupts are enabled
-as a group via WR1, bits in this register control which External/Status conditions cause an interrupt.
-Only the External/Status conditions that occur after the controlling bit is set to 1 cause an
-interrupt. This is true, even if an External/Status condition is pending at the time the bit is set*/
+ as a group via WR1, bits in this register control which External/Status conditions cause an interrupt.
+ Only the External/Status conditions that occur after the controlling bit is set to 1 cause an
+ 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)
{
- LOG(("Z80SCC \"%s\" Channel %c : %s External/Status Source Control Bits %02x - not implemented \n", m_owner->tag(), 'A' + m_index, __func__, data));
- m_wr15 = data;
+ LOG(("%s(%d) \"%s\": %c : External/Status Control Bits - not implemented\n",
+ FUNCNAME, data, m_owner->tag(), 'A' + m_index));
+ 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)
{
- UINT8 reg = m_wr0;
- UINT8 regmask = (WR0_REGISTER_MASK | m_ph);
+ UINT8 reg = m_uart->m_wr0_ptrbits; //m_wr0;
+ 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
-
- reg &= regmask;
+ m_uart->m_wr0_ptrbits = 0; // The "Point High" command is only valid for one access
+ reg &= regmask;
+
if (reg != 0)
{
// mask out register index
m_wr0 &= ~regmask;
}
-
- LOG(("%s(%02x) reg %02x, regmask %02x, WR0 %02x\n", __func__, data, reg, regmask, m_wr0));
-
- /* TODO. Sort out 80X30 & other SCC variants limitations in register access */
+
+ LOG(("\n%s(%02x) reg %02x, regmask %02x\n", FUNCNAME, data, reg, regmask));
+
+ /* TODO. Sort out 80X30 & other SCC variants limitations in register access */
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_WR2_INT_VECTOR: do_sccreg_wr2(data); break;
+ case REG_WR2_INT_VECTOR: do_sccreg_wr2(data); break;
case REG_WR3_RX_CONTROL:
- do_sioreg_wr3(data);
- update_serial();
- receive_register_reset();
- break;
+ do_sccreg_wr3(data);
+ update_serial();
+ receive_register_reset();
+ break;
case REG_WR4_RX_TX_MODES:
- do_sioreg_wr4(data);
- update_serial();
- transmit_register_reset();
- receive_register_reset();
- break;
+ do_sccreg_wr4(data);
+ update_serial();
+ transmit_register_reset();
+ receive_register_reset();
+ break;
case REG_WR5_TX_CONTROL:
- do_sioreg_wr5(data);
- update_serial();
- transmit_register_reset();
- update_rts();
- break;
- case REG_WR6_SYNC_OR_SDLC_A: do_sioreg_wr6(data); break;
- case REG_WR7_SYNC_OR_SDLC_F: do_sioreg_wr7(data); break;
- case REG_WR8_TRANSMIT_DATA: do_sccreg_wr8(data); break;
+ do_sccreg_wr5(data);
+ update_serial();
+ transmit_register_reset();
+ update_rts();
+ break;
+ case REG_WR6_SYNC_OR_SDLC_A: do_sccreg_wr6(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_WR9_MASTER_INT_CTRL: do_sccreg_wr9(data); break;
- case REG_WR10_MSC_RX_TX_CTRL: do_sccreg_wr10(data); break;
- case REG_WR11_CLOCK_MODES: do_sccreg_wr11(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_WR14_MISC_CTRL: do_sccreg_wr14(data); break;
- case REG_WR15_EXT_ST_INT_CTRL:
- LOG(("Z80SCC \"%s\" Channel %c : unsupported command: External/Status Control Bits %02x\n", m_owner->tag(), 'A' + m_index, data));
- break;
+ case REG_WR10_MSC_RX_TX_CTRL: do_sccreg_wr10(data); break;
+ case REG_WR11_CLOCK_MODES: do_sccreg_wr11(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_WR14_MISC_CTRL: do_sccreg_wr14(data); break;
+ case REG_WR15_EXT_ST_INT_CTRL:do_sccreg_wr15(data); break;
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);
}
}
//-------------------------------------------------
-// data_read - read data register from fifo
+// data_read - read data register from fifo
//-------------------------------------------------
UINT8 z80scc_channel::data_read()
{
UINT8 data = 0;
- if (m_rx_fifo_wp != m_rx_fifo_rp)
- {
- /* Special Receive Condition interrupts are generated after the character is read from
- the FIFO, not when the special condition is first detected. This is done so that when
- using receive interrupt on first or Special Condition or Special Condition Only, data is
- directly read out of the data FIFO without checking the status first. If a special condi-
- tion interrupted the CPU when first detected, it would be necessary to read RR1
- before each byte in the FIFO to determine which byte had the special condition.
- Therefore, by not generating the interrupt until after the byte has been read and then
- locking the FIFO, only one status read is necessary. A DMA can be used to do all data
- transfers (otherwise, it would be necessary to disable the DMA to allow the CPU to
- read the status on each byte). Consequently, since the special condition locks the
- FIFO to preserve the status, it is necessary to issue the Error Reset command to
- unlock it. Only the exit location of the FIFO is locked allowing more data to be
- received into the other bytes of the Receive FIFO.*/
+ LOG(("%s \"%s\": %c : Data Register Read: \n", FUNCNAME, m_owner->tag(), 'A' + m_index));
+ if (m_rx_fifo_wp != m_rx_fifo_rp)
+ {
+ /* Special Receive Condition interrupts are generated after the character is read from
+ the FIFO, not when the special condition is first detected. This is done so that when
+ using receive interrupt on first or Special Condition or Special Condition Only, data is
+ directly read out of the data FIFO without checking the status first. If a special condi-
+ tion interrupted the CPU when first detected, it would be necessary to read RR1
+ before each byte in the FIFO to determine which byte had the special condition.
+ Therefore, by not generating the interrupt until after the byte has been read and then
+ locking the FIFO, only one status read is necessary. A DMA can be used to do all data
+ transfers (otherwise, it would be necessary to disable the DMA to allow the CPU to
+ read the status on each byte). Consequently, since the special condition locks the
+ FIFO to preserve the status, it is necessary to issue the Error Reset command to
+ unlock it. Only the exit location of the FIFO is locked allowing more data to be
+ received into the other bytes of the Receive FIFO.*/
+
// load data from the FIFO
data = m_rx_fifo_rp_data();
-
- // load error status from the FIFO
+
+ // load error status from the FIFO
m_rr1 = (m_rr1 & ~(RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR)) | m_rx_error_fifo[m_rx_fifo_rp];
-
- // trigger interrup and lock the fifo if an error is present
- if (m_rr1 & (RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR))
- {
- switch (m_wr1 & WR1_RX_INT_MODE_MASK)
- {
- case WR1_RX_INT_FIRST:
- if (!m_rx_first)
- {
- m_uart->trigger_interrupt(m_index, INT_SPECIAL);
- }
- break;
-
- case WR1_RX_INT_ALL_PARITY:
- case WR1_RX_INT_ALL:
- m_uart->trigger_interrupt(m_index, INT_SPECIAL);
- break;
- }
- }
- else
+
+ // trigger interrup and lock the fifo if an error is present
+ if (m_rr1 & (RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR))
+ {
+ switch (m_wr1 & WR1_RX_INT_MODE_MASK)
+ {
+ case WR1_RX_INT_FIRST:
+ if (!m_rx_first)
{
- // decrease FIFO pointer
- m_rx_fifo_rp_step();
+ m_uart->trigger_interrupt(m_index, INT_SPECIAL);
}
- }
+ break;
+
+ case WR1_RX_INT_ALL_PARITY:
+ case WR1_RX_INT_ALL:
+ m_uart->trigger_interrupt(m_index, INT_SPECIAL);
+ break;
+ }
+ }
else
{
- logerror("data_read: Attempt to read out character from empty FIFO\n");
+ // decrease FIFO pointer
+ m_rx_fifo_rp_step();
}
+ }
+ 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");
+ }
- 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;
}
@@ -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)
{
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);
@@ -1778,28 +1947,27 @@ void z80scc_channel::data_write(UINT8 data)
m_rr0 |= RR0_TX_BUFFER_EMPTY;
if (m_wr1 & WR1_TX_INT_ENABLE)
- {
+ {
m_uart->trigger_interrupt(m_index, INT_TRANSMIT);
- }
+ }
}
else
{
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;
-
- LOG(("Z80SCC \"%s\" Channel %c : Data Register Write '%02x'\n", m_owner->tag(), 'A' + m_index, data));
}
//-------------------------------------------------
-// receive_data - receive data word into fifo
+// receive_data - receive data word into fifo
//-------------------------------------------------
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 ||
( (m_rx_fifo_wp + 1 == m_rx_fifo_sz) && (m_rx_fifo_rp == 0) ))
@@ -1845,12 +2013,12 @@ void z80scc_channel::receive_data(UINT8 data)
//-------------------------------------------------
-// cts_w - clear to send handler
+// cts_w - clear to send handler
//-------------------------------------------------
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)
{
@@ -1880,17 +2048,16 @@ WRITE_LINE_MEMBER( z80scc_channel::cts_w )
}
}
}
- // m_rr0 &= ~RR0_CTS; // Remove, just to test
}
//-------------------------------------------------
-// dcd_w - data carrier detected handler
+// dcd_w - data carrier detected handler
//-------------------------------------------------
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)
{
@@ -1923,12 +2090,12 @@ WRITE_LINE_MEMBER( z80scc_channel::dcd_w )
//-------------------------------------------------
-// ri_w - ring indicator handler
+// ri_w - ring indicator handler
//-------------------------------------------------
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)
{
@@ -1955,55 +2122,60 @@ WRITE_LINE_MEMBER( z80scc_channel::ri_w )
}
//-------------------------------------------------
-// sync_w - sync handler
+// sync_w - sync handler
//-------------------------------------------------
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));
}
//-------------------------------------------------
-// rxc_w - receive clock
+// rxc_w - receive clock
//-------------------------------------------------
WRITE_LINE_MEMBER( z80scc_channel::rxc_w )
{
- //LOG(("Z80SCC \"%s\" Channel %c : Receiver Clock Pulse\n", m_owner->tag(), m_index + 'A'));
- int clocks = get_clock_mode();
- if (clocks == 1)
- rx_clock_w(state);
- else if(state)
+ //LOG(("Z80SCC \"%s\": %c : Receiver Clock Pulse\n", m_owner->tag(), m_index + 'A'));
+ if (m_wr3 & WR3_RX_ENABLE)
{
- rx_clock_w(m_rx_clock < clocks/2);
-
- m_rx_clock++;
- if (m_rx_clock == clocks)
- m_rx_clock = 0;
-
+ int clocks = get_clock_mode();
+ if (clocks == 1)
+ rx_clock_w(state);
+ else if(state)
+ {
+ rx_clock_w(m_rx_clock < clocks/2);
+
+ m_rx_clock++;
+ if (m_rx_clock == clocks)
+ m_rx_clock = 0;
+
+ }
}
}
//-------------------------------------------------
-// txc_w - transmit clock
+// txc_w - transmit clock
//-------------------------------------------------
WRITE_LINE_MEMBER( z80scc_channel::txc_w )
{
- //LOG(("Z80SCC \"%s\" Channel %c : Transmitter Clock Pulse\n", m_owner->tag(), m_index + 'A'));
- int clocks = get_clock_mode();
- if (clocks == 1)
- tx_clock_w(state);
- else if(state)
+ //LOG(("Z80SCC \"%s\": %c : Transmitter Clock Pulse\n", m_owner->tag(), m_index + 'A'));
+ if (m_wr5 & WR5_TX_ENABLE)
{
- tx_clock_w(m_tx_clock < clocks/2);
-
- m_tx_clock++;
- if (m_tx_clock == clocks)
- m_tx_clock = 0;
-
+ int clocks = get_clock_mode();
+ if (clocks == 1)
+ tx_clock_w(state);
+ else if(state)
+ {
+ tx_clock_w(m_tx_clock < clocks/2);
+
+ m_tx_clock++;
+ if (m_tx_clock == clocks)
+ m_tx_clock = 0;
+ }
}
}
//-------------------------------------------------
-// update_serial -
+// update_serial -
//-------------------------------------------------
void z80scc_channel::update_serial()
{
@@ -2030,24 +2202,24 @@ void z80scc_channel::update_serial()
if (m_rxc > 0)
{
set_rcv_rate(m_rxc / clocks);
- LOG((" - Receiver clock: %d mode: %d rate: %d/%xh\n", m_rxc, clocks, m_rxc / clocks, m_rxc / clocks));
+ LOG((" - Receiver clock: %d mode: %d rate: %d/%xh\n", m_rxc, clocks, m_rxc / clocks, m_rxc / clocks));
}
if (m_txc > 0)
{
set_tra_rate(m_txc / clocks);
- LOG((" - Transmit clock: %d mode: %d rate: %d/%xh\n", m_rxc, clocks, m_rxc / clocks, m_rxc / clocks));
+ LOG((" - Transmit clock: %d mode: %d rate: %d/%xh\n", m_rxc, clocks, m_rxc / clocks, m_rxc / clocks));
}
}
//-------------------------------------------------
-// set_dtr -
+// set_dtr -
//-------------------------------------------------
void z80scc_channel::set_dtr(int state)
{
+ LOG(("%s(%d)\n", FUNCNAME, 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)
m_uart->m_out_dtra_cb(m_dtr);
else
@@ -2057,12 +2229,11 @@ void z80scc_channel::set_dtr(int state)
//-------------------------------------------------
-// write_rx - called by terminal through rs232/diserial
-// when character is sent to board
+// write_rx - called by terminal through rs232/diserial
+// when character is sent to board
//-------------------------------------------------
WRITE_LINE_MEMBER(z80scc_channel::write_rx)
{
- // printf("%c", state ? '+' : 'o');
m_rxd = state;
//only use rx_w when self-clocked
if(m_rxc)
diff --git a/src/devices/machine/z80scc.h b/src/devices/machine/z80scc.h
index 07e95cac051..134e7993037 100644
--- a/src/devices/machine/z80scc.h
+++ b/src/devices/machine/z80scc.h
@@ -2,31 +2,31 @@
// copyright-holders:Joakim Larsson Edstrom
/***************************************************************************
- Z80-SCC Serial Communications Controller emulation
+ Z80-SCC Serial Communications Controller emulation
****************************************************************************
- _____ _____ _____ _____
- AD1 1|* \_/ |40 AD0 D1 1|* \_/ |40 D0
- AD3 2| |39 AD2 D3 2| |39 D2
- AD5 3| |38 AD4 D5 3| |38 D4
- AD7 4| |37 AD6 D7 4| |37 D6
- _INT 5| |36 _DS _INT 5| |36 _RD
- IEO 6| |35 _AS IEO 6| |35 _WR
- IEI 7| |34 R/_W IEI 7| |34 B/_A
- _INTACK 8| |33 _CS0 _INTACK 8| |33 _CE
- VCC 9| |32 CS1 VCC 9| |32 C/_D
- _W//REQA 10| |31 GND _W//REQA 10| |31 GND
- _SYNCA 11| Z8030 |30 _W/_REQ _SYNCA 11| Z8530 |30 _W/_REQB
- _RTxCA 12| Z80C30 |29 _SYNCB _RTxCA 12| Z85C30 |29 _SYNCB
- RxDA 13| Z80230 |28 _RTxCB RxDA 13| Z85230 |28 _RTxCB
- _TRxCA 14| |27 RxDB _TRxCA 14| |27 RxDB
- TxDA 15| |26 _TRxCB TxDA 15| |26 _TRxCB
- _DTR//REQA 16| |25 TxDB _DTR//REQA 16| |25 TxDB
- _RTSA 17| |24 _DTR/_REQB _RTSA 17| |24 _DTR/_REQB
- _CTSA 18| |23 _RTSB _CTSA 18| |23 _RTSB
- _DCDA 19| |22 _CTSB _DCDA 19| |22 _CTSB
- PCLK 20|_____________|21 _DCDB PCLK 20|_____________|21 _DCDB
- ZBUS Universal Bus
+ _____ _____ _____ _____
+ AD1 1|* \_/ |40 AD0 D1 1|* \_/ |40 D0
+ AD3 2| |39 AD2 D3 2| |39 D2
+ AD5 3| |38 AD4 D5 3| |38 D4
+ AD7 4| |37 AD6 D7 4| |37 D6
+ _INT 5| |36 _DS _INT 5| |36 _RD
+ IEO 6| |35 _AS IEO 6| |35 _WR
+ IEI 7| |34 R/_W IEI 7| |34 B/_A
+ _INTACK 8| |33 _CS0 _INTACK 8| |33 _CE
+ VCC 9| |32 CS1 VCC 9| |32 C/_D
+ _W//REQA 10| |31 GND _W//REQA 10| |31 GND
+ _SYNCA 11| Z8030 |30 _W/_REQ _SYNCA 11| Z8530 |30 _W/_REQB
+ _RTxCA 12| Z80C30 |29 _SYNCB _RTxCA 12| Z85C30 |29 _SYNCB
+ RxDA 13| Z80230 |28 _RTxCB RxDA 13| Z85230 |28 _RTxCB
+ _TRxCA 14| |27 RxDB _TRxCA 14| |27 RxDB
+ TxDA 15| |26 _TRxCB TxDA 15| |26 _TRxCB
+ _DTR//REQA 16| |25 TxDB _DTR//REQA 16| |25 TxDB
+ _RTSA 17| |24 _DTR/_REQB _RTSA 17| |24 _DTR/_REQB
+ _CTSA 18| |23 _RTSB _CTSA 18| |23 _RTSB
+ _DCDA 19| |22 _CTSB _DCDA 19| |22 _CTSB
+ PCLK 20|_____________|21 _DCDB PCLK 20|_____________|21 _DCDB
+ ZBUS Universal Bus
***************************************************************************/
@@ -38,7 +38,7 @@
#include "cpu/z80/z80daisy.h"
//**************************************************************************
-// DEVICE CONFIGURATION MACROS
+// DEVICE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_Z80SCC_ADD(_tag, _clock, _rxa, _txa, _rxb, _txb) \
@@ -101,14 +101,16 @@
//**************************************************************************
-// TYPE DEFINITIONS
+// TYPE DEFINITIONS
//**************************************************************************
// ======================> z80scc_channel
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;
@@ -126,41 +128,42 @@ public:
virtual void rcv_callback();
virtual void rcv_complete();
- // read register handlers
- UINT8 do_sccreg_rr0();
- UINT8 do_sccreg_rr1();
- UINT8 do_sccreg_rr2();
- UINT8 do_sccreg_rr3();
- UINT8 do_sccreg_rr4();
- UINT8 do_sccreg_rr5();
- UINT8 do_sccreg_rr6();
- UINT8 do_sccreg_rr7();
- UINT8 do_sccreg_rr8();
- UINT8 do_sccreg_rr9();
- UINT8 do_sccreg_rr10();
- UINT8 do_sccreg_rr11();
- UINT8 do_sccreg_rr12();
- UINT8 do_sccreg_rr13();
- UINT8 do_sccreg_rr14();
- UINT8 do_sccreg_rr15();
-
- // write register handlers
- void do_sccreg_wr0(UINT8 data);
- void do_sccreg_wr1(UINT8 data);
- void do_sccreg_wr2(UINT8 data);
- void do_sccreg_wr3(UINT8 data);
- void do_sccreg_wr4(UINT8 data);
- void do_sccreg_wr5(UINT8 data);
- void do_sccreg_wr6(UINT8 data);
- void do_sccreg_wr7(UINT8 data);
- void do_sccreg_wr8(UINT8 data);
- void do_sccreg_wr9(UINT8 data);
- void do_sccreg_wr10(UINT8 data);
- void do_sccreg_wr11(UINT8 data);
- void do_sccreg_wr12(UINT8 data);
- void do_sccreg_wr13(UINT8 data);
- void do_sccreg_wr14(UINT8 data);
- void do_sccreg_wr15(UINT8 data);
+ // read register handlers
+ UINT8 do_sccreg_rr0();
+ UINT8 do_sccreg_rr1();
+ UINT8 do_sccreg_rr2();
+ UINT8 do_sccreg_rr3();
+ UINT8 do_sccreg_rr4();
+ UINT8 do_sccreg_rr5();
+ UINT8 do_sccreg_rr6();
+ UINT8 do_sccreg_rr7();
+ UINT8 do_sccreg_rr8();
+ UINT8 do_sccreg_rr9();
+ UINT8 do_sccreg_rr10();
+ UINT8 do_sccreg_rr11();
+ UINT8 do_sccreg_rr12();
+ UINT8 do_sccreg_rr13();
+ UINT8 do_sccreg_rr14();
+ UINT8 do_sccreg_rr15();
+
+ // write register handlers
+ void do_sccreg_wr0(UINT8 data);
+ void do_sccreg_wr0_resets(UINT8 data);
+ void do_sccreg_wr1(UINT8 data);
+ void do_sccreg_wr2(UINT8 data);
+ void do_sccreg_wr3(UINT8 data);
+ void do_sccreg_wr4(UINT8 data);
+ void do_sccreg_wr5(UINT8 data);
+ void do_sccreg_wr6(UINT8 data);
+ void do_sccreg_wr7(UINT8 data);
+ void do_sccreg_wr8(UINT8 data);
+ void do_sccreg_wr9(UINT8 data);
+ void do_sccreg_wr10(UINT8 data);
+ void do_sccreg_wr11(UINT8 data);
+ void do_sccreg_wr12(UINT8 data);
+ void do_sccreg_wr13(UINT8 data);
+ void do_sccreg_wr14(UINT8 data);
+ void do_sccreg_wr15(UINT8 data);
UINT8 control_read();
void control_write(UINT8 data);
@@ -170,7 +173,7 @@ public:
void receive_data(UINT8 data);
void m_rx_fifo_rp_step();
- UINT8 m_rx_fifo_rp_data();
+ UINT8 m_rx_fifo_rp_data();
DECLARE_WRITE_LINE_MEMBER( write_rx );
DECLARE_WRITE_LINE_MEMBER( cts_w );
@@ -184,19 +187,17 @@ public:
int m_txc;
// Register state
- // read registers enum
-#if 0 //defined by z80sio.h
+ // read registers enum
UINT8 m_rr0; // REG_RR0_STATUS
UINT8 m_rr1; // REG_RR1_SPEC_RCV_COND
UINT8 m_rr2; // REG_RR2_INTERRUPT_VECT
-#endif
UINT8 m_rr3; // REG_RR3_INTERUPPT_PEND
UINT8 m_rr4; // REG_RR4_WR4_OR_RR0
UINT8 m_rr5; // REG_RR5_WR5_OR_RR0
UINT8 m_rr6; // REG_RR6_LSB_OR_RR2
UINT8 m_rr7; // REG_RR7_MSB_OR_RR3
UINT8 m_rr8; // REG_RR8_RECEIVE_DATA
- UINT8 m_rr9; // REG_RR9_WR3_OR_RR13
+ UINT8 m_rr9; // REG_RR9_WR3_OR_RR13
UINT8 m_rr10; // REG_RR10_MISC_STATUS
UINT8 m_rr11; // REG_RR11_WR10_OR_RR15
UINT8 m_rr12; // REG_RR12_LO_TIME_CONST
@@ -204,8 +205,7 @@ public:
UINT8 m_rr14; // REG_RR14_WR7_OR_R10
UINT8 m_rr15; // REG_RR15_WR15_EXT_STAT
- // write registers enum
-#if 0 //defined by z80sio.h
+ // write registers enum
UINT8 m_wr0; // REG_WR0_COMMAND_REGPT
UINT8 m_wr1; // REG_WR1_INT_DMA_ENABLE
UINT8 m_wr2; // REG_WR2_INT_VECTOR
@@ -214,7 +214,6 @@ public:
UINT8 m_wr5; // REG_WR5_TX_CONTROL
UINT8 m_wr6; // REG_WR6_SYNC_OR_SDLC_A
UINT8 m_wr7; // REG_WR7_SYNC_OR_SDLC_F
-#endif
UINT8 m_wr8; // REG_WR8_TRANSMIT_DATA
UINT8 m_wr9; // REG_WR9_MASTER_INT_CTRL
UINT8 m_wr10; // REG_WR10_MSC_RX_TX_CTRL
@@ -230,288 +229,288 @@ protected:
{
INT_TRANSMIT = 0,
INT_EXTERNAL = 1,
- INT_RECEIVE = 2,
- INT_SPECIAL = 3
+ INT_RECEIVE = 2,
+ INT_SPECIAL = 3
};
- // Read registers
- enum
- {
- REG_RR0_STATUS = 0, // SIO
- REG_RR1_SPEC_RCV_COND = 1, // SIO
- REG_RR2_INTERRUPT_VECT = 2, // SIO
- REG_RR3_INTERUPPT_PEND = 3,
- REG_RR4_WR4_OR_RR0 = 4,
- REG_RR5_WR5_OR_RR0 = 5,
- REG_RR6_LSB_OR_RR2 = 6,
- REG_RR7_MSB_OR_RR3 = 7,
- REG_RR8_RECEIVE_DATA = 8,
- REG_RR9_WR3_OR_RR13 = 9,
- REG_RR10_MISC_STATUS = 10,
- REG_RR11_WR10_OR_RR15 = 11,
- REG_RR12_LO_TIME_CONST = 12,
- REG_RR13_HI_TIME_CONST = 13,
- REG_RR14_WR7_OR_R10 = 14,
- REG_RR15_WR15_EXT_STAT = 15
- };
-
- // Write registers
- enum
- {
- REG_WR0_COMMAND_REGPT = 0, // SIO
- REG_WR1_INT_DMA_ENABLE = 1, // SIO
- REG_WR2_INT_VECTOR = 2, // SIO
- REG_WR3_RX_CONTROL = 3, // SIO
- REG_WR4_RX_TX_MODES = 4, // SIO
- REG_WR5_TX_CONTROL = 5, // SIO
- REG_WR6_SYNC_OR_SDLC_A = 6, // SIO
- REG_WR7_SYNC_OR_SDLC_F = 7, // SIO
- REG_WR8_TRANSMIT_DATA = 8,
- REG_WR9_MASTER_INT_CTRL = 9,
- REG_WR10_MSC_RX_TX_CTRL = 10,
- REG_WR11_CLOCK_MODES = 11,
- REG_WR12_LO_BAUD_GEN = 12,
- REG_WR13_HI_BAUD_GEN = 13,
- REG_WR14_MISC_CTRL = 14,
- REG_WR15_EXT_ST_INT_CTRL= 15
- };
-
+ // Read registers
+ enum
+ {
+ REG_RR0_STATUS = 0, // SIO
+ REG_RR1_SPEC_RCV_COND = 1, // SIO
+ REG_RR2_INTERRUPT_VECT = 2, // SIO
+ REG_RR3_INTERUPPT_PEND = 3,
+ REG_RR4_WR4_OR_RR0 = 4,
+ REG_RR5_WR5_OR_RR0 = 5,
+ REG_RR6_LSB_OR_RR2 = 6,
+ REG_RR7_MSB_OR_RR3 = 7,
+ REG_RR8_RECEIVE_DATA = 8,
+ REG_RR9_WR3_OR_RR13 = 9,
+ REG_RR10_MISC_STATUS = 10,
+ REG_RR11_WR10_OR_RR15 = 11,
+ REG_RR12_LO_TIME_CONST = 12,
+ REG_RR13_HI_TIME_CONST = 13,
+ REG_RR14_WR7_OR_R10 = 14,
+ REG_RR15_WR15_EXT_STAT = 15
+ };
+
+ // Write registers
enum
{
- RR0_RX_CHAR_AVAILABLE = 0x01, // SIO bit
- RR0_ZC = 0x02, // SCC bit
- RR0_TX_BUFFER_EMPTY = 0x04, // SIO
- RR0_DCD = 0x08, // SIO
- RR0_RI = 0x10, // DART bit? TODO: investigate function and remove
- RR0_SYNC_HUNT = 0x10, // SIO bit, not supported
- RR0_CTS = 0x20, // SIO bit
- RR0_TX_UNDERRUN = 0x40, // SIO bit, not supported
- RR0_BREAK_ABORT = 0x80 // SIO bit, not supported
+ REG_WR0_COMMAND_REGPT = 0, // SIO
+ REG_WR1_INT_DMA_ENABLE = 1, // SIO
+ REG_WR2_INT_VECTOR = 2, // SIO
+ REG_WR3_RX_CONTROL = 3, // SIO
+ REG_WR4_RX_TX_MODES = 4, // SIO
+ REG_WR5_TX_CONTROL = 5, // SIO
+ REG_WR6_SYNC_OR_SDLC_A = 6, // SIO
+ REG_WR7_SYNC_OR_SDLC_F = 7, // SIO
+ REG_WR8_TRANSMIT_DATA = 8,
+ REG_WR9_MASTER_INT_CTRL = 9,
+ REG_WR10_MSC_RX_TX_CTRL = 10,
+ REG_WR11_CLOCK_MODES = 11,
+ REG_WR12_LO_BAUD_GEN = 12,
+ REG_WR13_HI_BAUD_GEN = 13,
+ REG_WR14_MISC_CTRL = 14,
+ REG_WR15_EXT_ST_INT_CTRL= 15
};
enum
{
- RR1_ALL_SENT = 0x01, // SIO/SCC bit
- RR1_RESIDUE_CODE_MASK = 0x0e, // SIO/SCC bits, not supported
- RR1_PARITY_ERROR = 0x10, // SIO/SCC bits
- RR1_RX_OVERRUN_ERROR = 0x20, // SIO/SCC bits
- RR1_CRC_FRAMING_ERROR = 0x40, // SIO/SCC bits
- RR1_END_OF_FRAME = 0x80 // SIO/SCC bits, not supported
+ RR0_RX_CHAR_AVAILABLE = 0x01, // SIO bit
+ RR0_ZC = 0x02, // SCC bit
+ RR0_TX_BUFFER_EMPTY = 0x04, // SIO
+ RR0_DCD = 0x08, // SIO
+ RR0_RI = 0x10, // DART bit? TODO: investigate function and remove
+ RR0_SYNC_HUNT = 0x10, // SIO bit, not supported
+ RR0_CTS = 0x20, // SIO bit
+ RR0_TX_UNDERRUN = 0x40, // SIO bit, not supported
+ RR0_BREAK_ABORT = 0x80 // SIO bit, not supported
};
- enum
- { // TODO: overload SIO functionality
- RR2_INT_VECTOR_MASK = 0xff, // SCC channel A, SIO channel B (special case)
- RR2_INT_VECTOR_V1 = 0x02, // SIO (special case) /SCC Channel B
- RR2_INT_VECTOR_V2 = 0x04, // SIO (special case) /SCC Channel B
- RR2_INT_VECTOR_V3 = 0x08 // SIO (special case) /SCC Channel B
- };
-
- enum
- {
- RR3_CHANB_EXT_IP = 0x01, // SCC IP pending registers
- RR3_CHANB_TX_IP = 0x02, // only read in Channel A (for both channels)
- RR3_CHANB_RX_IP = 0x04, // channel B return all zero
- RR3_CHANA_EXT_IP = 0x08,
- RR3_CHANA_TX_IP = 0x10,
- RR3_CHANA_RX_IP = 0x20
- };
+ enum
+ {
+ RR1_ALL_SENT = 0x01, // SIO/SCC bit
+ RR1_RESIDUE_CODE_MASK = 0x0e, // SIO/SCC bits, not supported
+ RR1_PARITY_ERROR = 0x10, // SIO/SCC bits
+ RR1_RX_OVERRUN_ERROR = 0x20, // SIO/SCC bits
+ RR1_CRC_FRAMING_ERROR = 0x40, // SIO/SCC bits
+ RR1_END_OF_FRAME = 0x80 // SIO/SCC bits, not supported
+ };
+ enum
+ { // TODO: overload SIO functionality
+ RR2_INT_VECTOR_MASK = 0xff, // SCC channel A, SIO channel B (special case)
+ RR2_INT_VECTOR_V1 = 0x02, // SIO (special case) /SCC Channel B
+ RR2_INT_VECTOR_V2 = 0x04, // SIO (special case) /SCC Channel B
+ RR2_INT_VECTOR_V3 = 0x08 // SIO (special case) /SCC Channel B
+ };
+
+ enum
+ {
+ RR3_CHANB_EXT_IP = 0x01, // SCC IP pending registers
+ RR3_CHANB_TX_IP = 0x02, // only read in Channel A (for both channels)
+ RR3_CHANB_RX_IP = 0x04, // channel B return all zero
+ RR3_CHANA_EXT_IP = 0x08,
+ RR3_CHANA_TX_IP = 0x10,
+ RR3_CHANA_RX_IP = 0x20
+ };
+
enum // Universal Bus WR0 commands for 85X30
{
- WR0_REGISTER_MASK = 0x07,
- WR0_COMMAND_MASK = 0x38, // COMMANDS
- WR0_NULL = 0x00, // 0 0 0
- WR0_POINT_HIGH = 0x08, // 0 0 1
- WR0_RESET_EXT_STATUS = 0x10, // 0 1 0
- WR0_SEND_ABORT = 0x18, // 0 1 1
- WR0_ENABLE_INT_NEXT_RX = 0x20, // 1 0 0
- WR0_RESET_TX_INT = 0x28, // 1 0 1
- WR0_ERROR_RESET = 0x30, // 1 1 0
- WR0_RESET_HIGHEST_IUS = 0x38, // 1 1 1
- WR0_CRC_RESET_CODE_MASK = 0xc0, // RESET
- WR0_CRC_RESET_NULL = 0x00, // 0 0
- WR0_CRC_RESET_RX = 0x40, // 0 1
- WR0_CRC_RESET_TX = 0x80, // 1 0
+ WR0_REGISTER_MASK = 0x07,
+ WR0_COMMAND_MASK = 0x38, // COMMANDS
+ WR0_NULL = 0x00, // 0 0 0
+ WR0_POINT_HIGH = 0x08, // 0 0 1
+ WR0_RESET_EXT_STATUS = 0x10, // 0 1 0
+ WR0_SEND_ABORT = 0x18, // 0 1 1
+ WR0_ENABLE_INT_NEXT_RX = 0x20, // 1 0 0
+ WR0_RESET_TX_INT = 0x28, // 1 0 1
+ WR0_ERROR_RESET = 0x30, // 1 1 0
+ WR0_RESET_HIGHEST_IUS = 0x38, // 1 1 1
+ WR0_CRC_RESET_CODE_MASK = 0xc0, // RESET
+ WR0_CRC_RESET_NULL = 0x00, // 0 0
+ WR0_CRC_RESET_RX = 0x40, // 0 1
+ WR0_CRC_RESET_TX = 0x80, // 1 0
WR0_CRC_RESET_TX_UNDERRUN = 0xc0 // 1 1
};
enum // ZBUS WR0 commands or 80X30
{
- WR0_Z_COMMAND_MASK = 0x38, // COMMANDS
- WR0_Z_NULL_1 = 0x00, // 0 0 0
- WR0_Z_NULL_2 = 0x08, // 0 0 1
- WR0_Z_RESET_EXT_STATUS = 0x10, // 0 1 0
- WR0_Z_SEND_ABORT = 0x18, // 0 1 1
- WR0_Z_ENABLE_INT_NEXT_RX = 0x20, // 1 0 0
- WR0_Z_RESET_TX_INT = 0x28, // 1 0 1
- WR0_Z_ERROR_RESET = 0x30, // 1 1 0
- WR0_Z_RESET_HIGHEST_IUS = 0x38, // 1 1 1
- WR0_Z_SHIFT_MASK = 0x03, // SHIFT mode SDLC chan B
- WR0_Z_SEL_SHFT_LEFT = 0x02, // 1 0
- WR0_Z_SEL_SHFT_RIGHT = 0x03 // 1 1
- };
+ WR0_Z_COMMAND_MASK = 0x38, // COMMANDS
+ WR0_Z_NULL_1 = 0x00, // 0 0 0
+ WR0_Z_NULL_2 = 0x08, // 0 0 1
+ WR0_Z_RESET_EXT_STATUS = 0x10, // 0 1 0
+ WR0_Z_SEND_ABORT = 0x18, // 0 1 1
+ WR0_Z_ENABLE_INT_NEXT_RX = 0x20, // 1 0 0
+ WR0_Z_RESET_TX_INT = 0x28, // 1 0 1
+ WR0_Z_ERROR_RESET = 0x30, // 1 1 0
+ WR0_Z_RESET_HIGHEST_IUS = 0x38, // 1 1 1
+ WR0_Z_SHIFT_MASK = 0x03, // SHIFT mode SDLC chan B
+ WR0_Z_SEL_SHFT_LEFT = 0x02, // 1 0
+ WR0_Z_SEL_SHFT_RIGHT = 0x03 // 1 1
+ };
enum
{
- WR1_EXT_INT_ENABLE = 0x01,
- WR1_TX_INT_ENABLE = 0x02,
- WR1_PARITY_IS_SPEC_COND = 0x04,
- WR1_RX_INT_MODE_MASK = 0x18,
- WR1_RX_INT_DISABLE = 0x00,
- WR1_RX_INT_FIRST = 0x08,
- WR1_RX_INT_ALL_PARITY = 0x10, // not supported
- WR1_RX_INT_ALL = 0x18,
- WR1_WRDY_ON_RX_TX = 0x20, // not supported
- WR1_WRDY_FUNCTION = 0x40, // not supported
- WR1_WRDY_ENABLE = 0x80 // not supported
+ WR1_EXT_INT_ENABLE = 0x01,
+ WR1_TX_INT_ENABLE = 0x02,
+ WR1_PARITY_IS_SPEC_COND = 0x04,
+ WR1_RX_INT_MODE_MASK = 0x18,
+ WR1_RX_INT_DISABLE = 0x00,
+ WR1_RX_INT_FIRST = 0x08,
+ WR1_RX_INT_ALL_PARITY = 0x10, // not supported
+ WR1_RX_INT_ALL = 0x18,
+ WR1_WRDY_ON_RX_TX = 0x20, // not supported
+ WR1_WRDY_FUNCTION = 0x40, // not supported
+ WR1_WRDY_ENABLE = 0x80 // not supported
};
enum
{
- WR3_RX_ENABLE = 0x01,
+ WR3_RX_ENABLE = 0x01,
WR3_SYNC_CHAR_LOAD_INHIBIT= 0x02, // not supported
- WR3_ADDRESS_SEARCH_MODE = 0x04, // not supported
- WR3_RX_CRC_ENABLE = 0x08, // not supported
- WR3_ENTER_HUNT_PHASE = 0x10, // not supported
- WR3_AUTO_ENABLES = 0x20,
- WR3_RX_WORD_LENGTH_MASK = 0xc0,
- WR3_RX_WORD_LENGTH_5 = 0x00,
- WR3_RX_WORD_LENGTH_7 = 0x40,
- WR3_RX_WORD_LENGTH_6 = 0x80,
- WR3_RX_WORD_LENGTH_8 = 0xc0
+ WR3_ADDRESS_SEARCH_MODE = 0x04, // not supported
+ WR3_RX_CRC_ENABLE = 0x08, // not supported
+ WR3_ENTER_HUNT_PHASE = 0x10, // not supported
+ WR3_AUTO_ENABLES = 0x20,
+ WR3_RX_WORD_LENGTH_MASK = 0xc0,
+ WR3_RX_WORD_LENGTH_5 = 0x00,
+ WR3_RX_WORD_LENGTH_7 = 0x40,
+ WR3_RX_WORD_LENGTH_6 = 0x80,
+ WR3_RX_WORD_LENGTH_8 = 0xc0
+ };
+
+ enum
+ {
+ WR4_PARITY_ENABLE = 0x01,
+ WR4_PARITY_EVEN = 0x02,
+ WR4_STOP_BITS_MASK = 0x0c,
+ WR4_STOP_BITS_1 = 0x04,
+ WR4_STOP_BITS_1_5 = 0x08, // not supported
+ WR4_STOP_BITS_2 = 0x0c,
+ WR4_SYNC_MODE_MASK = 0x30, // not supported
+ WR4_SYNC_MODE_8_BIT = 0x00, // not supported
+ WR4_SYNC_MODE_16_BIT = 0x10, // not supported
+ WR4_SYNC_MODE_SDLC = 0x20, // not supported
+ WR4_SYNC_MODE_EXT = 0x30, // not supported
+ WR4_CLOCK_RATE_MASK = 0xc0,
+ WR4_CLOCK_RATE_X1 = 0x00,
+ WR4_CLOCK_RATE_X16 = 0x40,
+ WR4_CLOCK_RATE_X32 = 0x80,
+ WR4_CLOCK_RATE_X64 = 0xc0
+ };
+
+ enum
+ {
+ WR5_TX_CRC_ENABLE = 0x01, // not supported
+ WR5_RTS = 0x02,
+ WR5_CRC16 = 0x04, // not supported
+ WR5_TX_ENABLE = 0x08,
+ WR5_SEND_BREAK = 0x10,
+ WR5_TX_WORD_LENGTH_MASK = 0x60,
+ WR5_TX_WORD_LENGTH_5 = 0x00,
+ WR5_TX_WORD_LENGTH_6 = 0x40,
+ WR5_TX_WORD_LENGTH_7 = 0x20,
+ WR5_TX_WORD_LENGTH_8 = 0x60,
+ WR5_DTR = 0x80
};
+ /* SCC specifics */
enum
{
- WR4_PARITY_ENABLE = 0x01,
- WR4_PARITY_EVEN = 0x02,
- WR4_STOP_BITS_MASK = 0x0c,
- WR4_STOP_BITS_1 = 0x04,
- WR4_STOP_BITS_1_5 = 0x08, // not supported
- WR4_STOP_BITS_2 = 0x0c,
- WR4_SYNC_MODE_MASK = 0x30, // not supported
- WR4_SYNC_MODE_8_BIT = 0x00, // not supported
- WR4_SYNC_MODE_16_BIT = 0x10, // not supported
- WR4_SYNC_MODE_SDLC = 0x20, // not supported
- WR4_SYNC_MODE_EXT = 0x30, // not supported
- WR4_CLOCK_RATE_MASK = 0xc0,
- WR4_CLOCK_RATE_X1 = 0x00,
- WR4_CLOCK_RATE_X16 = 0x40,
- WR4_CLOCK_RATE_X32 = 0x80,
- WR4_CLOCK_RATE_X64 = 0xc0
+ WR9_CMD_MASK = 0xC0,
+ WR9_CMD_NORESET = 0x00,
+ WR9_CMD_CHNB_RESET = 0x40,
+ WR9_CMD_CHNA_RESET = 0x80,
+ WR9_CMD_HW_RESET = 0xC0,
+ WR9_BIT_VIS = 0x01,
+ WR9_BIT_NV = 0x02,
+ WR9_BIT_DLC = 0x04,
+ WR9_BIT_MIE = 0x08,
+ WR9_BIT_SHSL = 0x10,
+ WR9_BIT_IACK = 0x20
};
enum
{
- WR5_TX_CRC_ENABLE = 0x01, // not supported
- WR5_RTS = 0x02,
- WR5_CRC16 = 0x04, // not supported
- WR5_TX_ENABLE = 0x08,
- WR5_SEND_BREAK = 0x10,
- WR5_TX_WORD_LENGTH_MASK = 0x60,
- WR5_TX_WORD_LENGTH_5 = 0x00,
- WR5_TX_WORD_LENGTH_6 = 0x40,
- WR5_TX_WORD_LENGTH_7 = 0x20,
- WR5_TX_WORD_LENGTH_8 = 0x60,
- WR5_DTR = 0x80
+ WR11_RCVCLK_TYPE = 0x80,
+ WR11_RCVCLK_SRC_MASK = 0x60, // RCV CLOCK
+ WR11_RCVCLK_SRC_RTXC = 0x00, // 0 0
+ WR11_RCVCLK_SRC_TRXC = 0x20, // 0 1
+ WR11_RCVCLK_SRC_BR = 0x40, // 1 0
+ WR11_RCVCLK_SRC_DPLL = 0x60, // 1 1
+ WR11_TRACLK_SRC_MASK = 0x18, // TRA CLOCK
+ WR11_TRACLK_SRC_RTXC = 0x00, // 0 0
+ WR11_TRACLK_SRC_TRXC = 0x08, // 0 1
+ WR11_TRACLK_SRC_BR = 0x10, // 1 0
+ WR11_TRACLK_SRC_DPLL = 0x18, // 1 1
+ WR11_TRXC_DIRECTION = 0x04,
+ WR11_TRXSRC_SRC_MASK = 0x03, // TRXX CLOCK
+ WR11_TRXSRC_SRC_XTAL = 0x00, // 0 0
+ WR11_TRXSRC_SRC_TRA = 0x01, // 0 1
+ WR11_TRXSRC_SRC_BR = 0x02, // 1 0
+ WR11_TRXSRC_SRC_DPLL = 0x03 // 1 1
};
- /* SCC specifics */
- enum
- {
- WR9_CMD_MASK = 0xC0,
- WR9_CMD_NORESET = 0x00,
- WR9_CMD_CHNB_RESET = 0x40,
- WR9_CMD_CHNA_RESET = 0x80,
- WR9_CMD_HW_RESET = 0xC0,
- WR9_BIT_VIS = 0x01,
- WR9_BIT_NV = 0x02,
- WR9_BIT_DLC = 0x04,
- WR9_BIT_MIE = 0x08,
- WR9_BIT_SHSL = 0x10,
- WR9_BIT_IACK = 0x20
- };
-
- enum
- {
- WR11_RCVCLK_TYPE = 0x80,
- WR11_RCVCLK_SRC_MASK = 0x60, // RCV CLOCK
- WR11_RCVCLK_SRC_RTXC = 0x00, // 0 0
- WR11_RCVCLK_SRC_TRXC = 0x20, // 0 1
- WR11_RCVCLK_SRC_BR = 0x40, // 1 0
- WR11_RCVCLK_SRC_DPLL = 0x60, // 1 1
- WR11_TRACLK_SRC_MASK = 0x18, // TRA CLOCK
- WR11_TRACLK_SRC_RTXC = 0x00, // 0 0
- WR11_TRACLK_SRC_TRXC = 0x08, // 0 1
- WR11_TRACLK_SRC_BR = 0x10, // 1 0
- WR11_TRACLK_SRC_DPLL = 0x18, // 1 1
- WR11_TRXC_DIRECTION = 0x04,
- WR11_TRXSRC_SRC_MASK = 0x03, // TRXX CLOCK
- WR11_TRXSRC_SRC_XTAL = 0x00, // 0 0
- WR11_TRXSRC_SRC_TRA = 0x01, // 0 1
- WR11_TRXSRC_SRC_BR = 0x02, // 1 0
- WR11_TRXSRC_SRC_DPLL = 0x03 // 1 1
- };
-
- enum
- {
- WR14_DPLL_CMD_MASK = 0xe0, // Command
- WR14_CMD_NULL = 0x00, // 0 0 0
- WR14_CMD_ESM = 0x20, // 0 0 1
- WR14_CMD_RMC = 0x40, // 0 1 0
- WR14_CMD_DISABLE_DPLL = 0x60, // 0 1 1
- WR14_CMD_SS_BGR = 0x80, // 1 0 0
- WR14_CMD_SS_RTXC = 0xa0, // 1 0 1
- WR14_CMD_SET_FM = 0xc0, // 1 1 0
- WR14_CMD_SET_NRZI = 0xe0 // 1 1 1
- };
+ enum
+ {
+ WR14_DPLL_CMD_MASK = 0xe0, // Command
+ WR14_CMD_NULL = 0x00, // 0 0 0
+ WR14_CMD_ESM = 0x20, // 0 0 1
+ WR14_CMD_RMC = 0x40, // 0 1 0
+ WR14_CMD_DISABLE_DPLL = 0x60, // 0 1 1
+ WR14_CMD_SS_BGR = 0x80, // 1 0 0
+ WR14_CMD_SS_RTXC = 0xa0, // 1 0 1
+ WR14_CMD_SET_FM = 0xc0, // 1 1 0
+ WR14_CMD_SET_NRZI = 0xe0 // 1 1 1
+ };
void update_serial();
void set_dtr(int state);
void set_rts(int state);
int get_clock_mode();
- void update_rts();
+ void update_rts();
stop_bits_t get_stop_bits();
int get_rx_word_length();
int get_tx_word_length();
// receiver state
- UINT8 m_rx_data_fifo[8]; // receive data FIFO
- UINT8 m_rx_error_fifo[8]; // receive error FIFO
- UINT8 m_rx_error; // current receive error
- //int m_rx_fifo // receive FIFO pointer
- int m_rx_fifo_rp; // receive FIFO read pointer
- int m_rx_fifo_wp; // receive FIFO write pointer
- int m_rx_fifo_sz; // receive FIFO size
-
- int m_rx_clock; // receive clock pulse count
- int m_rx_first; // first character received
- int m_rx_break; // receive break condition
- UINT8 m_rx_rr0_latch; // read register 0 latched
+ UINT8 m_rx_data_fifo[8]; // receive data FIFO
+ UINT8 m_rx_error_fifo[8]; // receive error FIFO
+ UINT8 m_rx_error; // current receive error
+ //int m_rx_fifo // receive FIFO pointer
+ int m_rx_fifo_rp; // receive FIFO read pointer
+ int m_rx_fifo_wp; // receive FIFO write pointer
+ int m_rx_fifo_sz; // receive FIFO size
+
+ int m_rx_clock; // receive clock pulse count
+ int m_rx_first; // first character received
+ int m_rx_break; // receive break condition
+ UINT8 m_rx_rr0_latch; // read register 0 latched
int m_rxd;
- int m_ri; // ring indicator latch
- int m_cts; // clear to send latch
- int m_dcd; // data carrier detect latch
+ int m_ri; // ring indicator latch
+ int m_cts; // clear to send latch
+ int m_dcd; // data carrier detect latch
// transmitter state
- UINT8 m_tx_data; // transmit data register
- int m_tx_clock; // transmit clock pulse count
+ UINT8 m_tx_data; // transmit data register
+ int m_tx_clock; // transmit clock pulse count
- int m_dtr; // data terminal ready
- int m_rts; // request to send
+ int m_dtr; // data terminal ready
+ int m_rts; // request to send
// synchronous state
- UINT16 m_sync; // sync character
+ UINT16 m_sync; // sync character
- // int m_index;
+ int m_index;
z80scc_device *m_uart;
// SCC specifics
- int m_ph; // Point high command to access regs 08-0f
- UINT8 m_zc;
+ int m_ph; // Point high command to access regs 08-0f
+ UINT8 m_zc;
};
@@ -557,10 +556,11 @@ public:
DECLARE_READ8_MEMBER( ba_cd_r );
DECLARE_WRITE8_MEMBER( ba_cd_w );
- DECLARE_READ8_MEMBER( da_r ) { return m_chanA->data_read(); }
- DECLARE_WRITE8_MEMBER( da_w ) { m_chanA->data_write(data); }
- DECLARE_READ8_MEMBER( db_r ) { return m_chanB->data_read(); }
- DECLARE_WRITE8_MEMBER( db_w ) { m_chanB->data_write(data); }
+ /* Definitions moved to z80scc.c for enhencements */
+ DECLARE_READ8_MEMBER( da_r ); // { return m_chanA->data_read(); }
+ DECLARE_WRITE8_MEMBER( da_w ); // { m_chanA->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_WRITE8_MEMBER( ca_w ) { m_chanA->control_write(data); }
@@ -607,7 +607,7 @@ protected:
// Variants in the SCC family
enum
{
- TYPE_Z80SCC = 0x001,
+ TYPE_Z80SCC = 0x001,
TYPE_SCC8030 = 0x002,
TYPE_SCC80C30 = 0x004,
TYPE_SCC80230 = 0x008,
@@ -615,16 +615,16 @@ protected:
TYPE_SCC85C30 = 0x020,
TYPE_SCC85230 = 0x040,
TYPE_SCC85233 = 0x080,
- TYPE_SCC8523L = 0x100
+ TYPE_SCC8523L = 0x100
};
#define SET_NMOS ( z80scc_device::TYPE_SCC8030 | z80scc_device::TYPE_SCC8530 )
#define SET_CMOS ( z80scc_device::TYPE_SCC80C30 | z80scc_device::TYPE_SCC85C30 )
#define SET_ESCC ( z80scc_device::TYPE_SCC80230 | z80scc_device::TYPE_SCC85230 | z80scc_device::TYPE_SCC8523L )
-#define SET_EMSCC z80scc_device::TYPE_SCC85233
+#define SET_EMSCC z80scc_device::TYPE_SCC85233
#define SET_Z80X30 ( z80scc_device::TYPE_SCC8030 | z80scc_device::TYPE_SCC80C30 | z80scc_device::TYPE_SCC80230 )
#define SET_Z85X3X ( z80scc_device::TYPE_SCC8530 | z80scc_device::TYPE_SCC85C30 | z80scc_device::TYPE_SCC85230 \
- | z80scc_device::TYPE_SCC8523L | z80scc_device::TYPE_SCC85233 )
+ | z80scc_device::TYPE_SCC8523L | z80scc_device::TYPE_SCC85233 )
enum
{
@@ -641,27 +641,28 @@ protected:
int m_rxcb;
int m_txcb;
- devcb_write_line m_out_txda_cb;
- devcb_write_line m_out_dtra_cb;
- devcb_write_line m_out_rtsa_cb;
- devcb_write_line m_out_wrdya_cb;
- devcb_write_line m_out_synca_cb;
+ devcb_write_line m_out_txda_cb;
+ devcb_write_line m_out_dtra_cb;
+ devcb_write_line m_out_rtsa_cb;
+ devcb_write_line m_out_wrdya_cb;
+ devcb_write_line m_out_synca_cb;
- devcb_write_line m_out_txdb_cb;
- devcb_write_line m_out_dtrb_cb;
- devcb_write_line m_out_rtsb_cb;
- devcb_write_line m_out_wrdyb_cb;
- devcb_write_line m_out_syncb_cb;
+ devcb_write_line m_out_txdb_cb;
+ devcb_write_line m_out_dtrb_cb;
+ devcb_write_line m_out_rtsb_cb;
+ devcb_write_line m_out_wrdyb_cb;
+ devcb_write_line m_out_syncb_cb;
- devcb_write_line m_out_int_cb;
- devcb_write_line m_out_rxdrqa_cb;
- devcb_write_line m_out_txdrqa_cb;
- devcb_write_line m_out_rxdrqb_cb;
- devcb_write_line m_out_txdrqb_cb;
+ devcb_write_line m_out_int_cb;
+ devcb_write_line m_out_rxdrqa_cb;
+ devcb_write_line m_out_txdrqa_cb;
+ devcb_write_line m_out_rxdrqb_cb;
+ devcb_write_line m_out_txdrqb_cb;
- int m_int_state[6]; // interrupt state
+ int m_int_state[6]; // interrupt state
int m_variant;
+ UINT8 m_wr0_ptrbits;
};
class scc8030_device : public z80scc_device
diff --git a/src/devices/machine/z80sio.c b/src/devices/machine/z80sio.c
index 41e841a3ea6..09c0e46663f 100644
--- a/src/devices/machine/z80sio.c
+++ b/src/devices/machine/z80sio.c
@@ -11,7 +11,7 @@
check that an operation is invalid because of package type but relies
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
PLCC44 SIO/4
-------------------------------------------------------------------
@@ -50,7 +50,7 @@
#include "z80sio.h"
//**************************************************************************
-// MACROS / CONSTANTS
+// MACROS / CONSTANTS
//**************************************************************************
#define VERBOSE 0
@@ -68,13 +68,13 @@
#define FUNCNAME __PRETTY_FUNCTION__
#endif
-#define CHANA_TAG "cha"
-#define CHANB_TAG "chb"
+#define CHANA_TAG "cha"
+#define CHANB_TAG "chb"
//**************************************************************************
-// DEVICE DEFINITIONS
+// DEVICE DEFINITIONS
//**************************************************************************
// device type definition
@@ -82,12 +82,12 @@ const device_type Z80SIO = &device_creator<z80sio_device>;
const device_type Z80SIO_CHANNEL = &device_creator<z80sio_channel>;
//-------------------------------------------------
-// device_mconfig_additions -
+// device_mconfig_additions -
//-------------------------------------------------
MACHINE_CONFIG_FRAGMENT( z80sio )
- MCFG_DEVICE_ADD(CHANA_TAG, Z80SIO_CHANNEL, 0)
- MCFG_DEVICE_ADD(CHANB_TAG, Z80SIO_CHANNEL, 0)
+MCFG_DEVICE_ADD(CHANA_TAG, Z80SIO_CHANNEL, 0)
+MCFG_DEVICE_ADD(CHANB_TAG, Z80SIO_CHANNEL, 0)
MACHINE_CONFIG_END
machine_config_constructor z80sio_device::device_mconfig_additions() const
@@ -96,38 +96,38 @@ machine_config_constructor z80sio_device::device_mconfig_additions() const
}
//**************************************************************************
-// LIVE DEVICE
+// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
-// z80sio_device - constructor
+// z80sio_device - constructor
//-------------------------------------------------
z80sio_device::z80sio_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT32 variant, const char *shortname, const char *source)
: device_t(mconfig, type, name, tag, owner, clock, shortname, source),
- device_z80daisy_interface(mconfig, *this),
- m_chanA(*this, CHANA_TAG),
- m_chanB(*this, CHANB_TAG),
- m_rxca(0),
- m_txca(0),
- m_rxcb(0),
- m_txcb(0),
- m_out_txda_cb(*this),
- m_out_dtra_cb(*this),
- m_out_rtsa_cb(*this),
- m_out_wrdya_cb(*this),
- m_out_synca_cb(*this),
- m_out_txdb_cb(*this),
- m_out_dtrb_cb(*this),
- m_out_rtsb_cb(*this),
- m_out_wrdyb_cb(*this),
- m_out_syncb_cb(*this),
- m_out_int_cb(*this),
- m_out_rxdrqa_cb(*this),
- m_out_txdrqa_cb(*this),
- m_out_rxdrqb_cb(*this),
- m_out_txdrqb_cb(*this),
- m_variant(variant)
+ device_z80daisy_interface(mconfig, *this),
+ m_chanA(*this, CHANA_TAG),
+ m_chanB(*this, CHANB_TAG),
+ m_rxca(0),
+ m_txca(0),
+ m_rxcb(0),
+ m_txcb(0),
+ m_out_txda_cb(*this),
+ m_out_dtra_cb(*this),
+ m_out_rtsa_cb(*this),
+ m_out_wrdya_cb(*this),
+ m_out_synca_cb(*this),
+ m_out_txdb_cb(*this),
+ m_out_dtrb_cb(*this),
+ m_out_rtsb_cb(*this),
+ m_out_wrdyb_cb(*this),
+ m_out_syncb_cb(*this),
+ m_out_int_cb(*this),
+ m_out_rxdrqa_cb(*this),
+ m_out_txdrqa_cb(*this),
+ m_out_rxdrqb_cb(*this),
+ m_out_txdrqb_cb(*this),
+ m_variant(variant)
{
for (int i = 0; i < 8; i++)
m_int_state[i] = 0;
@@ -135,41 +135,40 @@ z80sio_device::z80sio_device(const machine_config &mconfig, device_type type, co
z80sio_device::z80sio_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, Z80SIO, "Z80 SIO", tag, owner, clock, "z80sio", __FILE__),
- device_z80daisy_interface(mconfig, *this),
- m_chanA(*this, CHANA_TAG),
- m_chanB(*this, CHANB_TAG),
- m_rxca(0),
- m_txca(0),
- m_rxcb(0),
- m_txcb(0),
- m_out_txda_cb(*this),
- m_out_dtra_cb(*this),
- m_out_rtsa_cb(*this),
- m_out_wrdya_cb(*this),
- m_out_synca_cb(*this),
- m_out_txdb_cb(*this),
- m_out_dtrb_cb(*this),
- m_out_rtsb_cb(*this),
- m_out_wrdyb_cb(*this),
- m_out_syncb_cb(*this),
- m_out_int_cb(*this),
- m_out_rxdrqa_cb(*this),
- m_out_txdrqa_cb(*this),
- m_out_rxdrqb_cb(*this),
- m_out_txdrqb_cb(*this),
- m_variant(TYPE_Z80SIO)
+ device_z80daisy_interface(mconfig, *this),
+ m_chanA(*this, CHANA_TAG),
+ m_chanB(*this, CHANB_TAG),
+ m_rxca(0),
+ m_txca(0),
+ m_rxcb(0),
+ m_txcb(0),
+ m_out_txda_cb(*this),
+ m_out_dtra_cb(*this),
+ m_out_rtsa_cb(*this),
+ m_out_wrdya_cb(*this),
+ m_out_synca_cb(*this),
+ m_out_txdb_cb(*this),
+ m_out_dtrb_cb(*this),
+ m_out_rtsb_cb(*this),
+ m_out_wrdyb_cb(*this),
+ m_out_syncb_cb(*this),
+ m_out_int_cb(*this),
+ m_out_rxdrqa_cb(*this),
+ m_out_txdrqa_cb(*this),
+ m_out_rxdrqb_cb(*this),
+ m_out_txdrqb_cb(*this),
+ m_variant(TYPE_Z80SIO)
{
for (int i = 0; i < 8; i++)
m_int_state[i] = 0;
}
//-------------------------------------------------
-// device_start - device-specific startup
+// device_start - device-specific startup
//-------------------------------------------------
-
void z80sio_device::device_start()
{
- LOG(("%s\n", FUNCNAME));
+ LOG(("%s\n", FUNCNAME));
// resolve callbacks
m_out_txda_cb.resolve_safe();
m_out_dtra_cb.resolve_safe();
@@ -201,9 +200,8 @@ void z80sio_device::device_start()
//-------------------------------------------------
-// device_reset - device-specific reset
+// device_reset - device-specific reset
//-------------------------------------------------
-
void z80sio_device::device_reset()
{
LOG(("%s \"%s\" \n", FUNCNAME, tag()));
@@ -213,17 +211,17 @@ void z80sio_device::device_reset()
}
//-------------------------------------------------
-// z80daisy_irq_state - get interrupt status
+// z80daisy_irq_state - get interrupt status
//-------------------------------------------------
-
int z80sio_device::z80daisy_irq_state()
{
int state = 0;
int i;
- LOG(("Z80SIO \"%s\" : Interrupt State A:%d%d%d%d B:%d%d%d%d\n", tag(),
- 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]));
+
+ 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[4], m_int_state[5], m_int_state[6], m_int_state[7]));
// loop over all interrupt sources
for (i = 0; i < 8; i++)
@@ -237,21 +235,20 @@ int z80sio_device::z80daisy_irq_state()
state |= m_int_state[i];
}
- LOG(("Z80SIO \"%s\" : Interrupt State %u\n", tag(), state));
-
+ LOG(("Interrupt State %u\n", state));
+
return state;
}
//-------------------------------------------------
-// z80daisy_irq_ack - interrupt acknowledge
+// z80daisy_irq_ack - interrupt acknowledge
//-------------------------------------------------
-
int z80sio_device::z80daisy_irq_ack()
{
int i;
- LOG(("Z80SIO \"%s\" Interrupt Acknowledge\n", tag()));
+ LOG(("%s %s \n",FUNCNAME, tag()));
// loop over all interrupt sources
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;
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;
}
@@ -277,14 +274,13 @@ int z80sio_device::z80daisy_irq_ack()
//-------------------------------------------------
-// z80daisy_irq_reti - return from interrupt
+// z80daisy_irq_reti - return from interrupt
//-------------------------------------------------
-
void z80sio_device::z80daisy_irq_reti()
{
int i;
- LOG(("Z80SIO \"%s\" Return from Interrupt\n", tag()));
+ LOG(("%s %s \n",FUNCNAME, tag()));
// loop over all interrupt sources
for (i = 0; i < 8; i++)
@@ -304,22 +300,23 @@ void z80sio_device::z80daisy_irq_reti()
//-------------------------------------------------
-// check_interrupts -
+// 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;
m_out_int_cb(state);
}
//-------------------------------------------------
-// reset_interrupts -
+// reset_interrupts -
//-------------------------------------------------
-
void z80sio_device::reset_interrupts()
{
+ LOG(("%s %s \n",FUNCNAME, tag()));
+ // reset internal interrupt sources
for (int i = 0; i < 8; i++)
{
m_int_state[i] = 0;
@@ -330,14 +327,15 @@ 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)
{
UINT8 vector = m_chanB->m_wr2;
int priority;
+ LOG(("%s %s \n",FUNCNAME, tag()));
+
#if 0
if((m_variant == TYPE_I8274) || (m_variant == TYPE_UPD7201))
{
@@ -386,10 +384,7 @@ void z80sio_device::trigger_interrupt(int index, int state)
// status affects vector
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
m_chanB->m_rr2 = vector;
@@ -403,42 +398,40 @@ void z80sio_device::trigger_interrupt(int index, int state)
//-------------------------------------------------
-// m1_r - interrupt acknowledge
+// m1_r - interrupt acknowledge
//-------------------------------------------------
-
int z80sio_device::m1_r()
{
+ LOG(("%s %s \n",FUNCNAME, tag()));
return z80daisy_irq_ack();
}
//-------------------------------------------------
-// cd_ba_r -
+// cd_ba_r -
//-------------------------------------------------
-
READ8_MEMBER( z80sio_device::cd_ba_r )
{
int ba = BIT(offset, 0);
int cd = BIT(offset, 1);
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();
}
//-------------------------------------------------
-// cd_ba_w -
+// cd_ba_w -
//-------------------------------------------------
-
WRITE8_MEMBER( z80sio_device::cd_ba_w )
{
int ba = BIT(offset, 0);
int cd = BIT(offset, 1);
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)
channel->control_write(data);
@@ -448,32 +441,30 @@ WRITE8_MEMBER( z80sio_device::cd_ba_w )
//-------------------------------------------------
-// ba_cd_r -
+// ba_cd_r -
//-------------------------------------------------
-
READ8_MEMBER( z80sio_device::ba_cd_r )
{
int ba = BIT(offset, 1);
int cd = BIT(offset, 0);
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();
}
//-------------------------------------------------
-// ba_cd_w -
+// ba_cd_w -
//-------------------------------------------------
-
WRITE8_MEMBER( z80sio_device::ba_cd_w )
{
int ba = BIT(offset, 1);
int cd = BIT(offset, 0);
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)
channel->control_write(data);
@@ -482,13 +473,12 @@ WRITE8_MEMBER( z80sio_device::ba_cd_w )
}
//**************************************************************************
-// SIO CHANNEL
+// SIO CHANNEL
//**************************************************************************
//-------------------------------------------------
-// z80sio_channel - constructor
+// z80sio_channel - constructor
//-------------------------------------------------
-
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_serial_interface(mconfig, *this),
@@ -508,6 +498,7 @@ z80sio_channel::z80sio_channel(const machine_config &mconfig, const char *tag, d
m_rts(0),
m_sync(0)
{
+ LOG(("%s\n",FUNCNAME));
// Reset all registers
m_rr0 = m_rr1 = m_rr2 = 0;
m_wr0 = m_wr1 = m_wr2 = m_wr3 = m_wr4 = m_wr5 = m_wr6 = m_wr7 = 0;
@@ -521,14 +512,14 @@ z80sio_channel::z80sio_channel(const machine_config &mconfig, const char *tag, d
//-------------------------------------------------
-// start - channel startup
+// start - channel startup
//-------------------------------------------------
-
void z80sio_channel::device_start()
{
- LOG(("%s\n",FUNCNAME));
+ LOG(("%s\n",FUNCNAME));
m_uart = downcast<z80sio_device *>(owner());
m_index = m_uart->get_channel_index(this);
+ m_variant = ((z80sio_device *)m_owner)->m_variant;
// state saving
save_item(NAME(m_rr0));
@@ -558,17 +549,19 @@ void z80sio_channel::device_start()
save_item(NAME(m_dtr));
save_item(NAME(m_rts));
save_item(NAME(m_sync));
+ save_item(NAME(m_variant));
device_serial_interface::register_save_state(machine().save(), this);
}
//-------------------------------------------------
-// reset - reset channel status
+// reset - reset channel status
//-------------------------------------------------
-
void z80sio_channel::device_reset()
{
- LOG(("%s\n", FUNCNAME));
+ LOG(("%s\n", FUNCNAME));
+
+ // Reset RS232 emulation
receive_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);
}
-
//-------------------------------------------------
-// tra_callback -
+// tra_callback -
//-------------------------------------------------
-
void z80sio_channel::tra_callback()
{
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
if (m_index == z80sio_device::CHANNEL_A)
m_uart->m_out_txda_cb(1);
@@ -613,6 +605,7 @@ void z80sio_channel::tra_callback()
}
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
if (m_index == z80sio_device::CHANNEL_A)
m_uart->m_out_txda_cb(0);
@@ -621,24 +614,32 @@ void z80sio_channel::tra_callback()
}
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
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
- 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);
}
}
//-------------------------------------------------
-// tra_complete -
+// 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))
{
- 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);
@@ -650,6 +651,7 @@ void z80sio_channel::tra_complete()
}
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
if (m_index == z80sio_device::CHANNEL_A)
m_uart->m_out_txda_cb(0);
@@ -658,6 +660,7 @@ void z80sio_channel::tra_complete()
}
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
if (m_index == z80sio_device::CHANNEL_A)
m_uart->m_out_txda_cb(1);
@@ -668,6 +671,7 @@ void z80sio_channel::tra_complete()
// if transmit buffer is 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
m_rr1 |= RR1_ALL_SENT;
@@ -679,43 +683,54 @@ void z80sio_channel::tra_complete()
//-------------------------------------------------
-// rcv_callback -
+// rcv_callback -
//-------------------------------------------------
-
void z80sio_channel::rcv_callback()
{
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);
}
+#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()
{
+ UINT8 data;
+
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);
}
//-------------------------------------------------
-// get_clock_mode - get clock divisor
+// get_clock_mode - get clock divisor
//-------------------------------------------------
int z80sio_channel::get_clock_mode()
{
+ LOG(("%s %s\n",FUNCNAME, tag()));
int clocks = 1;
switch (m_wr4 & WR4_CLOCK_RATE_MASK)
{
- case WR4_CLOCK_RATE_X1: clocks = 1; break;
- case WR4_CLOCK_RATE_X16: clocks = 16; break;
- case WR4_CLOCK_RATE_X32: clocks = 32; break;
- case WR4_CLOCK_RATE_X64: clocks = 64; break;
+ case WR4_CLOCK_RATE_X1: clocks = 1; break;
+ case WR4_CLOCK_RATE_X16: clocks = 16; break;
+ case WR4_CLOCK_RATE_X32: clocks = 32; break;
+ case WR4_CLOCK_RATE_X64: clocks = 64; break;
}
return clocks;
@@ -734,6 +749,7 @@ CR5 = m_wr5 and SR1 = m_rr1
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)
m_uart->m_out_rtsa_cb(state);
else
@@ -742,28 +758,31 @@ void z80sio_channel::set_rts(int state)
void z80sio_channel::update_rts()
{
- if (m_wr5 & WR5_RTS)
- {
- // when the RTS bit is set, the _RTS output goes low
- set_rts(0);
- m_rts = 1;
- }
- else
- {
- // when the RTS bit is reset, the _RTS output goes high after the transmitter empties
- m_rts = 0;
- }
-
- // data terminal ready output follows the state programmed into the DTR bit*/
- set_dtr((m_wr5 & WR5_DTR) ? 0 : 1);
+ // 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)
+ {
+ // when the RTS bit is set, the _RTS output goes low
+ set_rts(0);
+ m_rts = 1;
+ }
+ else
+ {
+ // when the RTS bit is reset, the _RTS output goes high after the transmitter empties
+ m_rts = 0;
+ }
+
+ // data terminal ready output follows the state programmed into the DTR bit*/
+ set_dtr((m_wr5 & WR5_DTR) ? 0 : 1);
}
//-------------------------------------------------
-// get_stop_bits - get number of stop bits
+// get_stop_bits - get number of 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)
{
case WR4_STOP_BITS_1: return STOP_BITS_1;
@@ -776,19 +795,20 @@ device_serial_interface::stop_bits_t z80sio_channel::get_stop_bits()
//-------------------------------------------------
-// get_rx_word_length - get receive word length
+// get_rx_word_length - get receive word length
//-------------------------------------------------
int z80sio_channel::get_rx_word_length()
{
+ LOG(("%s %s\n",FUNCNAME, tag()));
int bits = 5;
switch (m_wr3 & WR3_RX_WORD_LENGTH_MASK)
{
- case WR3_RX_WORD_LENGTH_5: bits = 5; break;
- case WR3_RX_WORD_LENGTH_6: bits = 6; break;
- case WR3_RX_WORD_LENGTH_7: bits = 7; break;
- case WR3_RX_WORD_LENGTH_8: bits = 8; break;
+ case WR3_RX_WORD_LENGTH_5: bits = 5; break;
+ case WR3_RX_WORD_LENGTH_6: bits = 6; break;
+ case WR3_RX_WORD_LENGTH_7: bits = 7; break;
+ case WR3_RX_WORD_LENGTH_8: bits = 8; break;
}
return bits;
@@ -796,19 +816,20 @@ int z80sio_channel::get_rx_word_length()
//-------------------------------------------------
-// get_tx_word_length - get transmit word length
+// get_tx_word_length - get transmit word length
//-------------------------------------------------
int z80sio_channel::get_tx_word_length()
{
+ LOG(("%s %s\n",FUNCNAME, tag()));
int bits = 5;
switch (m_wr5 & WR5_TX_WORD_LENGTH_MASK)
{
- case WR5_TX_WORD_LENGTH_5: bits = 5; break;
- case WR5_TX_WORD_LENGTH_6: bits = 6; break;
- case WR5_TX_WORD_LENGTH_7: bits = 7; break;
- case WR5_TX_WORD_LENGTH_8: bits = 8; break;
+ case WR5_TX_WORD_LENGTH_5: bits = 5; break;
+ case WR5_TX_WORD_LENGTH_6: bits = 6; break;
+ case WR5_TX_WORD_LENGTH_7: bits = 7; break;
+ case WR5_TX_WORD_LENGTH_8: bits = 8; break;
}
return bits;
@@ -820,14 +841,16 @@ int z80sio_channel::get_tx_word_length()
* Break/Abort latch. */
UINT8 z80sio_channel::do_sioreg_rr0()
{
- return m_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 z80sio_channel::do_sioreg_rr1()
{
- return m_rr1;
+ LOG(("%s %s\n",FUNCNAME, tag()));
+ return m_rr1;
}
/*
* This register contains the interrupt vector written into WR2 if the Status
@@ -839,20 +862,22 @@ no interrupts are pending, the vector is modified with V3 = 0, V2 = 1, and
V1 = 1. This register is read only through Channel B. */
UINT8 z80sio_channel::do_sioreg_rr2()
{
- // channel B only
- return m_index == z80sio_device::CHANNEL_B ? m_rr2 : 0;
+ LOG(("%s %s\n",FUNCNAME, tag()));
+ // channel B only
+ return m_index == z80sio_device::CHANNEL_B ? m_rr2 : 0;
}
//-------------------------------------------------
-// control_read - read control register
+// control_read - read control register
//-------------------------------------------------
UINT8 z80sio_channel::control_read()
{
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)
{
// mask out register index
@@ -861,201 +886,202 @@ UINT8 z80sio_channel::control_read()
switch (reg)
{
- case REG_RR0_STATUS: data = do_sioreg_rr0(); break;
- case REG_RR1_SPEC_RCV_COND: data = do_sioreg_rr1(); break;
+ case REG_RR0_STATUS: data = do_sioreg_rr0(); break;
+ case REG_RR1_SPEC_RCV_COND: data = do_sioreg_rr1(); break;
case REG_RR2_INTERRUPT_VECT: data = do_sioreg_rr2(); break;
default:
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;
}
-/* 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 */
void z80sio_channel::do_sioreg_wr0_resets(UINT8 data)
{
- switch (data & WR0_CRC_RESET_CODE_MASK)
- {
- case WR0_CRC_RESET_NULL:
- LOG(("Z80SIO \"%s\" Channel %c : CRC_RESET_NULL\n", m_owner->tag(), 'A' + m_index));
- break;
- case WR0_CRC_RESET_RX: /* In Synchronous mode: all Os (zeros) (CCITT-O CRC-16) */
- LOG(("Z80SIO \"%s\" Channel %c : CRC_RESET_RX - not implemented\n", m_owner->tag(), 'A' + m_index));
- break;
- case WR0_CRC_RESET_TX: /* In HDLC mode: all 1s (ones) (CCITT-1) */
- LOG(("Z80SIO \"%s\" Channel %c : CRC_RESET_TX - not implemented\n", m_owner->tag(), 'A' + m_index));
- break;
- case WR0_CRC_RESET_TX_UNDERRUN: /* Resets Tx underrun/EOM bit (D6 of the SRO register) */
- LOG(("Z80SIO \"%s\" Channel %c : CRC_RESET_TX_UNDERRUN - not implemented\n", m_owner->tag(), 'A' + m_index));
- break;
- default: /* Will not happen unless someone messes with the 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);
- }
+ LOG(("%s %s\n",FUNCNAME, tag()));
+ switch (data & WR0_CRC_RESET_CODE_MASK)
+ {
+ case WR0_CRC_RESET_NULL:
+ LOG(("Z80SIO \"%s\" Channel %c : CRC_RESET_NULL\n", m_owner->tag(), 'A' + m_index));
+ break;
+ case WR0_CRC_RESET_RX: /* In Synchronous mode: all Os (zeros) (CCITT-O CRC-16) */
+ LOG(("Z80SIO \"%s\" Channel %c : CRC_RESET_RX - not implemented\n", m_owner->tag(), 'A' + m_index));
+ break;
+ case WR0_CRC_RESET_TX: /* In HDLC mode: all 1s (ones) (CCITT-1) */
+ LOG(("Z80SIO \"%s\" Channel %c : CRC_RESET_TX - not implemented\n", m_owner->tag(), 'A' + m_index));
+ break;
+ case WR0_CRC_RESET_TX_UNDERRUN: /* Resets Tx underrun/EOM bit (D6 of the SRO register) */
+ LOG(("Z80SIO \"%s\" Channel %c : CRC_RESET_TX_UNDERRUN - not implemented\n", m_owner->tag(), 'A' + m_index));
+ break;
+ default: /* Will not happen unless someone messes with the 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)
{
- m_wr0 = data;
- switch (data & WR0_COMMAND_MASK)
+ m_wr0 = data;
+ switch (data & WR0_COMMAND_MASK)
{
- case WR0_NULL:
- LOG(("Z80SIO \"%s\" Channel %c : Null\n", m_owner->tag(), 'A' + m_index));
- break;
- case WR0_RESET_EXT_STATUS:
- // reset external/status interrupt
- m_rr0 &= ~(RR0_DCD | RR0_SYNC_HUNT | RR0_CTS | RR0_BREAK_ABORT);
- // release the latch
- m_rx_rr0_latch = 0;
- // update register to reflect wire values TODO: Check if this will fire new interrupts
- if (!m_dcd) m_rr0 |= RR0_DCD;
- if (m_sync) m_rr0 |= RR0_SYNC_HUNT;
- if (m_cts) m_rr0 |= RR0_CTS;
-
- LOG(("Z80SIO \"%s\" Channel %c : Reset External/Status Interrupt\n", m_owner->tag(), 'A' + m_index));
- break;
- case WR0_CHANNEL_RESET:
- // channel reset
- LOG(("Z80SIO \"%s\" Channel %c : Channel Reset\n", m_owner->tag(), 'A' + m_index));
- device_reset();
- break;
- case WR0_ENABLE_INT_NEXT_RX:
- // enable interrupt on next receive character
- LOG(("Z80SIO \"%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:
- // reset transmitter interrupt pending
- LOG(("Z80SIO \"%s\" Channel %c : Reset Transmitter Interrupt Pending\n", m_owner->tag(), 'A' + m_index));
- logerror("Z80SIO \"%s\" Channel %c : unsupported command: Reset Transmitter Interrupt Pending\n", m_owner->tag(), 'A' + m_index);
- break;
- case WR0_ERROR_RESET:
- // error reset
- LOG(("Z80SIO \"%s\" Channel %c : Error Reset\n", m_owner->tag(), 'A' + m_index));
- m_rr1 &= ~(RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR);
- break;
- case WR0_RETURN_FROM_INT:
- // return from interrupt
- LOG(("Z80SIO \"%s\" Channel %c : Return from Interrupt\n", m_owner->tag(), 'A' + m_index));
- m_uart->z80daisy_irq_reti();
- break;
- default:
- LOG(("Z80SIO \"%s\" Channel %c : Unsupported WR0 command %02x mask %02x\n", m_owner->tag(), 'A' + m_index, data, WR0_REGISTER_MASK));
-
- }
- do_sioreg_wr0_resets(data);
+ case WR0_NULL:
+ LOG(("Z80SIO \"%s\" Channel %c : Null\n", m_owner->tag(), 'A' + m_index));
+ break;
+ case WR0_RESET_EXT_STATUS:
+ // reset external/status interrupt
+ m_rr0 &= ~(RR0_DCD | RR0_SYNC_HUNT | RR0_CTS | RR0_BREAK_ABORT);
+ // release the latch
+ m_rx_rr0_latch = 0;
+ // update register to reflect wire values TODO: Check if this will fire new interrupts
+ if (!m_dcd) m_rr0 |= RR0_DCD;
+ if (m_sync) m_rr0 |= RR0_SYNC_HUNT;
+ if (m_cts) m_rr0 |= RR0_CTS;
+
+ LOG(("Z80SIO \"%s\" Channel %c : Reset External/Status Interrupt\n", m_owner->tag(), 'A' + m_index));
+ break;
+ case WR0_CHANNEL_RESET:
+ // channel reset
+ LOG(("Z80SIO \"%s\" Channel %c : Channel Reset\n", m_owner->tag(), 'A' + m_index));
+ device_reset();
+ break;
+ case WR0_ENABLE_INT_NEXT_RX:
+ // enable interrupt on next receive character
+ LOG(("Z80SIO \"%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:
+ // reset transmitter interrupt pending
+ LOG(("Z80SIO \"%s\" Channel %c : Reset Transmitter Interrupt Pending\n", m_owner->tag(), 'A' + m_index));
+ logerror("Z80SIO \"%s\" Channel %c : unsupported command: Reset Transmitter Interrupt Pending\n", m_owner->tag(), 'A' + m_index);
+ break;
+ case WR0_ERROR_RESET:
+ // error reset
+ LOG(("Z80SIO \"%s\" Channel %c : Error Reset\n", m_owner->tag(), 'A' + m_index));
+ m_rr1 &= ~(RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR);
+ break;
+ case WR0_RETURN_FROM_INT:
+ // return from interrupt
+ LOG(("Z80SIO \"%s\" Channel %c : Return from Interrupt\n", m_owner->tag(), 'A' + m_index));
+ m_uart->z80daisy_irq_reti();
+ break;
+ default:
+ LOG(("Z80SIO \"%s\" Channel %c : Unsupported WR0 command %02x mask %02x\n", m_owner->tag(), 'A' + m_index, data, WR0_REGISTER_MASK));
+
+ }
+ do_sioreg_wr0_resets(data);
}
void z80sio_channel::do_sioreg_wr1(UINT8 data)
{
/* TODO: implement vector modifications when WR1 bit D2 is changed */
- m_wr1 = data;
- LOG(("Z80SIO \"%s\" Channel %c : External Interrupt Enable %u\n", m_owner->tag(), 'A' + m_index, (data & WR1_EXT_INT_ENABLE) ? 1 : 0));
- LOG(("Z80SIO \"%s\" Channel %c : Transmit Interrupt Enable %u\n", m_owner->tag(), 'A' + m_index, (data & WR1_TX_INT_ENABLE) ? 1 : 0));
- LOG(("Z80SIO \"%s\" Channel %c : Status Affects Vector %u\n", m_owner->tag(), 'A' + m_index, (data & WR1_STATUS_VECTOR) ? 1 : 0));
- LOG(("Z80SIO \"%s\" Channel %c : Wait/Ready Enable %u\n", m_owner->tag(), 'A' + m_index, (data & WR1_WRDY_ENABLE) ? 1 : 0));
- LOG(("Z80SIO \"%s\" Channel %c : Wait/Ready Function %s\n", m_owner->tag(), 'A' + m_index, (data & WR1_WRDY_FUNCTION) ? "Ready" : "Wait"));
- LOG(("Z80SIO \"%s\" Channel %c : Wait/Ready on %s\n", m_owner->tag(), 'A' + m_index, (data & WR1_WRDY_ON_RX_TX) ? "Receive" : "Transmit"));
-
- switch (data & WR1_RX_INT_MODE_MASK)
- {
- case WR1_RX_INT_DISABLE:
- LOG(("Z80SIO \"%s\" Channel %c : Receiver Interrupt Disabled\n", m_owner->tag(), 'A' + m_index));
- break;
-
- case WR1_RX_INT_FIRST:
- LOG(("Z80SIO \"%s\" Channel %c : Receiver Interrupt on First Character\n", m_owner->tag(), 'A' + m_index));
- break;
-
- case WR1_RX_INT_ALL_PARITY:
- LOG(("Z80SIO \"%s\" Channel %c : Receiver Interrupt on All Characters, Parity Affects Vector\n", m_owner->tag(), 'A' + m_index));
- break;
-
- case WR1_RX_INT_ALL:
- LOG(("Z80SIO \"%s\" Channel %c : Receiver Interrupt on All Characters\n", m_owner->tag(), 'A' + m_index));
- break;
- }
+ m_wr1 = data;
+ LOG(("Z80SIO \"%s\" Channel %c : External Interrupt Enable %u\n", m_owner->tag(), 'A' + m_index, (data & WR1_EXT_INT_ENABLE) ? 1 : 0));
+ LOG(("Z80SIO \"%s\" Channel %c : Transmit Interrupt Enable %u\n", m_owner->tag(), 'A' + m_index, (data & WR1_TX_INT_ENABLE) ? 1 : 0));
+ LOG(("Z80SIO \"%s\" Channel %c : Status Affects Vector %u\n", m_owner->tag(), 'A' + m_index, (data & WR1_STATUS_VECTOR) ? 1 : 0));
+ LOG(("Z80SIO \"%s\" Channel %c : Wait/Ready Enable %u\n", m_owner->tag(), 'A' + m_index, (data & WR1_WRDY_ENABLE) ? 1 : 0));
+ LOG(("Z80SIO \"%s\" Channel %c : Wait/Ready Function %s\n", m_owner->tag(), 'A' + m_index, (data & WR1_WRDY_FUNCTION) ? "Ready" : "Wait"));
+ LOG(("Z80SIO \"%s\" Channel %c : Wait/Ready on %s\n", m_owner->tag(), 'A' + m_index, (data & WR1_WRDY_ON_RX_TX) ? "Receive" : "Transmit"));
+
+ switch (data & WR1_RX_INT_MODE_MASK)
+ {
+ case WR1_RX_INT_DISABLE:
+ LOG(("Z80SIO \"%s\" Channel %c : Receiver Interrupt Disabled\n", m_owner->tag(), 'A' + m_index));
+ break;
+
+ case WR1_RX_INT_FIRST:
+ LOG(("Z80SIO \"%s\" Channel %c : Receiver Interrupt on First Character\n", m_owner->tag(), 'A' + m_index));
+ break;
+
+ case WR1_RX_INT_ALL_PARITY:
+ LOG(("Z80SIO \"%s\" Channel %c : Receiver Interrupt on All Characters, Parity Affects Vector\n", m_owner->tag(), 'A' + m_index));
+ break;
+
+ case WR1_RX_INT_ALL:
+ LOG(("Z80SIO \"%s\" Channel %c : Receiver Interrupt on All Characters\n", m_owner->tag(), 'A' + m_index));
+ break;
+ }
}
void z80sio_channel::do_sioreg_wr2(UINT8 data)
{
- m_wr2 = data;
- if (m_index == z80sio_device::CHANNEL_B)
- {
- if (m_wr1 & z80sio_channel::WR1_STATUS_VECTOR)
- m_rr2 = ( m_rr2 & 0x0e ) | ( m_wr2 & 0xF1);
- else
- m_rr2 = m_wr2;
- }
- m_uart->check_interrupts();
- LOG(("Z80SIO \"%s\" Channel %c : Interrupt Vector %02x\n", m_owner->tag(), 'A' + m_index, data));
+ m_wr2 = data;
+ if (m_index == z80sio_device::CHANNEL_B)
+ {
+ if (m_wr1 & z80sio_channel::WR1_STATUS_VECTOR)
+ m_rr2 = ( m_rr2 & 0x0e ) | ( m_wr2 & 0xF1);
+ else
+ m_rr2 = m_wr2;
+ }
+ m_uart->check_interrupts();
+ LOG(("Z80SIO \"%s\" Channel %c : Interrupt Vector %02x\n", m_owner->tag(), 'A' + m_index, data));
}
void z80sio_channel::do_sioreg_wr3(UINT8 data)
{
- m_wr3 = data;
- LOG(("Z80SIO \"%s\" Channel %c : Receiver Enable %u\n", m_owner->tag(), 'A' + m_index, (data & WR3_RX_ENABLE) ? 1 : 0));
- LOG(("Z80SIO \"%s\" Channel %c : Auto Enables %u\n", m_owner->tag(), 'A' + m_index, (data & WR3_AUTO_ENABLES) ? 1 : 0));
- LOG(("Z80SIO \"%s\" Channel %c : Receiver Bits/Character %u\n", m_owner->tag(), 'A' + m_index, get_rx_word_length()));
+ m_wr3 = data;
+ LOG(("Z80SIO \"%s\" Channel %c : Receiver Enable %u\n", m_owner->tag(), 'A' + m_index, (data & WR3_RX_ENABLE) ? 1 : 0));
+ LOG(("Z80SIO \"%s\" Channel %c : Auto Enables %u\n", m_owner->tag(), 'A' + m_index, (data & WR3_AUTO_ENABLES) ? 1 : 0));
+ LOG(("Z80SIO \"%s\" Channel %c : Receiver Bits/Character %u\n", m_owner->tag(), 'A' + m_index, get_rx_word_length()));
}
void z80sio_channel::do_sioreg_wr4(UINT8 data)
{
- m_wr4 = data;
- LOG(("Z80SIO \"%s\" Channel %c : Parity Enable %u\n", m_owner->tag(), 'A' + m_index, (data & WR4_PARITY_ENABLE) ? 1 : 0));
- LOG(("Z80SIO \"%s\" Channel %c : Parity %s\n", m_owner->tag(), 'A' + m_index, (data & WR4_PARITY_EVEN) ? "Even" : "Odd"));
- LOG(("Z80SIO \"%s\" Channel %c : Stop Bits %s\n", m_owner->tag(), 'A' + m_index, stop_bits_tostring(get_stop_bits())));
- LOG(("Z80SIO \"%s\" Channel %c : Clock Mode %uX\n", m_owner->tag(), 'A' + m_index, get_clock_mode()));
+ m_wr4 = data;
+ LOG(("Z80SIO \"%s\" Channel %c : Parity Enable %u\n", m_owner->tag(), 'A' + m_index, (data & WR4_PARITY_ENABLE) ? 1 : 0));
+ LOG(("Z80SIO \"%s\" Channel %c : Parity %s\n", m_owner->tag(), 'A' + m_index, (data & WR4_PARITY_EVEN) ? "Even" : "Odd"));
+ LOG(("Z80SIO \"%s\" Channel %c : Stop Bits %s\n", m_owner->tag(), 'A' + m_index, stop_bits_tostring(get_stop_bits())));
+ LOG(("Z80SIO \"%s\" Channel %c : Clock Mode %uX\n", m_owner->tag(), 'A' + m_index, get_clock_mode()));
}
void z80sio_channel::do_sioreg_wr5(UINT8 data)
{
- m_wr5 = data;
- LOG(("Z80SIO \"%s\" Channel %c : Transmitter Enable %u\n", m_owner->tag(), 'A' + m_index, (data & WR5_TX_ENABLE) ? 1 : 0));
- LOG(("Z80SIO \"%s\" Channel %c : Transmitter Bits/Character %u\n", m_owner->tag(), 'A' + m_index, get_tx_word_length()));
- LOG(("Z80SIO \"%s\" Channel %c : Send Break %u\n", m_owner->tag(), 'A' + m_index, (data & WR5_SEND_BREAK) ? 1 : 0));
- LOG(("Z80SIO \"%s\" Channel %c : Request to Send %u\n", m_owner->tag(), 'A' + m_index, (data & WR5_RTS) ? 1 : 0));
- LOG(("Z80SIO \"%s\" Channel %c : Data Terminal Ready %u\n", m_owner->tag(), 'A' + m_index, (data & WR5_DTR) ? 1 : 0));
+ m_wr5 = data;
+ LOG(("Z80SIO \"%s\" Channel %c : Transmitter Enable %u\n", m_owner->tag(), 'A' + m_index, (data & WR5_TX_ENABLE) ? 1 : 0));
+ LOG(("Z80SIO \"%s\" Channel %c : Transmitter Bits/Character %u\n", m_owner->tag(), 'A' + m_index, get_tx_word_length()));
+ LOG(("Z80SIO \"%s\" Channel %c : Send Break %u\n", m_owner->tag(), 'A' + m_index, (data & WR5_SEND_BREAK) ? 1 : 0));
+ LOG(("Z80SIO \"%s\" Channel %c : Request to Send %u\n", m_owner->tag(), 'A' + m_index, (data & WR5_RTS) ? 1 : 0));
+ LOG(("Z80SIO \"%s\" Channel %c : Data Terminal Ready %u\n", m_owner->tag(), 'A' + m_index, (data & WR5_DTR) ? 1 : 0));
}
void z80sio_channel::do_sioreg_wr6(UINT8 data)
{
- LOG(("Z80SIO \"%s\" Channel %c : Transmit Sync %02x\n", m_owner->tag(), 'A' + m_index, data));
- m_sync = (m_sync & 0xff00) | data;
+ LOG(("Z80SIO \"%s\" Channel %c : Transmit Sync %02x\n", m_owner->tag(), 'A' + m_index, data));
+ m_sync = (m_sync & 0xff00) | data;
}
void z80sio_channel::do_sioreg_wr7(UINT8 data)
{
- LOG(("Z80SIO \"%s\" Channel %c : Receive Sync %02x\n", m_owner->tag(), 'A' + m_index, data));
- m_sync = (data << 8) | (m_sync & 0xff);
+ LOG(("Z80SIO \"%s\" Channel %c : Receive Sync %02x\n", m_owner->tag(), 'A' + m_index, data));
+ m_sync = (data << 8) | (m_sync & 0xff);
}
//-------------------------------------------------
-// control_write - write control register
+// control_write - write control register
//-------------------------------------------------
-
void z80sio_channel::control_write(UINT8 data)
{
- UINT8 reg = m_wr0 & WR0_REGISTER_MASK;
+ UINT8 reg = m_wr0 & WR0_REGISTER_MASK;
if (reg != 0)
{
// mask out register index
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)
{
- case REG_WR0_COMMAND_REGPT: do_sioreg_wr0(data); break;
- case REG_WR1_INT_DMA_ENABLE: do_sioreg_wr1(data); m_uart->check_interrupts(); break;
- case REG_WR2_INT_VECTOR: do_sioreg_wr2(data); break;
- case REG_WR3_RX_CONTROL: do_sioreg_wr3(data); update_serial(); break;
- case REG_WR4_RX_TX_MODES: do_sioreg_wr4(data); update_serial(); break;
- case REG_WR5_TX_CONTROL: do_sioreg_wr5(data); update_serial(); update_rts(); break;
- case REG_WR6_SYNC_OR_SDLC_A: do_sioreg_wr6(data); break;
- case REG_WR7_SYNC_OR_SDLC_F: do_sioreg_wr7(data); break;
+ case REG_WR0_COMMAND_REGPT: do_sioreg_wr0(data); break;
+ case REG_WR1_INT_DMA_ENABLE: do_sioreg_wr1(data); m_uart->check_interrupts(); break;
+ case REG_WR2_INT_VECTOR: do_sioreg_wr2(data); break;
+ case REG_WR3_RX_CONTROL: do_sioreg_wr3(data); update_serial(); break;
+ case REG_WR4_RX_TX_MODES: do_sioreg_wr4(data); update_serial(); break;
+ case REG_WR5_TX_CONTROL: do_sioreg_wr5(data); update_serial(); update_rts(); break;
+ case REG_WR6_SYNC_OR_SDLC_A: do_sioreg_wr6(data); break;
+ case REG_WR7_SYNC_OR_SDLC_F: do_sioreg_wr7(data); break;
default:
logerror("Z80SIO \"%s\" Channel %c : Unsupported WRx register:%02x\n", m_owner->tag(), 'A' + m_index, reg);
}
@@ -1063,9 +1089,8 @@ void z80sio_channel::control_write(UINT8 data)
//-------------------------------------------------
-// data_read - read data register
+// data_read - read data register
//-------------------------------------------------
-
UINT8 z80sio_channel::data_read()
{
UINT8 data = 0;
@@ -1074,30 +1099,29 @@ UINT8 z80sio_channel::data_read()
{
// load data from the FIFO
data = m_rx_data_fifo[m_rx_fifo];
-
+
// load error status from the FIFO
m_rr1 = (m_rr1 & ~(RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR)) | m_rx_error_fifo[m_rx_fifo];
-
+
// decrease FIFO pointer
m_rx_fifo--;
-
+
if (m_rx_fifo < 0)
{
// no more characters available in the FIFO
m_rr0 &= ~ RR0_RX_CHAR_AVAILABLE;
}
}
-
+
LOG(("Z80SIO \"%s\" Channel %c : Data Register Read '%02x'\n", m_owner->tag(), 'A' + m_index, data));
-
+
return data;
}
-
+
//-------------------------------------------------
-// data_write - write data register
+// data_write - write data register
//-------------------------------------------------
-
void z80sio_channel::data_write(UINT8 data)
{
m_tx_data = data;
@@ -1116,25 +1140,24 @@ void z80sio_channel::data_write(UINT8 data)
}
else
{
+ LOG((" Transmitter %s, data byte dropped\n", m_wr5 & WR5_TX_ENABLE ? "not enabled" : "not emptied"));
m_rr0 &= ~RR0_TX_BUFFER_EMPTY;
}
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)
{
- 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)
{
+ LOG((" Overrun detected\n"));
// receive overrun error detected
m_rx_error |= RR1_RX_OVERRUN_ERROR;
@@ -1142,9 +1165,9 @@ void z80sio_channel::receive_data(UINT8 data)
{
case WR1_RX_INT_FIRST:
if (!m_rx_first)
- {
- m_uart->trigger_interrupt(m_index, INT_SPECIAL);
- }
+ {
+ m_uart->trigger_interrupt(m_index, INT_SPECIAL);
+ }
break;
case WR1_RX_INT_ALL_PARITY:
@@ -1157,13 +1180,13 @@ void z80sio_channel::receive_data(UINT8 data)
{
m_rx_fifo++;
}
-
+
// store received character and error status into FIFO
m_rx_data_fifo[m_rx_fifo] = data;
m_rx_error_fifo[m_rx_fifo] = m_rx_error;
-
+
m_rr0 |= RR0_RX_CHAR_AVAILABLE;
-
+
// receive interrupt
switch (m_wr1 & WR1_RX_INT_MODE_MASK)
{
@@ -1171,7 +1194,6 @@ void z80sio_channel::receive_data(UINT8 data)
if (m_rx_first)
{
m_uart->trigger_interrupt(m_index, INT_RECEIVE);
-
m_rx_first = 0;
}
break;
@@ -1180,17 +1202,20 @@ void z80sio_channel::receive_data(UINT8 data)
case WR1_RX_INT_ALL:
m_uart->trigger_interrupt(m_index, INT_RECEIVE);
break;
+ default:
+ LOG(("No interrupt triggered\n"));
+
}
}
//-------------------------------------------------
-// cts_w - clear to send handler
+// cts_w - clear to send handler
//-------------------------------------------------
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)
{
@@ -1224,7 +1249,7 @@ WRITE_LINE_MEMBER( z80sio_channel::cts_w )
//-------------------------------------------------
-// dcd_w - data carrier detected handler
+// dcd_w - data carrier detected handler
//-------------------------------------------------
WRITE_LINE_MEMBER( z80sio_channel::dcd_w )
@@ -1262,7 +1287,7 @@ WRITE_LINE_MEMBER( z80sio_channel::dcd_w )
//-------------------------------------------------
-// sh_w - Sync Hunt handler
+// sh_w - Sync Hunt handler
//-------------------------------------------------
WRITE_LINE_MEMBER( z80sio_channel::sync_w )
@@ -1295,7 +1320,7 @@ WRITE_LINE_MEMBER( z80sio_channel::sync_w )
//-------------------------------------------------
-// rxc_w - receive clock
+// rxc_w - receive clock
//-------------------------------------------------
WRITE_LINE_MEMBER( z80sio_channel::rxc_w )
@@ -1317,7 +1342,7 @@ WRITE_LINE_MEMBER( z80sio_channel::rxc_w )
//-------------------------------------------------
-// txc_w - transmit clock
+// txc_w - transmit clock
//-------------------------------------------------
WRITE_LINE_MEMBER( z80sio_channel::txc_w )
@@ -1339,7 +1364,7 @@ WRITE_LINE_MEMBER( z80sio_channel::txc_w )
//-------------------------------------------------
-// update_serial -
+// update_serial -
//-------------------------------------------------
void z80sio_channel::update_serial()
{
@@ -1347,7 +1372,7 @@ void z80sio_channel::update_serial()
stop_bits_t stop_bits = get_stop_bits();
parity_t parity;
- LOG(("Z80SIO update_serial\n"));
+ LOG(("Z80SIO update_serial\n"));
if (m_wr4 & WR4_PARITY_ENABLE)
{
@@ -1377,11 +1402,12 @@ void z80sio_channel::update_serial()
//-------------------------------------------------
-// set_dtr -
+// set_dtr -
//-------------------------------------------------
void z80sio_channel::set_dtr(int state)
{
+ LOG(("%s(%d)\n", FUNCNAME, state));
m_dtr = state;
if (m_index == z80sio_device::CHANNEL_A)
@@ -1391,7 +1417,7 @@ void z80sio_channel::set_dtr(int state)
}
//-------------------------------------------------
-// write_rx -
+// write_rx -
//-------------------------------------------------
WRITE_LINE_MEMBER(z80sio_channel::write_rx)
diff --git a/src/devices/machine/z80sio.h b/src/devices/machine/z80sio.h
index d1a3eeb26ea..bf75e8fe362 100644
--- a/src/devices/machine/z80sio.h
+++ b/src/devices/machine/z80sio.h
@@ -59,7 +59,7 @@
#include "cpu/z80/z80daisy.h"
//**************************************************************************
-// DEVICE CONFIGURATION MACROS
+// DEVICE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_Z80SIO_ADD(_tag, _clock, _rxa, _txa, _rxb, _txb) \
@@ -116,7 +116,7 @@
//**************************************************************************
-// TYPE DEFINITIONS
+// TYPE DEFINITIONS
//**************************************************************************
// ======================> z80sio_channel
@@ -142,22 +142,22 @@ public:
virtual void rcv_callback();
virtual void rcv_complete();
- // read register handlers
- UINT8 do_sioreg_rr0();
- UINT8 do_sioreg_rr1();
- UINT8 do_sioreg_rr2();
-
- // write register handlers
- void do_sioreg_wr0(UINT8 data);
- void do_sioreg_wr0_resets(UINT8 data);
- void do_sioreg_wr1(UINT8 data);
- void do_sioreg_wr2(UINT8 data);
- void do_sioreg_wr3(UINT8 data);
- void do_sioreg_wr4(UINT8 data);
- void do_sioreg_wr5(UINT8 data);
- void do_sioreg_wr6(UINT8 data);
- void do_sioreg_wr7(UINT8 data);
-
+ // read register handlers
+ UINT8 do_sioreg_rr0();
+ UINT8 do_sioreg_rr1();
+ UINT8 do_sioreg_rr2();
+
+ // write register handlers
+ void do_sioreg_wr0(UINT8 data);
+ void do_sioreg_wr0_resets(UINT8 data);
+ void do_sioreg_wr1(UINT8 data);
+ void do_sioreg_wr2(UINT8 data);
+ void do_sioreg_wr3(UINT8 data);
+ void do_sioreg_wr4(UINT8 data);
+ void do_sioreg_wr5(UINT8 data);
+ void do_sioreg_wr6(UINT8 data);
+ void do_sioreg_wr7(UINT8 data);
+
UINT8 control_read();
void control_write(UINT8 data);
@@ -178,11 +178,11 @@ public:
int m_txc;
// Register state
- // read registers enum
+ // read registers enum
UINT8 m_rr0; // REG_RR0_STATUS
UINT8 m_rr1; // REG_RR1_SPEC_RCV_COND
UINT8 m_rr2; // REG_RR2_INTERRUPT_VECT
- // write registers enum
+ // write registers enum
UINT8 m_wr0; // REG_WR0_COMMAND_REGPT
UINT8 m_wr1; // REG_WR1_INT_DMA_ENABLE
UINT8 m_wr2; // REG_WR2_INT_VECTOR
@@ -203,160 +203,160 @@ protected:
INT_SPECIAL
};
- // Read registers
- enum
- {
- REG_RR0_STATUS = 0,
- REG_RR1_SPEC_RCV_COND = 1,
- REG_RR2_INTERRUPT_VECT = 2
- };
-
- // Write registers
- enum
- {
- REG_WR0_COMMAND_REGPT = 0,
- REG_WR1_INT_DMA_ENABLE = 1,
- REG_WR2_INT_VECTOR = 2,
- REG_WR3_RX_CONTROL = 3,
- REG_WR4_RX_TX_MODES = 4,
- REG_WR5_TX_CONTROL = 5,
- REG_WR6_SYNC_OR_SDLC_A = 6,
- REG_WR7_SYNC_OR_SDLC_F = 7
- };
-
+ // Read registers
enum
{
- RR0_RX_CHAR_AVAILABLE = 0x01,
- RR0_INTERRUPT_PENDING = 0x02,
- RR0_TX_BUFFER_EMPTY = 0x04,
- RR0_DCD = 0x08,
- RR0_SYNC_HUNT = 0x10,
- RR0_CTS = 0x20,
- RR0_TX_UNDERRUN = 0x40,
- RR0_BREAK_ABORT = 0x80
+ REG_RR0_STATUS = 0,
+ REG_RR1_SPEC_RCV_COND = 1,
+ REG_RR2_INTERRUPT_VECT = 2
};
-
+
+ // Write registers
enum
{
- RR1_ALL_SENT = 0x01,
- RR1_RESIDUE_CODE_MASK = 0x0e,
- RR1_PARITY_ERROR = 0x10,
- RR1_RX_OVERRUN_ERROR = 0x20,
- RR1_CRC_FRAMING_ERROR = 0x40,
- RR1_END_OF_FRAME = 0x80
+ REG_WR0_COMMAND_REGPT = 0,
+ REG_WR1_INT_DMA_ENABLE = 1,
+ REG_WR2_INT_VECTOR = 2,
+ REG_WR3_RX_CONTROL = 3,
+ REG_WR4_RX_TX_MODES = 4,
+ REG_WR5_TX_CONTROL = 5,
+ REG_WR6_SYNC_OR_SDLC_A = 6,
+ REG_WR7_SYNC_OR_SDLC_F = 7
+ };
+
+ enum
+ {
+ RR0_RX_CHAR_AVAILABLE = 0x01,
+ RR0_INTERRUPT_PENDING = 0x02,
+ RR0_TX_BUFFER_EMPTY = 0x04,
+ RR0_DCD = 0x08,
+ RR0_SYNC_HUNT = 0x10,
+ RR0_CTS = 0x20,
+ RR0_TX_UNDERRUN = 0x40,
+ RR0_BREAK_ABORT = 0x80
};
- enum
- { // TODO: overload SIO functionality
- RR2_INT_VECTOR_MASK = 0xff, // SCC channel A, SIO channel B (special case)
- RR2_INT_VECTOR_V1 = 0x02, // SIO (special case) /SCC Channel B
- RR2_INT_VECTOR_V2 = 0x04, // SIO (special case) /SCC Channel B
- RR2_INT_VECTOR_V3 = 0x08 // SIO (special case) /SCC Channel B
- };
+ enum
+ {
+ RR1_ALL_SENT = 0x01,
+ RR1_RESIDUE_CODE_MASK = 0x0e,
+ RR1_PARITY_ERROR = 0x10,
+ RR1_RX_OVERRUN_ERROR = 0x20,
+ RR1_CRC_FRAMING_ERROR = 0x40,
+ RR1_END_OF_FRAME = 0x80
+ };
enum
+ { // TODO: overload SIO functionality
+ RR2_INT_VECTOR_MASK = 0xff, // SCC channel A, SIO channel B (special case)
+ RR2_INT_VECTOR_V1 = 0x02, // SIO (special case) /SCC Channel B
+ RR2_INT_VECTOR_V2 = 0x04, // SIO (special case) /SCC Channel B
+ RR2_INT_VECTOR_V3 = 0x08 // SIO (special case) /SCC Channel B
+ };
+
+ enum
{
- WR0_REGISTER_MASK = 0x07,
- WR0_COMMAND_MASK = 0x38,
- WR0_NULL = 0x00,
- WR0_SEND_ABORT = 0x08, // not supported
- WR0_RESET_EXT_STATUS = 0x10,
- WR0_CHANNEL_RESET = 0x18,
- WR0_ENABLE_INT_NEXT_RX = 0x20,
- WR0_RESET_TX_INT = 0x28, // not supported
- WR0_ERROR_RESET = 0x30,
- WR0_RETURN_FROM_INT = 0x38, // not supported
- WR0_CRC_RESET_CODE_MASK = 0xc0, // not supported
- WR0_CRC_RESET_NULL = 0x00, // not supported
- WR0_CRC_RESET_RX = 0x40, // not supported
- WR0_CRC_RESET_TX = 0x80, // not supported
+ WR0_REGISTER_MASK = 0x07,
+ WR0_COMMAND_MASK = 0x38,
+ WR0_NULL = 0x00,
+ WR0_SEND_ABORT = 0x08, // not supported
+ WR0_RESET_EXT_STATUS = 0x10,
+ WR0_CHANNEL_RESET = 0x18,
+ WR0_ENABLE_INT_NEXT_RX = 0x20,
+ WR0_RESET_TX_INT = 0x28, // not supported
+ WR0_ERROR_RESET = 0x30,
+ WR0_RETURN_FROM_INT = 0x38, // not supported
+ WR0_CRC_RESET_CODE_MASK = 0xc0, // not supported
+ WR0_CRC_RESET_NULL = 0x00, // not supported
+ WR0_CRC_RESET_RX = 0x40, // not supported
+ WR0_CRC_RESET_TX = 0x80, // not supported
WR0_CRC_RESET_TX_UNDERRUN = 0xc0 // not supported
};
enum
{
- WR1_EXT_INT_ENABLE = 0x01,
- WR1_TX_INT_ENABLE = 0x02,
- WR1_STATUS_VECTOR = 0x04,
- WR1_RX_INT_MODE_MASK = 0x18,
- WR1_RX_INT_DISABLE = 0x00,
- WR1_RX_INT_FIRST = 0x08,
- WR1_RX_INT_ALL_PARITY = 0x10, // not supported
- WR1_RX_INT_ALL = 0x18,
- WR1_WRDY_ON_RX_TX = 0x20, // not supported
- WR1_WRDY_FUNCTION = 0x40, // not supported
- WR1_WRDY_ENABLE = 0x80 // not supported
+ WR1_EXT_INT_ENABLE = 0x01,
+ WR1_TX_INT_ENABLE = 0x02,
+ WR1_STATUS_VECTOR = 0x04,
+ WR1_RX_INT_MODE_MASK = 0x18,
+ WR1_RX_INT_DISABLE = 0x00,
+ WR1_RX_INT_FIRST = 0x08,
+ WR1_RX_INT_ALL_PARITY = 0x10, // not supported
+ WR1_RX_INT_ALL = 0x18,
+ WR1_WRDY_ON_RX_TX = 0x20, // not supported
+ WR1_WRDY_FUNCTION = 0x40, // not supported
+ WR1_WRDY_ENABLE = 0x80 // not supported
};
enum
{
- WR2_DATA_XFER_INT = 0x00, // not supported
- WR2_DATA_XFER_DMA_INT = 0x01, // not supported
- WR2_DATA_XFER_DMA = 0x02, // not supported
- WR2_DATA_XFER_ILLEGAL = 0x03, // not supported
- WR2_DATA_XFER_MASK = 0x03, // not supported
- WR2_PRIORITY = 0x04, // not supported
- WR2_MODE_8085_1 = 0x00, // not supported
- WR2_MODE_8085_2 = 0x08, // not supported
- WR2_MODE_8086_8088 = 0x10, // not supported
- WR2_MODE_ILLEGAL = 0x18, // not supported
- WR2_MODE_MASK = 0x18, // not supported
- WR2_VECTORED_INT = 0x20, // not supported
- WR2_PIN10_SYNDETB_RTSB = 0x80 // not supported
+ WR2_DATA_XFER_INT = 0x00, // not supported
+ WR2_DATA_XFER_DMA_INT = 0x01, // not supported
+ WR2_DATA_XFER_DMA = 0x02, // not supported
+ WR2_DATA_XFER_ILLEGAL = 0x03, // not supported
+ WR2_DATA_XFER_MASK = 0x03, // not supported
+ WR2_PRIORITY = 0x04, // not supported
+ WR2_MODE_8085_1 = 0x00, // not supported
+ WR2_MODE_8085_2 = 0x08, // not supported
+ WR2_MODE_8086_8088 = 0x10, // not supported
+ WR2_MODE_ILLEGAL = 0x18, // not supported
+ WR2_MODE_MASK = 0x18, // not supported
+ WR2_VECTORED_INT = 0x20, // not supported
+ WR2_PIN10_SYNDETB_RTSB = 0x80 // not supported
};
enum
{
- WR3_RX_ENABLE = 0x01,
+ WR3_RX_ENABLE = 0x01,
WR3_SYNC_CHAR_LOAD_INHIBIT= 0x02, // not supported
- WR3_ADDRESS_SEARCH_MODE = 0x04, // not supported
- WR3_RX_CRC_ENABLE = 0x08, // not supported
- WR3_ENTER_HUNT_PHASE = 0x10, // not supported
- WR3_AUTO_ENABLES = 0x20,
- WR3_RX_WORD_LENGTH_MASK = 0xc0,
- WR3_RX_WORD_LENGTH_5 = 0x00,
- WR3_RX_WORD_LENGTH_7 = 0x40,
- WR3_RX_WORD_LENGTH_6 = 0x80,
- WR3_RX_WORD_LENGTH_8 = 0xc0
+ WR3_ADDRESS_SEARCH_MODE = 0x04, // not supported
+ WR3_RX_CRC_ENABLE = 0x08, // not supported
+ WR3_ENTER_HUNT_PHASE = 0x10, // not supported
+ WR3_AUTO_ENABLES = 0x20,
+ WR3_RX_WORD_LENGTH_MASK = 0xc0,
+ WR3_RX_WORD_LENGTH_5 = 0x00,
+ WR3_RX_WORD_LENGTH_7 = 0x40,
+ WR3_RX_WORD_LENGTH_6 = 0x80,
+ WR3_RX_WORD_LENGTH_8 = 0xc0
};
enum
{
- WR4_PARITY_ENABLE = 0x01,
- WR4_PARITY_EVEN = 0x02,
- WR4_STOP_BITS_MASK = 0x0c,
- WR4_STOP_BITS_1 = 0x04,
- WR4_STOP_BITS_1_5 = 0x08, // not supported
- WR4_STOP_BITS_2 = 0x0c,
- WR4_SYNC_MODE_MASK = 0x30, // not supported
- WR4_SYNC_MODE_8_BIT = 0x00, // not supported
- WR4_SYNC_MODE_16_BIT = 0x10, // not supported
- WR4_SYNC_MODE_SDLC = 0x20, // not supported
- WR4_SYNC_MODE_EXT = 0x30, // not supported
- WR4_CLOCK_RATE_MASK = 0xc0,
- WR4_CLOCK_RATE_X1 = 0x00,
- WR4_CLOCK_RATE_X16 = 0x40,
- WR4_CLOCK_RATE_X32 = 0x80,
- WR4_CLOCK_RATE_X64 = 0xc0
+ WR4_PARITY_ENABLE = 0x01,
+ WR4_PARITY_EVEN = 0x02,
+ WR4_STOP_BITS_MASK = 0x0c,
+ WR4_STOP_BITS_1 = 0x04,
+ WR4_STOP_BITS_1_5 = 0x08, // not supported
+ WR4_STOP_BITS_2 = 0x0c,
+ WR4_SYNC_MODE_MASK = 0x30, // not supported
+ WR4_SYNC_MODE_8_BIT = 0x00, // not supported
+ WR4_SYNC_MODE_16_BIT = 0x10, // not supported
+ WR4_SYNC_MODE_SDLC = 0x20, // not supported
+ WR4_SYNC_MODE_EXT = 0x30, // not supported
+ WR4_CLOCK_RATE_MASK = 0xc0,
+ WR4_CLOCK_RATE_X1 = 0x00,
+ WR4_CLOCK_RATE_X16 = 0x40,
+ WR4_CLOCK_RATE_X32 = 0x80,
+ WR4_CLOCK_RATE_X64 = 0xc0
};
enum
{
- WR5_TX_CRC_ENABLE = 0x01, // not supported
- WR5_RTS = 0x02,
- WR5_CRC16 = 0x04, // not supported
- WR5_TX_ENABLE = 0x08,
- WR5_SEND_BREAK = 0x10,
- WR5_TX_WORD_LENGTH_MASK = 0x60,
- WR5_TX_WORD_LENGTH_5 = 0x00,
- WR5_TX_WORD_LENGTH_6 = 0x40,
- WR5_TX_WORD_LENGTH_7 = 0x20,
- WR5_TX_WORD_LENGTH_8 = 0x60,
- WR5_DTR = 0x80
+ WR5_TX_CRC_ENABLE = 0x01, // not supported
+ WR5_RTS = 0x02,
+ WR5_CRC16 = 0x04, // not supported
+ WR5_TX_ENABLE = 0x08,
+ WR5_SEND_BREAK = 0x10,
+ WR5_TX_WORD_LENGTH_MASK = 0x60,
+ WR5_TX_WORD_LENGTH_5 = 0x00,
+ WR5_TX_WORD_LENGTH_6 = 0x40,
+ WR5_TX_WORD_LENGTH_7 = 0x20,
+ WR5_TX_WORD_LENGTH_8 = 0x60,
+ WR5_DTR = 0x80
};
void update_serial();
- void update_rts();
+ void update_rts();
void set_dtr(int state);
void set_rts(int state);
@@ -366,30 +366,30 @@ protected:
int get_tx_word_length();
// receiver state
- UINT8 m_rx_data_fifo[3]; // receive data FIFO
- UINT8 m_rx_error_fifo[3]; // receive error FIFO
- UINT8 m_rx_error; // current receive error
- int m_rx_fifo; // receive FIFO pointer
+ UINT8 m_rx_data_fifo[3]; // receive data FIFO
+ UINT8 m_rx_error_fifo[3]; // receive error FIFO
+ UINT8 m_rx_error; // current receive error
+ int m_rx_fifo; // receive FIFO pointer
- int m_rx_clock; // receive clock pulse count
- int m_rx_first; // first character received
- int m_rx_break; // receive break condition
- UINT8 m_rx_rr0_latch; // read register 0 latched
+ int m_rx_clock; // receive clock pulse count
+ int m_rx_first; // first character received
+ int m_rx_break; // receive break condition
+ UINT8 m_rx_rr0_latch; // read register 0 latched
int m_rxd;
- int m_sh; // sync hunt
- int m_cts; // clear to send latch
- int m_dcd; // data carrier detect latch
+ int m_sh; // sync hunt
+ int m_cts; // clear to send latch
+ int m_dcd; // data carrier detect latch
// transmitter state
- UINT8 m_tx_data; // transmit data register
- int m_tx_clock; // transmit clock pulse count
+ UINT8 m_tx_data; // transmit data register
+ int m_tx_clock; // transmit clock pulse count
- int m_dtr; // data terminal ready
- int m_rts; // request to send
+ int m_dtr; // data terminal ready
+ int m_rts; // request to send
// synchronous state
- UINT16 m_sync; // sync character
+ UINT16 m_sync; // sync character
int m_index;
z80sio_device *m_uart;
@@ -403,11 +403,11 @@ class z80sio_device : public device_t,
{
friend class z80sio_channel;
-public:
+ public:
// construction/destruction
z80sio_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT32 variant, const char *shortname, const char *source);
z80sio_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-
+
template<class _Object> static devcb_base &set_out_txda_callback(device_t &device, _Object object) { return downcast<z80sio_device &>(device).m_out_txda_cb.set_callback(object); }
template<class _Object> static devcb_base &set_out_dtra_callback(device_t &device, _Object object) { return downcast<z80sio_device &>(device).m_out_dtra_cb.set_callback(object); }
template<class _Object> static devcb_base &set_out_rtsa_callback(device_t &device, _Object object) { return downcast<z80sio_device &>(device).m_out_rtsa_cb.set_callback(object); }
@@ -504,26 +504,25 @@ protected:
int m_rxcb;
int m_txcb;
- devcb_write_line m_out_txda_cb;
- devcb_write_line m_out_dtra_cb;
- devcb_write_line m_out_rtsa_cb;
- devcb_write_line m_out_wrdya_cb;
- devcb_write_line m_out_synca_cb;
-
- devcb_write_line m_out_txdb_cb;
- devcb_write_line m_out_dtrb_cb;
- devcb_write_line m_out_rtsb_cb;
- devcb_write_line m_out_wrdyb_cb;
- devcb_write_line m_out_syncb_cb;
-
- devcb_write_line m_out_int_cb;
- devcb_write_line m_out_rxdrqa_cb;
- devcb_write_line m_out_txdrqa_cb;
- devcb_write_line m_out_rxdrqb_cb;
- devcb_write_line m_out_txdrqb_cb;
-
- int m_int_state[8]; // interrupt state
-
+ devcb_write_line m_out_txda_cb;
+ devcb_write_line m_out_dtra_cb;
+ devcb_write_line m_out_rtsa_cb;
+ devcb_write_line m_out_wrdya_cb;
+ devcb_write_line m_out_synca_cb;
+
+ devcb_write_line m_out_txdb_cb;
+ devcb_write_line m_out_dtrb_cb;
+ devcb_write_line m_out_rtsb_cb;
+ devcb_write_line m_out_wrdyb_cb;
+ devcb_write_line m_out_syncb_cb;
+
+ devcb_write_line m_out_int_cb;
+ devcb_write_line m_out_rxdrqa_cb;
+ devcb_write_line m_out_txdrqa_cb;
+ devcb_write_line m_out_rxdrqb_cb;
+ devcb_write_line m_out_txdrqb_cb;
+
+ int m_int_state[8]; // interrupt state
int m_variant;
};