summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author R. Belmont <rb6502@users.noreply.github.com>2016-07-01 08:02:18 -0400
committer GitHub <noreply@github.com>2016-07-01 08:02:18 -0400
commita957ae0f9ad9d4b9e906fc01d6f9b1e3b7ff391c (patch)
tree717ae0bae894df6220e866013fd4dbc83a1535f7
parent7b534607fee81cfd5d5b2080b02be0856299eaf7 (diff)
parent6363e821583b9c2f4b76460960cf89fb84e5309e (diff)
Merge pull request #1016 from JoakimLarsson/fcisio1
New Board: Force Computers ISIO-1/2
-rw-r--r--scripts/target/mame/mess.lua1
-rw-r--r--src/devices/machine/68230pit.cpp334
-rw-r--r--src/devices/machine/68230pit.h57
-rw-r--r--src/devices/machine/scnxx562.cpp1031
-rw-r--r--src/devices/machine/scnxx562.h94
-rw-r--r--src/mame/drivers/fcisio.cpp309
-rw-r--r--src/mame/mame.lst3
7 files changed, 1467 insertions, 362 deletions
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index 7c050bd06a5..3532f4d5ad7 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -3099,6 +3099,7 @@ files {
MAME_DIR .. "src/mame/drivers/fanucs15.cpp",
MAME_DIR .. "src/mame/drivers/fanucspmg.cpp",
MAME_DIR .. "src/mame/drivers/fc100.cpp",
+ MAME_DIR .. "src/mame/drivers/fcisio.cpp",
MAME_DIR .. "src/mame/drivers/fcscsi.cpp",
MAME_DIR .. "src/mame/drivers/fk1.cpp",
MAME_DIR .. "src/mame/drivers/ft68m.cpp",
diff --git a/src/devices/machine/68230pit.cpp b/src/devices/machine/68230pit.cpp
index ed9cfee7327..7398543dd52 100644
--- a/src/devices/machine/68230pit.cpp
+++ b/src/devices/machine/68230pit.cpp
@@ -1,17 +1,26 @@
// license:BSD-3-Clause
-// copyright-holders:Joakim Larsson Edstr??m
+// copyright-holders:Joakim Larsson Edstrom
/**********************************************************************
*
* Motorola MC68230 PI/T Parallell Interface and Timer
*
-* Revisions
-* 2015-07-15 JLE initial
+* PORT MODES INCLUDE :
+* - BIT I/O
+* - UNIDIRECTIONAL 8 BIT AND 16 BIT
+* - BIDIRECTIONAL 8 BIT AND 16 BIT
+* PROGRAMMABLE HANDSHAKING OPTIONS
+* 24-BIT PROGRAMMABLE TIMER MODES
+* FIVE SEPARATE INTERRUPT VECTORS SEPARATE PORT AND TIMER INTERRUPT SERVICE REQUESTS
+* REGISTERS AREREAD/WRITEAND DIRECTLY ADDRESSABLE
+* REGISTERS ARE ADDRESSED FOR MOVEP (Move Peripheral) AND DMAC COMPATIBILITY
+*
+* Revisions: 2015-07-15 JLE initial
*
* Todo
-* - Add clock and timers
+* - Complete support for clock and timers
+* - Add interrupt support
+* - Add DMA support
* - Add double buffering for each submode
-* - Add all missing registers
-* - Add configuration
**********************************************************************/
#include "68230pit.h"
@@ -32,9 +41,6 @@
#define LLFORMAT "%lld"
#endif
-//#define LOG(x) x
-//#define logerror printf
-
//**************************************************************************
// DEVICE TYPE DEFINITIONS
//**************************************************************************
@@ -45,9 +51,7 @@ const device_type PIT68230 = &device_creator<pit68230_device>;
// pit68230_device - constructors
//-------------------------------------------------
pit68230_device::pit68230_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_execute_interface (mconfig, *this)
- , m_icount (0)
+ : device_t (mconfig, type, name, tag, owner, clock, shortname, source)
, m_pa_out_cb(*this)
, m_pa_in_cb(*this)
, m_pb_out_cb(*this)
@@ -63,25 +67,27 @@ pit68230_device::pit68230_device(const machine_config &mconfig, device_type type
, m_paddr(0)
, m_pbddr(0)
, m_pcddr(0)
+ , m_pivr(0)
, m_pacr(0)
, m_pbcr(0)
, m_padr(0)
, m_pbdr(0)
+ , m_pcdr(0)
, m_psr(0)
, m_tcr(0)
+ , m_tivr(0)
, m_cpr(0)
- // , m_cprh(0)
- // , m_cprm(0)
- // , m_cprl(0)
+ // , m_cprh(0) // Collectivelly handled by m_cpr
+ // , m_cprm(0) // Collectivelly handled by m_cpr
+ // , m_cprl(0) // Collectivelly handled by m_cpr
, m_cntr(0)
+ , m_tsr(0)
{
}
pit68230_device::pit68230_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
- : device_t (mconfig, PIT68230, "PIT68230", tag, owner, clock, "pit68230", __FILE__),
- device_execute_interface (mconfig, *this)
- , m_icount (0)
+ : device_t (mconfig, PIT68230, "PIT68230", tag, owner, clock, "pit68230", __FILE__)
, m_pa_out_cb (*this)
, m_pa_in_cb(*this)
, m_pb_out_cb(*this)
@@ -97,17 +103,21 @@ pit68230_device::pit68230_device(const machine_config &mconfig, const char *tag,
, m_paddr(0)
, m_pbddr(0)
, m_pcddr(0)
+ , m_pivr(0)
, m_pacr(0)
, m_pbcr(0)
, m_padr(0)
, m_pbdr(0)
+ , m_pcdr(0)
, m_psr(0)
, m_tcr(0)
+ , m_tivr(0)
, m_cpr(0)
- // , m_cprh(0)
- // , m_cprm(0)
- // , m_cprl(0)
+ // , m_cprh(0) // Collectivelly handled by m_cpr
+ // , m_cprm(0) // Collectivelly handled by m_cpr
+ // , m_cprl(0) // Collectivelly handled by m_cpr
, m_cntr(0)
+ , m_tsr(0)
{
}
@@ -117,17 +127,40 @@ pit68230_device::pit68230_device(const machine_config &mconfig, const char *tag,
void pit68230_device::device_start ()
{
LOG(("%s\n", FUNCNAME));
- m_icountptr = &m_icount;
// resolve callbacks
m_pa_out_cb.resolve_safe();
m_pa_in_cb.resolve_safe(0);
m_pb_out_cb.resolve_safe();
m_pb_in_cb.resolve_safe(0);
+ m_pc_out_cb.resolve_safe();
+ m_pc_in_cb.resolve_safe(0);
m_h1_out_cb.resolve_safe();
m_h2_out_cb.resolve_safe();
m_h3_out_cb.resolve_safe();
m_h4_out_cb.resolve_safe();
+
+ // Timers
+ pit_timer = timer_alloc(TIMER_ID_PIT);
+
+ // state saving
+ save_item(NAME(m_pgcr));
+ save_item(NAME(m_psrr));
+ save_item(NAME(m_paddr));
+ save_item(NAME(m_pbddr));
+ save_item(NAME(m_pcddr));
+ save_item(NAME(m_pivr));
+ save_item(NAME(m_pacr));
+ save_item(NAME(m_pbcr));
+ save_item(NAME(m_padr));
+ save_item(NAME(m_pbdr));
+ save_item(NAME(m_pcdr));
+ save_item(NAME(m_psr));
+ save_item(NAME(m_tcr));
+ save_item(NAME(m_tivr));
+ save_item(NAME(m_cpr));
+ save_item(NAME(m_cntr));
+ save_item(NAME(m_tsr));
}
//-------------------------------------------------
@@ -142,11 +175,15 @@ void pit68230_device::device_reset ()
m_paddr = 0;
m_pbddr = 0;
m_pcddr = 0;
+ m_pivr = 0x0f;
m_pacr = 0; m_h2_out_cb(m_pacr);
m_pbcr = 0;
- m_padr = 0; m_pa_out_cb((offs_t)0, m_padr); // TODO: check PADDR
- m_pbdr = 0;
+ m_padr = 0; m_pa_out_cb((offs_t)0, m_padr);
+ m_pbdr = 0; m_pb_out_cb((offs_t)0, m_pbdr);
m_psr = 0;
+ m_tcr = 0;
+ m_tivr = 0x0f;
+ m_tsr = 0;
}
//-------------------------------------------------
@@ -154,6 +191,22 @@ void pit68230_device::device_reset ()
//-------------------------------------------------
void pit68230_device::device_timer (emu_timer &timer, device_timer_id id, INT32 param, void *ptr)
{
+ switch(id)
+ {
+ case TIMER_ID_PIT:
+ if (m_cntr-- == 0) // Zero detect
+ {
+ /* TODO: Check mode and use preload value if required or just rollover 24 bit */
+ if ((m_tcr & REG_TCR_ZD) == 0)
+ m_cntr = m_cpr;
+ else // mask off to 24 bit on rollover
+ m_cntr &= 0xffffff;
+ }
+ break;
+ default:
+ LOG(("Unhandled Timer ID %d\n", id));
+ break;
+ }
}
void pit68230_device::h1_set (UINT8 state)
@@ -170,18 +223,6 @@ void pit68230_device::portb_setbit (UINT8 bit, UINT8 state)
LOG(("%02x %lld\n", m_pbdr, machine ().firstcpu->total_cycles ()));
}
-//-------------------------------------------------
-// execute_run -
-//-------------------------------------------------
-void pit68230_device::execute_run ()
-{
- do {
- synchronize ();
-
- m_icount--;
- } while (m_icount > 0);
-}
-
#if VERBOSE > 2
static INT32 ow_cnt = 0;
static INT32 ow_data = 0;
@@ -218,6 +259,11 @@ void pit68230_device::wr_pitreg_pcddr(UINT8 data)
m_pcddr = data;
}
+void pit68230_device::wr_pitreg_pivr(UINT8 data)
+{
+ LOG(("%s(%02x) \"%s\": Not implemented yet\n", FUNCNAME, data, m_owner->tag()));
+}
+
void pit68230_device::wr_pitreg_pacr(UINT8 data)
{
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
@@ -250,9 +296,25 @@ void pit68230_device::wr_pitreg_pbcr(UINT8 data)
void pit68230_device::wr_pitreg_padr(UINT8 data)
{
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
- m_padr = data;
+ m_padr |= (data & m_paddr);
+ // callbacks
+ m_pa_out_cb ((offs_t)0, m_padr);
+}
+
+void pit68230_device::wr_pitreg_pbdr(UINT8 data)
+{
+ LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
+ m_pbdr |= (data & m_pbddr);
+ // callbacks
+ m_pb_out_cb ((offs_t)0, m_pbdr & m_pbddr);
+}
+
+void pit68230_device::wr_pitreg_pcdr(UINT8 data)
+{
+ LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
+ m_pcdr |= (data & m_pcddr);
// callbacks
- m_pa_out_cb ((offs_t)0, m_padr); // TODO: check PADDR
+ m_pc_out_cb ((offs_t)0, m_pcdr);
}
void pit68230_device::wr_pitreg_psr(UINT8 data)
@@ -325,9 +387,60 @@ TCR bit 0 - Timer Enable
*/
void pit68230_device::wr_pitreg_tcr(UINT8 data)
{
- LOG(("%s(%02x) \"%s\": %s - %02x Timer %s\n",
- FUNCNAME, data, m_owner->tag(), FUNCNAME, data, data & REG_TCR_ENABLE ? "enabled" : "disabled"));
+ int tout = 0;
+ int tiack = 0;
+ int irq = 0;
+ int psc = 0;
+ int clk = 0;
+ int pen = 0;
+ int sqr = 0;
+
+ LOG(("%s(%02x) %s\n", FUNCNAME, data, m_owner->tag()));
m_tcr = data;
+ switch (m_tcr & REG_TCR_TOUT_TIACK_MASK)
+ {
+ case REG_TCR_PC3_PC7:
+ case REG_TCR_PC3_PC7_DC: LOG(("- PC3 and PC7 used as I/O pins\n")); break;
+ case REG_TCR_TOUT_PC7_SQ:
+ case REG_TCR_TOUT_PC7_SQ_DC: LOG(("- PC3 used as SQuare wave TOUT and PC7 used as I/O pin - not supported yet\n")); sqr = 1; break;
+ case REG_TCR_TOUT_TIACK: LOG(("- PC3 used as TOUT and PC7 used as TIACK - not supported yet\n")); tout = 1; tiack = 1; break;
+ case REG_TCR_TOUT_TIACK_INT: LOG(("- PC3 used as TOUT and PC7 used as TIACK, Interrupts enabled - not supported yet\n")); tout = 1; tiack = 1; irq = 1; break;
+ case REG_TCR_TOUT_PC7: LOG(("- PC3 used as TOUT and PC7 used as I/O pin - not supported yet\n")); break;
+ case REG_TCR_TOUT_PC7_INT: LOG(("- PC3 used as TOUT and PC7 used as I/O pin, Interrupts enabled - not supported yet\n")); break;
+ }
+
+ switch (m_tcr & REG_TCR_CC_MASK)
+ {
+ case REG_TCR_CC_PC2_CLK_PSC: LOG(("- PC2 used as I/O pin,CLK and x32 prescaler are used\n")); clk = 1; psc = 1; break;
+ case REG_TCR_CC_TEN_CLK_PSC: LOG(("- PC2 used as Timer enable/disable, CLK and presacaler are used\n")); pen = 1; clk = 1; psc = 1; break;
+ case REG_TCR_CC_TIN_PSC: LOG(("- PC2 used as Timer clock and the presacaler is used - not supported yet\n")); psc = 1; break;
+ case REG_TCR_CC_TIN_RAW: LOG(("- PC2 used as Timer clock and the presacaler is NOT used - not supported yet\n")); break;
+ }
+ LOG(("%s", m_tcr & REG_TCR_ZR ? "- Spec violation, should always be 0!\n" : ""));
+ LOG(("- Timer %s when reaching 0 (zero)\n", m_tcr & REG_TCR_ZD ? "rolls over" : "reload the preload values"));
+ LOG(("- Timer is %s\n", m_tcr & REG_TCR_ENABLE ? "enabled" : "disabled"));
+
+ if (m_tcr & REG_TCR_ENABLE)
+ {
+ m_cntr = 0;
+ if (pen == 1){ LOG(("PC2 enable/disable TBD\n")); }
+ if (clk == 1)
+ {
+ int rate = clock() / (psc == 1 ? 32 : 1);
+ pit_timer->adjust(attotime::from_hz(rate), TIMER_ID_PIT, attotime::from_hz(rate));
+ LOG(("PIT timer started @ rate: %d and CLK: %d,\n", rate, clock()));
+ }
+ }
+ else
+ {
+ m_tcr = tout + tiack + irq + sqr; // remove this when the variables are used for the different modes!! Just here to to avoid warnings
+ }
+}
+
+void pit68230_device::wr_pitreg_tivr(UINT8 data)
+{
+ LOG(("%s(%02x) \"%s\": \n", FUNCNAME, data, m_owner->tag()));
+ m_tivr = data;
}
void pit68230_device::wr_pitreg_cprh(UINT8 data)
@@ -335,7 +448,6 @@ void pit68230_device::wr_pitreg_cprh(UINT8 data)
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
m_cpr &= ~0xff0000;
m_cpr |= ((data << 16) & 0xff0000);
- // m_cprh = data;
}
void pit68230_device::wr_pitreg_cprm(UINT8 data)
@@ -343,7 +455,6 @@ void pit68230_device::wr_pitreg_cprm(UINT8 data)
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
m_cpr &= ~0x00ff00;
m_cpr |= ((data << 8) & 0x00ff00);
- // m_cprm = data;
}
void pit68230_device::wr_pitreg_cprl(UINT8 data)
@@ -351,28 +462,41 @@ void pit68230_device::wr_pitreg_cprl(UINT8 data)
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
m_cpr &= ~0x0000ff;
m_cpr |= ((data << 0) & 0x0000ff);
- // m_cprl = data;
+}
+
+void pit68230_device::wr_pitreg_tsr(UINT8 data)
+{
+ LOG(("%s(%02x) \"%s\": \n", FUNCNAME, data, m_owner->tag()));
+ m_tsr = data;
}
WRITE8_MEMBER (pit68230_device::write)
{
LOG(("%s %s \n",tag(), FUNCNAME));
switch (offset) {
- case PIT_68230_PGCR: wr_pitreg_pgcr(data); break;
- case PIT_68230_PSRR: wr_pitreg_psrr(data); break;
- case PIT_68230_PADDR: wr_pitreg_paddr(data); break;
- case PIT_68230_PBDDR: wr_pitreg_pbddr(data); break;
- case PIT_68230_PCDDR: wr_pitreg_pcddr(data); break;
- case PIT_68230_PACR: wr_pitreg_pacr(data); break;
- case PIT_68230_PBCR: wr_pitreg_pbcr(data); break;
- case PIT_68230_PADR: wr_pitreg_padr(data); break;
- case PIT_68230_PAAR: break; // RO register so ignored
- case PIT_68230_PBAR: break; // RO register so ignored
- case PIT_68230_PSR: wr_pitreg_psr(data); break;
- case PIT_68230_TCR: wr_pitreg_tcr(data); break;
- case PIT_68230_CPRH: wr_pitreg_cprh(data); break;
- case PIT_68230_CPRM: wr_pitreg_cprm(data); break;
- case PIT_68230_CPRL: wr_pitreg_cprl(data); break;
+ case PIT_68230_PGCR: wr_pitreg_pgcr(data); break;
+ case PIT_68230_PSRR: wr_pitreg_psrr(data); break;
+ case PIT_68230_PADDR: wr_pitreg_paddr(data); break;
+ case PIT_68230_PBDDR: wr_pitreg_pbddr(data); break;
+ case PIT_68230_PCDDR: wr_pitreg_pcddr(data); break;
+ case PIT_68230_PIVR: wr_pitreg_pivr(data); break;
+ case PIT_68230_PACR: wr_pitreg_pacr(data); break;
+ case PIT_68230_PBCR: wr_pitreg_pbcr(data); break;
+ case PIT_68230_PADR: wr_pitreg_padr(data); break;
+ case PIT_68230_PBDR: wr_pitreg_pbdr(data); break;
+ case PIT_68230_PAAR: break; // Ignores write per spec, read only register
+ case PIT_68230_PBAR: break; // Ignores write per spec, read only register
+ case PIT_68230_PCDR: wr_pitreg_pcdr(data); break;
+ case PIT_68230_PSR: wr_pitreg_psr(data); break;
+ case PIT_68230_TCR: wr_pitreg_tcr(data); break;
+ case PIT_68230_TIVR: wr_pitreg_tivr(data); break;
+ case PIT_68230_CPRH: wr_pitreg_cprh(data); break;
+ case PIT_68230_CPRM: wr_pitreg_cprm(data); break;
+ case PIT_68230_CPRL: wr_pitreg_cprl(data); break;
+ case PIT_68230_CNTRH: break; // Ignores write per spec, read only register
+ case PIT_68230_CNTRM: break; // Ignores write per spec, read only register
+ case PIT_68230_CNTRL: break; // Ignores write per spec, read only register
+ case PIT_68230_TSR: wr_pitreg_tsr(data); break;
default:
LOG (("Unhandled Write of %02x to register %02x", data, offset));
}
@@ -427,6 +551,12 @@ UINT8 pit68230_device::rr_pitreg_pcddr()
return m_pcddr;
}
+UINT8 pit68230_device::rr_pitreg_pivr()
+{
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pivr));
+ return m_pivr;
+}
+
UINT8 pit68230_device::rr_pitreg_pacr()
{
LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pacr));
@@ -441,6 +571,8 @@ UINT8 pit68230_device::rr_pitreg_pbcr()
UINT8 pit68230_device::rr_pitreg_padr()
{
+ m_padr &= m_paddr;
+ m_padr |= (m_pa_in_cb() & ~m_paddr);
LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_padr));
return m_padr;
}
@@ -454,11 +586,21 @@ UINT8 pit68230_device::rr_pitreg_padr()
* RESET pin. PB0-PB7 sits on pins 17-24 on a 48 pin DIP package */
UINT8 pit68230_device::rr_pitreg_pbdr()
{
+ m_pbdr &= m_pbddr;
+ m_pbdr |= (m_pb_in_cb() & ~m_pbddr);
LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pbdr));
return m_pbdr;
}
-/* The port A alternate register is an alternate register for reading the port A pins.
+UINT8 pit68230_device::rr_pitreg_pcdr()
+{
+ m_pcdr &= m_pcddr;
+ m_pcdr |= (m_pc_in_cb() & ~m_pcddr);
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pcdr));
+ return m_pcdr;
+}
+
+/* The port A alternate register is an alternate register for reading the port A pins.
It is a read-only address and no other PI/T condition is affected. In all modes,
the instantaneous pin level is read and no input latching is performed except at the
data bus interface. Writes to this address are answered with DTACK, but the data is ignored.*/
@@ -496,6 +638,36 @@ UINT8 pit68230_device::rr_pitreg_psr()
return m_psr;
}
+UINT8 pit68230_device::rr_pitreg_tcr()
+{
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_tcr));
+ return m_tcr;
+}
+
+UINT8 pit68230_device::rr_pitreg_tivr()
+{
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_tivr));
+ return m_tivr;
+}
+
+UINT8 pit68230_device::rr_pitreg_cprh()
+{
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, (m_cpr >> 16) & 0xff));
+ return (m_cpr >> 16) & 0xff;
+}
+
+UINT8 pit68230_device::rr_pitreg_cprm()
+{
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, (m_cpr >> 8) & 0xff));
+ return (m_cpr >> 8) & 0xff;
+}
+
+UINT8 pit68230_device::rr_pitreg_cprl()
+{
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, (m_cpr >> 0) & 0xff));
+ return (m_cpr >> 0) & 0xff;
+}
+
UINT8 pit68230_device::rr_pitreg_cntrh()
{
LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, (m_cntr >> 16) & 0xff));
@@ -514,25 +686,39 @@ UINT8 pit68230_device::rr_pitreg_cntrl()
return (m_cntr >> 0) & 0xff;
}
+UINT8 pit68230_device::rr_pitreg_tsr()
+{
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_tsr));
+ return m_tsr;
+}
+
READ8_MEMBER (pit68230_device::read){
UINT8 data;
switch (offset) {
- case PIT_68230_PGCR: data = rr_pitreg_pgcr(); break;
- case PIT_68230_PSRR: data = rr_pitreg_psrr(); break;
- case PIT_68230_PADDR: data = rr_pitreg_paddr(); break;
- case PIT_68230_PBDDR: data = rr_pitreg_pbddr(); break;
- case PIT_68230_PCDDR: data = rr_pitreg_pcddr(); break;
- case PIT_68230_PACR: data = rr_pitreg_pacr(); break;
- case PIT_68230_PBCR: data = rr_pitreg_pbcr(); break;
- case PIT_68230_PADR: data = rr_pitreg_padr(); break;
- case PIT_68230_PBDR: data = rr_pitreg_pbdr(); break;
- case PIT_68230_PAAR: data = rr_pitreg_paar(); break;
- case PIT_68230_PBAR: data = rr_pitreg_pbar(); break;
- case PIT_68230_PSR: data = rr_pitreg_psr(); break;
- case PIT_68230_CNTRH: data = rr_pitreg_cntrh(); break;
- case PIT_68230_CNTRM: data = rr_pitreg_cntrm(); break;
- case PIT_68230_CNTRL: data = rr_pitreg_cntrl(); break;
+ case PIT_68230_PGCR: data = rr_pitreg_pgcr(); break;
+ case PIT_68230_PSRR: data = rr_pitreg_psrr(); break;
+ case PIT_68230_PADDR: data = rr_pitreg_paddr(); break;
+ case PIT_68230_PBDDR: data = rr_pitreg_pbddr(); break;
+ case PIT_68230_PCDDR: data = rr_pitreg_pcddr(); break;
+ case PIT_68230_PIVR: data = rr_pitreg_pivr(); break;
+ case PIT_68230_PACR: data = rr_pitreg_pacr(); break;
+ case PIT_68230_PBCR: data = rr_pitreg_pbcr(); break;
+ case PIT_68230_PADR: data = rr_pitreg_padr(); break;
+ case PIT_68230_PBDR: data = rr_pitreg_pbdr(); break;
+ case PIT_68230_PAAR: data = rr_pitreg_paar(); break;
+ case PIT_68230_PBAR: data = rr_pitreg_pbar(); break;
+ case PIT_68230_PCDR: data = rr_pitreg_pcdr(); break;
+ case PIT_68230_PSR: data = rr_pitreg_psr(); break;
+ case PIT_68230_TCR: data = rr_pitreg_tcr(); break;
+ case PIT_68230_TIVR: data = rr_pitreg_tivr(); break;
+ case PIT_68230_CPRH: data = rr_pitreg_cprh(); break;
+ case PIT_68230_CPRM: data = rr_pitreg_cprm(); break;
+ case PIT_68230_CPRL: data = rr_pitreg_cprl(); break;
+ case PIT_68230_CNTRH: data = rr_pitreg_cntrh(); break;
+ case PIT_68230_CNTRM: data = rr_pitreg_cntrm(); break;
+ case PIT_68230_CNTRL: data = rr_pitreg_cntrl(); break;
+ case PIT_68230_TSR: data = rr_pitreg_tsr(); break;
default:
LOG (("Unhandled read register %02x\n", offset));
data = 0;
diff --git a/src/devices/machine/68230pit.h b/src/devices/machine/68230pit.h
index 736868afa66..ae71b0ba1ee 100644
--- a/src/devices/machine/68230pit.h
+++ b/src/devices/machine/68230pit.h
@@ -103,7 +103,7 @@
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
-class pit68230_device : public device_t, public device_execute_interface
+class pit68230_device : public device_t//, public device_execute_interface
{
public:
// construction/destruction
@@ -131,44 +131,73 @@ class pit68230_device : public device_t, public device_execute_interface
void wr_pitreg_paddr(UINT8 data);
void wr_pitreg_pbddr(UINT8 data);
void wr_pitreg_pcddr(UINT8 data);
+ void wr_pitreg_pivr(UINT8 data);
void wr_pitreg_pacr(UINT8 data);
void wr_pitreg_pbcr(UINT8 data);
void wr_pitreg_padr(UINT8 data);
+ void wr_pitreg_pbdr(UINT8 data);
void wr_pitreg_paar(UINT8 data);
void wr_pitreg_pbar(UINT8 data);
+ void wr_pitreg_pcdr(UINT8 data);
void wr_pitreg_psr(UINT8 data);
void wr_pitreg_tcr(UINT8 data);
+ void wr_pitreg_tivr(UINT8 data);
void wr_pitreg_cprh(UINT8 data);
void wr_pitreg_cprm(UINT8 data);
void wr_pitreg_cprl(UINT8 data);
+ void wr_pitreg_tsr(UINT8 data);
UINT8 rr_pitreg_pgcr();
UINT8 rr_pitreg_psrr();
UINT8 rr_pitreg_paddr();
UINT8 rr_pitreg_pbddr();
UINT8 rr_pitreg_pcddr();
+ UINT8 rr_pitreg_pivr();
UINT8 rr_pitreg_pacr();
UINT8 rr_pitreg_pbcr();
UINT8 rr_pitreg_padr();
UINT8 rr_pitreg_pbdr();
UINT8 rr_pitreg_paar();
UINT8 rr_pitreg_pbar();
+ UINT8 rr_pitreg_pcdr();
UINT8 rr_pitreg_psr();
+ UINT8 rr_pitreg_tcr();
+ UINT8 rr_pitreg_tivr();
+ UINT8 rr_pitreg_cprh();
+ UINT8 rr_pitreg_cprm();
+ UINT8 rr_pitreg_cprl();
UINT8 rr_pitreg_cntrh();
UINT8 rr_pitreg_cntrm();
UINT8 rr_pitreg_cntrl();
+ UINT8 rr_pitreg_tsr();
protected:
enum {
- REG_TCR_ENABLE = 0x01
+ REG_TCR_ENABLE = 0x01,
+ REG_TCR_CC_MASK = 0x06,
+ REG_TCR_CC_PC2_CLK_PSC = 0x00,
+ REG_TCR_CC_TEN_CLK_PSC = 0x02,
+ REG_TCR_CC_TIN_PSC = 0x04,
+ REG_TCR_CC_TIN_RAW = 0x06,
+ REG_TCR_ZR = 0x08,
+ REG_TCR_ZD = 0x10,
+ REG_TCR_TOUT_TIACK_MASK = 0xe0, // 1 1 1
+ REG_TCR_PC3_PC7 = 0x00, // 0 0 0
+ REG_TCR_PC3_PC7_DC = 0x20, // 0 0 1
+ REG_TCR_TOUT_PC7_SQ = 0x40, // 0 1 0
+ REG_TCR_TOUT_PC7_SQ_DC = 0x60, // 0 1 1
+ REG_TCR_TOUT_TIACK = 0x80, // 1 0 0
+ REG_TCR_TOUT_TIACK_INT = 0xa0, // 1 0 1
+ REG_TCR_TOUT_PC7 = 0xc0, // 1 1 0
+ REG_TCR_TOUT_PC7_INT = 0xe0, // 1 1 1
};
// device-level overrides
virtual void device_start () override;
virtual void device_reset () override;
virtual void device_timer (emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual void execute_run () override;
+ // virtual void execute_run () override;
int m_icount;
devcb_write8 m_pa_out_cb;
@@ -188,19 +217,29 @@ protected:
UINT8 m_paddr; // Port A Data Direction register
UINT8 m_pbddr; // Port B Data Direction register
UINT8 m_pcddr; // Port C Data Direction register
+ UINT8 m_pivr; // Ports Interrupt vector
UINT8 m_pacr; // Port A Control register
UINT8 m_pbcr; // Port B Control register
UINT8 m_padr; // Port A Data register
UINT8 m_pbdr; // Port B Data register
+ UINT8 m_pcdr; // Port C Data register
UINT8 m_psr; // Port Status Register
- UINT8 m_tcr; // Timer Control Register
- int m_cpr; // Counter Preload Registers (3 x 8 = 24 bits)
- // UINT8 m_cprh; // Counter Preload Register High
- // UINT8 m_cprm; // Counter Preload Register Mid
- // UINT8 m_cprl; // Counter Preload Register Low
- int m_cntr; // - The 24 bit Counter
+ UINT8 m_tcr; // Timer Control Register
+ UINT8 m_tivr; // Timer Interrupt Vector register
+ int m_cpr; // Counter Preload Registers (3 x 8 = 24 bits)
+ int m_cntr; // - The 24 bit Counter
+ UINT8 m_tsr; // Timer Status Register
+
+ // Timers
+ emu_timer *pit_timer;
+
+ enum
+ {
+ TIMER_ID_PIT
+ };
};
// device type definition
extern const device_type PIT68230;
+
#endif /* __68230PIT_H__ */
diff --git a/src/devices/machine/scnxx562.cpp b/src/devices/machine/scnxx562.cpp
index e4e388eade4..ca217d61d1d 100644
--- a/src/devices/machine/scnxx562.cpp
+++ b/src/devices/machine/scnxx562.cpp
@@ -36,13 +36,13 @@ DONE (x) (p=partly) NMOS CMOS
Channels 2 FD 2 FD
Synch data rates 4Mbps 10Mbps
----- asynchrounous features ------------------
- p 5-8 bit per char Y Y
- y 1,1.5,2 stop bits Y Y in 1/16 bit increments
- p odd/even parity Y Y
+ x 5-8 bit per char Y Y
+ p 1-2 stop bits Y Y TODO: 1/16 bit increments
+ p odd/even parity Y Y TODO: parity generation on Tx
x1,x16 Y Y
break det/gen Y Y
- parity, framing & Y Y
- overrun error det
+ p parity, framing & Y Y TODO: parity check on Rx
+ overrun error det
-- byte oriented synchrounous features --
Int/ext char sync Y Y
1/2 synch chars ? ?
@@ -56,15 +56,15 @@ DONE (x) (p=partly) NMOS CMOS
CRC gen/det Y Y
SDLC loop w EOP Y Y
--
- Receiver FIFO 4 16
- Transmitter FIFO 4 16
- NRZ, NRZI, FM1 or Y Y
+ x Receiver FIFO 4 16
+ x Transmitter FIFO 4 16
+ NRZ, NRZI, FM1 or Y Y
FM2 enc/dec
Manchester dec Y Y
- Baud gen per chan Y Y
+ x Baud gen per chan Y Y
DPLL clock recov Y Y
-- Additional features CMOS versions -----
- Status FIFO N Y
+ p Status FIFO N Y
Watchdog timer N Y
Fifo Fill status N Y
DMA frame status N Y
@@ -85,11 +85,11 @@ DONE (x) (p=partly) NMOS CMOS
/* Useful temporary debug printout format */
// printf("TAG %lld %s%s Data:%d\n", machine().firstcpu->total_cycles(), __PRETTY_FUNCTION__, m_owner->tag(), data);
-#define VERBOSE 2
+#define VERBOSE 0
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
-#define LOGR(x)
-#if VERBOSE == 0
+#define LOGR(x)
+#if VERBOSE > 1
#define logerror printf
#endif
@@ -137,24 +137,29 @@ machine_config_constructor duscc_device::device_mconfig_additions() const
//-------------------------------------------------
duscc_device::duscc_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),
+ device_z80daisy_interface(mconfig, *this),
+ m_chanA(*this, CHANA_TAG),
+ m_chanB(*this, CHANB_TAG),
#if 0
- m_rxca(0),
- m_txca(0),
- m_rxcb(0),
- m_txcb(0),
+ m_rxca(0),
+ m_txca(0),
+ m_rxcb(0),
+ m_txcb(0),
#endif
- m_out_txda_cb(*this),
- m_out_dtra_cb(*this),
- m_out_rtsa_cb(*this),
- m_out_synca_cb(*this),
- m_out_txdb_cb(*this),
- m_out_dtrb_cb(*this),
- m_out_rtsb_cb(*this),
- m_out_syncb_cb(*this),
- m_variant(variant)
+ m_out_txda_cb(*this),
+ m_out_dtra_cb(*this),
+ m_out_rtsa_cb(*this),
+ m_out_synca_cb(*this),
+ m_out_txdb_cb(*this),
+ m_out_dtrb_cb(*this),
+ m_out_rtsb_cb(*this),
+ m_out_syncb_cb(*this),
+ m_out_int_cb(*this),
+ m_variant(variant),
+ m_gsr(0),
+ m_ivr(0),
+ m_ivrm(0),
+ m_icr(0)
{
for (auto & elem : m_int_state)
elem = 0;
@@ -162,17 +167,23 @@ duscc_device::duscc_device(const machine_config &mconfig, device_type type, cons
duscc_device::duscc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, DUSCC, "DUSCC", tag, owner, clock, "duscc", __FILE__),
- m_chanA(*this, CHANA_TAG),
- m_chanB(*this, CHANB_TAG),
- m_out_txda_cb(*this),
- m_out_dtra_cb(*this),
- m_out_rtsa_cb(*this),
- m_out_synca_cb(*this),
- m_out_txdb_cb(*this),
- m_out_dtrb_cb(*this),
- m_out_rtsb_cb(*this),
- m_out_syncb_cb(*this),
- m_variant(TYPE_DUSCC)
+ device_z80daisy_interface(mconfig, *this),
+ m_chanA(*this, CHANA_TAG),
+ m_chanB(*this, CHANB_TAG),
+ m_out_txda_cb(*this),
+ m_out_dtra_cb(*this),
+ m_out_rtsa_cb(*this),
+ m_out_synca_cb(*this),
+ m_out_txdb_cb(*this),
+ m_out_dtrb_cb(*this),
+ m_out_rtsb_cb(*this),
+ m_out_syncb_cb(*this),
+ m_out_int_cb(*this),
+ m_variant(TYPE_DUSCC),
+ m_gsr(0),
+ m_ivr(0),
+ m_ivrm(0),
+ m_icr(0)
{
for (auto & elem : m_int_state)
elem = 0;
@@ -202,14 +213,21 @@ void duscc_device::device_start()
m_out_dtra_cb.resolve_safe();
m_out_rtsa_cb.resolve_safe();
m_out_synca_cb.resolve_safe();
+
m_out_txdb_cb.resolve_safe();
m_out_dtrb_cb.resolve_safe();
m_out_rtsb_cb.resolve_safe();
m_out_syncb_cb.resolve_safe();
+ m_out_int_cb.resolve_safe();
- // state saving
- //save_item(NAME(m_int_state));
+ // state saving - stuff with runtime values
+ save_item(NAME(m_int_state));
+ save_item(NAME(m_gsr));
+ save_item(NAME(m_icr));
+ save_item(NAME(m_ivr));
+ save_item(NAME(m_ivrm));
+ // TODO: add serial device and daisy device save states
LOG((" - DUSCC variant %02x\n", m_variant));
}
@@ -224,16 +242,138 @@ void duscc_device::device_reset()
m_chanA->reset();
m_chanB->reset();
+ m_gsr = 0x00;
+ m_icr = 0x00;
+ m_ivr = 0x0f;
+ m_ivrm = 0x00;
+}
+
+/*
+ * Interrupt Control
+ A single interrupt output (IRON) is provided which is activated upon the occurrence of any of the following conditions:
+ - Channel A external or CIT special condition
+ - Channel B external or CIT special condition
+ - Channel A RxlTx error or special condition
+ - Channel B RxlTx error or special condition
+ - Channel A TxRDY
+ - Channel B TxRDY
+ - Channel A RxRDY
+ - Channel B RxRDY
+ Each of the above conditions occupies a bit in the General Status Register (GSR). If ICR[2] is set, the eight conditions are encoded
+ into three bits which are inserted into bits [2:0] or [4:2] of the interrupt vector register. This forms the content of the IVRM during
+ an interrupt acknowledge cycle. Unmodified and modified vectors can read directly through specified registers. Two of the conditions
+ are the inclusive OR of several other maskable conditions:
+ - Extemal or CIT special condition: Delta DCD, Delta CTS or CIT zero count (ICTSR[6:4j).
+ - Rxrrx error or special condition: any condition in the Receiver Status Register (RSR[7:0J) or a transmitter or DPLL condition in
+ the Transmitter and Receiver Status Register (TRSR[7:3J).
+ The TxRDY and RxRDY conditions are defined by OMR[4] and OMR[3], respectively. Also associated with the interrupt system are
+ the Interrupt Enable Register (IER), one bit in the Countermmer Control Register (CTCR), and the Interrupt Control Register (lCR).
+
+ The IER is programmed to enable specified conditions or groups of conditions to cause an interrupt by asserting the corresponding bit.
+ A negated bit prevents an interrupt from occurring when the condition is active and hence masks the interrupt. In addition to the
+ IER, CTCR[?] could be programmed to enable or disable an interrupt upon the CfT zero count condition. The interrupt priorities
+ within a channel are fixed. Priority between channels is controlled by ICR[7:6]. Reier to Table 8 and ICR[7:6].
+
+ The ICR contains the master interrupt enables for each channel (ICR[I] andICR[OJ) which must be set if the corresponding channel
+ is to cause an interrupt. The CPU vector mode is specified by ICR[5:4] which selects either vectored or non-vectored operation. If
+ vectored mode is selected, the content of the IVR or IVRM is placed on the data bus when lACK is activated. If ICR[2] is set, the content
+ of IVRM is output which contains the content of IVR and the encoded status of the interrupting condition.
+ Upon receiving an interrupt acknowledge, the DUSCC locks its current interrupt status until the end of the acknowledge cycle.
+ If it has an active interrupt pending, it responds with the appropriate vector and then asserts DTACKN. If it does not have an interrupt, it
+ propagates the acknowledge through its X2/1DCN output if this function is programmed in PCRA[7]; otherwise, the IACKN is
+ ignored. Locking the interrupt status at the leading edge of IACKN prevents a device at a High position in the interrupt daisy chain from
+ responding to an lACK issued for a lower priority device while the acknowledge is being propagated to that device.*/
+//-------------------------------------------------
+// z80daisy_irq_state - get interrupt status
+//-------------------------------------------------
+
+int duscc_device::z80daisy_irq_state()
+{
+ int state = 0;
+
+ LOG(("%s %s A:[%02x][%02x][%02x][%02x] B:[%02x][%02x][%02x][%02x] ",tag(), FUNCNAME,
+ 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 (auto & elem : m_int_state)
+ {
+ // if we're servicing a request, don't indicate more interrupts
+ if (elem & Z80_DAISY_IEO)
+ {
+ state |= Z80_DAISY_IEO;
+ break;
+ }
+ state |= elem;
+ }
+
+ LOG(("Interrupt State %02x\n", state));
+
+ return state;
+}
+
+
+//-------------------------------------------------
+// z80daisy_irq_ack - interrupt acknowledge
+//-------------------------------------------------
+
+int duscc_device::z80daisy_irq_ack()
+{
+
+ LOG(("%s %s()\n",tag(), FUNCNAME));
+
+ // loop over all interrupt sources
+ for (auto & elem : m_int_state)
+ {
+ // find the first channel with an interrupt requested
+ if (elem & Z80_DAISY_INT)
+ {
+ // clear interrupt, switch to the IEO state, and update the IRQs
+ elem = Z80_DAISY_IEO;
+ check_interrupts();
+
+ return m_ivrm;
+ }
+ }
+
+ return m_ivrm;
}
+
//-------------------------------------------------
-// check_interrupts -
+// z80daisy_irq_reti - return from interrupt
//-------------------------------------------------
+void duscc_device::z80daisy_irq_reti()
+{
+
+ LOG(("%s %s \n",tag(), FUNCNAME));
+
+ // loop over all interrupt sources
+ for (auto & elem : m_int_state)
+ {
+ // find the first channel with an IEO pending
+ if (elem & Z80_DAISY_IEO)
+ {
+ // clear the IEO state and update the IRQs
+ elem &= ~Z80_DAISY_IEO;
+ check_interrupts();
+ return;
+ }
+
+ }
+}
+
void duscc_device::check_interrupts()
{
- LOG(("%s %s - not implemented\n",tag(), FUNCNAME));
- // m_out_int_cb(state);
+ LOG(("%s %s()\n",tag(), FUNCNAME));
+ int state = (z80daisy_irq_state() & Z80_DAISY_INT) ? ASSERT_LINE : CLEAR_LINE;
+
+ // "If no interrupt is pending, an H'FF' is output when reading the IVRM."
+ if (state == 0)
+ m_ivrm = 0xff;
+
+ m_out_int_cb(state);
}
@@ -244,7 +384,7 @@ void duscc_device::check_interrupts()
void duscc_device::reset_interrupts()
{
LOG(("%s %s - not implemented \n",tag(), FUNCNAME));
-#if 0
+
// reset internal interrupt sources
for (auto & elem : m_int_state)
{
@@ -253,22 +393,93 @@ void duscc_device::reset_interrupts()
// check external interrupt sources
check_interrupts();
-#endif
}
UINT8 duscc_device::modify_vector(UINT8 vec, int i, UINT8 src)
{
+ /*
+ Interrupt Vector Modification
+ V2 V1 V0 if ICR[2] = 1 and ICR[3] = 0
+ V4 V3 V2 if ICR[2] = 1 and ICR[3] = 1
+--------------------------------------------------
+ 0 0 0 Ch A Receiver ready
+ 0 0 1 Ch A Transmitter ready
+ 0 1 0 Ch A Rx/Tx Status
+ 0 1 1 Ch A external or C/T status
+ 1 0 0 Ch B Receiver ready
+ 1 0 1 Ch B Transmitter ready
+ 1 1 0 Ch B Rx/Tx Status
+ 1 1 1 Ch B external or C/T status
+--------------------------------------------------
+ */
LOG(("%s %s - not implemented\n",tag(), FUNCNAME));
+ //TODO: Prevent modification if no vector has been programmed, even if it is the default vector.
+ if ((m_icr & REG_ICR_VEC_MOD) != 0) // Affect vector?
+ {
+ // Modify vector according to "Vector Include Status" bit (REG_ICR_V2V4_MOD)
+ if ((m_icr & REG_ICR_V2V4_MOD) != 0)
+ { // Affect V2-V4
+ vec &= 0x07 << 3;
+ vec |= src << 3;
+ }
+ else // Affect V0-V2
+ {
+ vec &= 0x07 << 0;
+ vec |= src << 0;
+ }
+ }
return vec;
}
-//-------------------------------------------------
-// trigger_interrupt -
+/* Interrupt Control and Status Registers
+ This group of registers define mechanisms for communications between the DUSCC and the processor and contain the device status
+ information. Four registers, available for each channel, and four common device registers comprise this group which consists of
+ the following:
+ 1. Interrupt Enable Register (IERA/B).
+ 2. Receiver Status Register (RSRA/B).
+ 3. Transmitter and Receiver Status Register (TRSRA/B).
+ 4. Input and Coutnermmer Status Register (ICTSRA/B).
+ 5. interrupt Vector Register (IVR) and Modified Interrupt Vector Register (IVRM).
+ 6. Interrupt control register (lCR).
+ 7. General status register (GSR)
+*/
+
+//-----------------------------------------------------------------------
+// trigger_interrupt - called when a potential interrupt condition occurs and will only issue an interrupt if the DUSCC is
+// programmed to do so.
//-------------------------------------------------
void duscc_device::trigger_interrupt(int index, int state)
{
- LOG(("%s %s - not implemented\n",tag(), FUNCNAME));
+ UINT8 vector = m_ivr;
+ UINT8 source = 0;
+ int priority_level = 0;
+
+ LOG(("%s %s:%c %02x \n",FUNCNAME, tag(), 'A' + index, state));
+
+ /* The Interrup Controll Register (ICR) bits, must be set for the correspondning channel */
+ if ((m_icr & (index == CHANNEL_A ? REG_ICR_CHA : REG_ICR_CHB)) == 0)
+ {
+ LOG(("The Interrupt Control Register [%02x] bit for this channel is not set, blocking attempt to interrupt\n", m_icr));
+ return;
+ }
+
+ // Modify priority level
+ switch (m_icr & REG_ICR_PRIO_MASK)
+ {
+ case REG_ICR_PRIO_AHI: priority_level = state + (index == CHANNEL_A ? 0 : 4); break;
+ case REG_ICR_PRIO_BHI: priority_level = state + (index == CHANNEL_A ? 4 : 0); break;
+ case REG_ICR_PRIO_AINT: priority_level = state * 2 + (index == CHANNEL_A ? 0 : 1); break;
+ case REG_ICR_PRIO_BINT: priority_level = state * 2 + (index == CHANNEL_A ? 1 : 0); break;
+ default: logerror("Programming error, please report/fix\n"); // Will not happen
+ }
+
+ // Vector modification requested?
+ source = state + (index == CHANNEL_A ? 0 : 4); // bit in interrupt queue register of a certain priotiry level
+ m_ivrm = modify_vector(vector, index, source);
+
+ // trigger interrupt
+ m_int_state[priority_level] |= Z80_DAISY_INT;
}
READ8_MEMBER( duscc_device::read )
@@ -313,22 +524,21 @@ duscc_channel::duscc_channel(const machine_config &mconfig, const char *tag, dev
LOG(("%s\n",FUNCNAME));
// Reset all registers
- m_cmr1 = m_cmr2 = m_s1r = m_s2r = m_tpr = m_ttr = m_rpr = m_rtr
- = m_ctprh = m_ctprl = m_ctcr = m_omr = m_cth = m_ctl = m_pcr
- = m_ccr = m_rsr = m_trsr = m_ictsr = m_gsr = m_ier /* = m_rea */
- = m_cid = m_ivr = m_icr = /*m_sea =*/ m_ivrm = m_mrr = m_ier1
+ m_cmr1 = m_cmr2 = m_s1r = m_s2r = m_tpr = m_ttr = m_rpr = m_rtr
+ = /* m_ctprh = m_ctprl = */ m_ctpr = m_ctcr = m_omr
+ = /* m_cth = m_ctl = */ m_ct = m_pcr
+ = m_ccr = m_rsr = m_trsr = m_ictsr /*= m_gsr*/ = m_ier /*= m_rea*/
+ = m_cid = /*m_ivr = m_icr = m_sea = m_ivrm = */ m_mrr = m_ier1
= m_ier2 = m_ier3 = m_trcr = m_rflr = m_ftlr = m_trmsr = m_telr = 0;
- for (int i = 0; i < sizeof(m_rx_data_fifo); i++)
- {
- m_rx_data_fifo[i] = 0;
- m_rx_error_fifo[i] = 0;
- }
- for (int i = 0; i < sizeof(m_tx_data_fifo); i++)
- {
- m_tx_data_fifo[i] = 0;
- m_tx_error_fifo[i] = 0;
- }
+ for (auto & elem : m_rx_data_fifo)
+ elem = 0;
+ for (auto & elem : m_rx_error_fifo)
+ elem = 0;
+ for (auto & elem : m_tx_data_fifo)
+ elem = 0;
+ for (auto & elem : m_tx_error_fifo)
+ elem = 0;
}
//-------------------------------------------------
@@ -358,12 +568,14 @@ void duscc_channel::device_start()
save_item(NAME(m_ttr));
save_item(NAME(m_rpr));
save_item(NAME(m_rtr));
- save_item(NAME(m_ctprh));
- save_item(NAME(m_ctprl));
+ // save_item(NAME(m_ctprh));
+ // save_item(NAME(m_ctprl));
+ save_item(NAME(m_ctpr));
save_item(NAME(m_ctcr));
save_item(NAME(m_omr));
- save_item(NAME(m_cth));
- save_item(NAME(m_ctl));
+ // save_item(NAME(m_cth));
+ // save_item(NAME(m_ctl));
+ save_item(NAME(m_ct));
save_item(NAME(m_pcr));
save_item(NAME(m_ccr));
save_item(NAME(m_txfifo));
@@ -371,14 +583,14 @@ void duscc_channel::device_start()
save_item(NAME(m_rsr));
save_item(NAME(m_trsr));
save_item(NAME(m_ictsr));
- save_item(NAME(m_gsr)); // TODO: Move this to the device instead, it is a global register
+ // save_item(NAME(m_gsr)); // Moved this to the device instead, it is a global register
save_item(NAME(m_ier));
- // save_item(NAME(m_rea));
+ // save_item(NAME(m_rea));
save_item(NAME(m_cid));
- save_item(NAME(m_ivr));
- save_item(NAME(m_icr));
- // save_item(NAME(m_sea));
- save_item(NAME(m_ivrm));
+ // save_item(NAME(m_ivr)); // Moved this to the device instead, it is a global register
+ // save_item(NAME(m_icr)); // Moved this to the device instead, it is a global register
+ // save_item(NAME(m_sea));
+ // save_item(NAME(m_ivrm)); // Moved this to the device instead, it is a global register
save_item(NAME(m_mrr));
save_item(NAME(m_ier1));
save_item(NAME(m_ier2));
@@ -405,7 +617,7 @@ void duscc_channel::device_start()
save_item(NAME(m_rts));
save_item(NAME(m_sync));
- device_serial_interface::register_save_state(machine().save(), this);
+ // device_serial_interface::register_save_state(machine().save(), this);
}
@@ -422,37 +634,37 @@ void duscc_channel::device_reset()
transmit_register_reset();
// Soft/Channel Reset values according to DUSCC users guide
- m_cmr1 =0x00;
- m_cmr2 =0x00;
- m_s1r =0x00;
- m_s2r =0x00;
- m_tpr =0x00;
- m_ttr =0x00;
- m_rpr =0x00;
- m_rtr =0x00;
- m_ctcr =0x00;
- m_omr =0x00;
- m_pcr =0x00;
- m_ccr =0x00;
- m_rsr =0x00;
- m_trsr =0x00;
- m_ictsr =0x00;
- m_gsr =0x00;
- m_ier =0x00;
- // m_rea =0x00;
- m_ivr =0x0f;
- m_icr =0x00;
- // m_sea =0x00;
- m_ivrm =0x00;
- m_mrr =0x00; // TODO: Need a read after reset to enable CMOS features
- m_ier1 =0x00;
- m_ier2 =0x00;
- m_ier3 =0x00;
- m_trcr =0x00;
- m_rflr =0x00;
- m_ftlr =0x33;
- m_trmsr =0x00;
- m_telr =0x10;
+ m_cmr1 =0x00;
+ m_cmr2 =0x00;
+ m_s1r =0x00;
+ m_s2r =0x00;
+ m_tpr =0x00;
+ m_ttr =0x00;
+ m_rpr =0x00;
+ m_rtr =0x00;
+ m_ctcr =0x00;
+ m_omr =0x00;
+ m_pcr =0x00;
+ m_ccr =0x00;
+ m_rsr =0x00;
+ m_trsr =0x00;
+ m_ictsr =0x00;
+ // m_gsr =0x00;
+ m_ier =0x00;
+ // m_rea =0x00;
+ // m_ivr =0x0f;
+ // m_icr =0x00;
+ // m_sea =0x00;
+ // m_ivrm =0x00;
+ m_mrr =0x00; // TODO: Need a read after reset to enable CMOS features
+ m_ier1 =0x00;
+ m_ier2 =0x00;
+ m_ier3 =0x00;
+ m_trcr =0x00;
+ m_rflr =0x00;
+ m_ftlr =0x33;
+ m_trmsr =0x00;
+ m_telr =0x10;
// reset external lines TODO: check relation to control bits and reset
set_rts(1);
@@ -518,10 +730,10 @@ void duscc_channel::tra_complete()
if (m_omr & REG_OMR_TXRDY_ACTIVATED)// Wait until FIFO empty before ready for more data?
{
if (m_tx_fifo_wp == m_tx_fifo_rp) // So is Tx FIFO empty?
- m_gsr |= (m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
+ m_uart->m_gsr |= (m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
}
else // Always ready for more!
- m_gsr |= (m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
+ m_uart->m_gsr |= (m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
}
}
@@ -681,21 +893,106 @@ int duscc_channel::get_tx_word_length()
return bits;
}
-UINT8 duscc_channel::do_dusccreg_cmr1_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_cmr2_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_s1r_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_s2r_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_tpr_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_ttr_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_rpr_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_rtr_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_ctprh_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_ctprl_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_ctcr_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_omr_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_cth_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_ctl_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_pcr_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
+// register read methods - see correspondning write method for details on each register
+
+UINT8 duscc_channel::do_dusccreg_cmr1_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_cmr1));
+ return m_cmr1;
+}
+
+UINT8 duscc_channel::do_dusccreg_cmr2_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_cmr2));
+ return m_cmr2;
+}
+
+UINT8 duscc_channel::do_dusccreg_s1r_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_s1r));
+ return m_s1r;
+}
+
+UINT8 duscc_channel::do_dusccreg_s2r_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_s2r));
+ return m_s2r;
+}
+
+UINT8 duscc_channel::do_dusccreg_tpr_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_tpr));
+ return m_tpr;
+}
+
+UINT8 duscc_channel::do_dusccreg_ttr_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_ttr));
+ return m_ttr;
+}
+
+UINT8 duscc_channel::do_dusccreg_rpr_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_rpr));
+ return m_rpr;
+}
+
+UINT8 duscc_channel::do_dusccreg_rtr_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_rtr));
+ return m_rtr;
+}
+
+UINT8 duscc_channel::do_dusccreg_ctprh_r()
+{
+ UINT8 ret = ((m_ctpr >> 8) & 0xff );
+ LOG(("%s(%02x)\n", FUNCNAME, ret));
+
+ // return m_ctprh;
+ return ret;
+}
+
+UINT8 duscc_channel::do_dusccreg_ctprl_r()
+{
+ UINT8 ret = (m_ctpr & 0xff);
+ LOG(("%s(%02x)\n", FUNCNAME, ret));
+ // return m_ctprl;
+ return ret;
+}
+
+UINT8 duscc_channel::do_dusccreg_ctcr_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_ctcr));
+ return m_ctcr;
+}
+
+UINT8 duscc_channel::do_dusccreg_omr_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_omr));
+ return m_omr;
+}
+
+UINT8 duscc_channel::do_dusccreg_cth_r()
+{
+ UINT8 ret = ((m_ct >> 8) & 0xff );
+ LOG(("%s(%02x)\n", FUNCNAME, ret));
+
+ return ret;
+}
+
+UINT8 duscc_channel::do_dusccreg_ctl_r()
+{
+ UINT8 ret = (m_ct & 0xff);
+ LOG(("%s(%02x)\n", FUNCNAME, ret));
+ // return m_ctl;
+ return ret;
+}
+
+UINT8 duscc_channel::do_dusccreg_pcr_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_pcr));
+ return m_pcr;
+}
/* Commands to the DUSCC are entered through the channel command register.A read of this
register returns the last invoked command (with bits 4 and 5 set to 1). */
@@ -716,7 +1013,9 @@ UINT8 duscc_channel::do_dusccreg_rxfifo_r()
if (m_rx_fifo_rp != m_rx_fifo_wp)
{
data = m_rx_data_fifo[m_rx_fifo_rp];
+ m_rx_error_fifo[m_rx_fifo_rp] = 0; // Loose the old errors
m_rx_fifo_rp_step();
+ m_rsr |= (m_rx_error_fifo[m_rx_fifo_rp] & (REG_RSR_CHAR_COMPARE | REG_RSR_FRAMING_ERROR | REG_RSR_PARITY_ERROR)); // Get new errors
LOG((" - RX reading out data:%02x '%c'\n", data, isalnum(data) ? data : ' '));
}
else
@@ -728,12 +1027,22 @@ UINT8 duscc_channel::do_dusccreg_rxfifo_r()
return (UINT8) data;
}
-UINT8 duscc_channel::do_dusccreg_rsr_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_trsr_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_ictsr_r()
+UINT8 duscc_channel::do_dusccreg_rsr_r()
+{
+ LOG(("%s: %02x\n", FUNCNAME, m_rsr));
+ return (UINT8) m_rsr;
+}
+
+UINT8 duscc_channel::do_dusccreg_trsr_r()
{
- logerror("register access method %s is not implemented yet\n", FUNCNAME);
- return (UINT8) m_ictsr;
+ LOG(("%s(%02x)\n", FUNCNAME, m_trsr));
+ return m_trsr;
+}
+
+UINT8 duscc_channel::do_dusccreg_ictsr_r()
+{
+ logerror("%s is not implemented yet\n", FUNCNAME);
+ return (UINT8) m_ictsr;
}
/* General Status Register (GSR)
@@ -758,12 +1067,16 @@ UINT8 duscc_channel::do_dusccreg_ictsr_r()
receiver' command is invoked.
*/
UINT8 duscc_channel::do_dusccreg_gsr_r()
-{
- LOGR(("%s <- %02x\n", FUNCNAME, m_gsr));
- return (UINT8) m_gsr;
+{
+ LOGR(("%s <- %02x\n", FUNCNAME, m_uart->m_gsr));
+ return (UINT8) m_uart->m_gsr;
}
-UINT8 duscc_channel::do_dusccreg_ier_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
+UINT8 duscc_channel::do_dusccreg_ier_r()
+{
+ LOGR(("%s <- %02x\n", FUNCNAME, m_uart->m_ier));
+ return (UINT8) 0;
+}
UINT8 duscc_channel::do_dusccreg_cid_r()
{
@@ -782,23 +1095,91 @@ UINT8 duscc_channel::do_dusccreg_cid_r()
return m_cid;
}
-UINT8 duscc_channel::do_dusccreg_ivr_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_icr_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_ivrm_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_mrr_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_ier1_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_ier2_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_ier3_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_trcr_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_rflr_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_ftlr_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_trmsr_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-UINT8 duscc_channel::do_dusccreg_telr_r(){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return (UINT8) 0; }
-
- // write register handlers
-/* CMR1 register
- [7:6] Data Encoding - These bits select the data encoding for the received and transmitted data:
- 00 If the DPLL is set to NRZI mode (see DPLL commands), it selects positive logic (1 = high, 0 = low).
+UINT8 duscc_channel::do_dusccreg_ivr_ivrm_r()
+{
+ LOG(("%s", FUNCNAME));
+ if ( m_index == duscc_device::CHANNEL_A )
+ {
+ LOG(("(%02x)\n", m_uart->m_ivr));
+ return m_uart->m_ivr; // Interrupt vector as programmed
+ }
+ else
+ {
+ LOG((" - IVRM\n"));
+ return m_uart->m_ivrm; // Modified Interrupt vector
+ }
+}
+
+UINT8 duscc_channel::do_dusccreg_icr_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_uart->m_icr));
+ return m_uart->m_icr;
+}
+
+UINT8 duscc_channel::do_dusccreg_mrr_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_mrr));
+ return m_mrr;
+}
+
+UINT8 duscc_channel::do_dusccreg_ier1_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_ier1));
+ return m_ier1;
+}
+
+UINT8 duscc_channel::do_dusccreg_ier2_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_ier2));
+ return m_ier2;
+}
+
+UINT8 duscc_channel::do_dusccreg_ier3_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_ier3));
+ return m_ier3;
+}
+
+UINT8 duscc_channel::do_dusccreg_trcr_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_trcr));
+ return m_trcr;
+}
+
+UINT8 duscc_channel::do_dusccreg_rflr_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_rflr));
+ return m_rflr;
+}
+
+UINT8 duscc_channel::do_dusccreg_ftlr_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_ftlr));
+ return m_ftlr;
+}
+
+UINT8 duscc_channel::do_dusccreg_trmsr_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_trmsr));
+ return m_trmsr;
+}
+
+UINT8 duscc_channel::do_dusccreg_telr_r()
+{
+ LOG(("%s(%02x)\n", FUNCNAME, m_telr));
+ return m_telr;
+}
+
+// write register handlers
+
+/* Channel Mode Configuration and Pin Description Registers
+ There are five registers in this group for each channel. The bit format for each of these registers is contained in Table 2. The
+ primary function of these registers is to define configuration of the channels and the function of the programmable pins. A channel
+ cannot be dynamically reconfigured. Do not write to CMRI or CMR2 if the receiver or transmitter is enabled.
+ */
+/* CMR1 register -
+ [7:6] Data Encoding - These bits select the data encoding for the received and transmitted data:
+ 00 If the DPLL is set to NRZI mode (see DPLL commands), it selects positive logic (1 = high, 0 = low).
If the DPLL is set to FM mode (see DPLL commands), Manchester (bi-phase level) encoding is selected.
01 NRZI. Non-return-to-zero inverted.
10 FMO. Bi-phase space.
@@ -933,8 +1314,38 @@ void duscc_channel::do_dusccreg_cmr2_w(UINT8 data)
return;
}
-void duscc_channel::do_dusccreg_s1r_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
-void duscc_channel::do_dusccreg_s2r_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
+/* SYN1/Secondary Address 1 Register (S1RA, S1RB)
+ [7:O} Character Compare
+ - In ASYNC mode this register holds a 5 to 8-bit long bit pattern which is ocmpared with received
+ characters. if a match occurs, the character compare status bit (RSR[7]) is set. This field is ignored if the receivEII is in a break
+ condition.
+ - In COP modes, this register contains the 5- to 8-bit SYNl bit pattern, right justified. Parity bit need not be included in the value
+ placed in the register even is parity is specmad in CMR1[4:3J. However, a character received with parity error, when parity is
+ specified, will not match. In ASYNC, or COP modes, if parity is specified, then any unused bits in this register must be programmed
+ to zeros. In BOP secondary mode it contains the address used to compare the first received address octet. The register is not used in
+ BOP primary mode or secondary modes where address comparisons are not made, such as when extended addressing is specified.
+ TODO: Add check in receive_data and set status bits accordingly
+*/
+void duscc_channel::do_dusccreg_s1r_w(UINT8 data)
+{
+ LOG(("%s(%02x) - not supported yet\n", FUNCNAME, data));
+ m_s1r = data;
+ return;
+}
+
+/* SYN2ISecondary Address 2 Register (S2RA, S2RB)
+ [7:0] - This register is not used in ASYNC, COP single SYN, BOP primary modes, BOP secondary modes with single address field:
+ and BOP secondary modes where address comparisons are not made, such as when extended addressing is specified.
+ In COP dual SYN modes,it contains the 5- to 8-b~'SYN2 bit pattern, right justWiad, Par~ bit need not be included in the value placed in
+ the register even if parity is specified in CMR1[4:3J. However, a character received w~ parity error, when parity is specified, will not
+ match. If parity Is specified, then any unused bits in this register must be programmed to zeros. In BOP secondary mode using two
+ address octets, it contains the partial address used to compare the second received address octet.*/
+void duscc_channel::do_dusccreg_s2r_w(UINT8 data)
+{
+ LOG(("%s(%02x) - not supported yet\n", FUNCNAME, data));
+ m_s2r = data;
+ return;
+}
/* Transmitter Parameter Register (TPRA, TPRB)
SYNC mode
@@ -1025,7 +1436,7 @@ void duscc_channel::do_dusccreg_ttr_w(UINT8 data)
m_ttr = data;
LOG(("- External source: %s\n", (m_ttr & REG_TTR_EXT) ? "TRxC" : "RTxC"));
LOG(("- Transmit Clock: "));
-#if VERBOSE > 0
+
switch(m_ttr & REG_TTR_TXCLK_MASK)
{
case REG_TTR_TXCLK_1XEXT: LOG(("1x External - not implemented\n")); break;
@@ -1041,7 +1452,6 @@ void duscc_channel::do_dusccreg_ttr_w(UINT8 data)
case REG_TTR_TXCLK_32X_OWN: LOG(("32x own channel C/T - not implemented\n")); break;
default: LOG(("Wrong programming\n")); break; // Should never happen
}
-#endif
LOG(("- BRG Tx rate %u assuming a 14.7456MHz CLK crystal\n", get_baudrate(m_ttr & REG_TTR_BRG_RATE_MASK)));
update_serial();
@@ -1163,7 +1573,6 @@ void duscc_channel::do_dusccreg_rtr_w(UINT8 data)
LOG(("- External source: %s\n", (m_rtr & REG_RTR_EXT) ? "TRxC" : "RTxC"));
LOG(("- Receiver Clock: "));
-#if VERBOSE > 0
switch(m_rtr & REG_RTR_RXCLK_MASK)
{
case REG_RTR_RXCLK_1XEXT: LOG(("1x External - not implemented\n")); break;
@@ -1179,7 +1588,6 @@ void duscc_channel::do_dusccreg_rtr_w(UINT8 data)
case REG_RTR_RXCLK_DPLL_32X_CT: LOG(("DPLL, source = 32X C/T - not implemented\n")); break;
default: LOG(("Wrong programming\n")); break; // Should never happen
}
-#endif
LOG(("- BRG Rx rate %u assuming a 14.7456MHz CLK crystal\n", get_baudrate(m_rtr & REG_RTR_BRG_RATE_MASK)));
update_serial();
@@ -1187,9 +1595,30 @@ void duscc_channel::do_dusccreg_rtr_w(UINT8 data)
return;
}
-void duscc_channel::do_dusccreg_ctprh_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
-void duscc_channel::do_dusccreg_ctprl_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
-void duscc_channel::do_dusccreg_ctcr_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
+void duscc_channel::do_dusccreg_ctprh_w(UINT8 data)
+{
+ LOG(("%s(%02x) - not supported yet\n", FUNCNAME, data));
+ // m_ctprh = data;
+ m_ctpr &= ~0x0000ff00;
+ m_ctpr |= ((data << 8) & 0x0000ff00);
+ return;
+}
+
+void duscc_channel::do_dusccreg_ctprl_w(UINT8 data)
+{
+ LOG(("%s(%02x) - not supported yet\n", FUNCNAME, data));
+ // m_ctprl = data;
+ m_ctpr &= ~0x000000ff;
+ m_ctpr |= (data & 0x000000ff);
+ return;
+}
+
+void duscc_channel::do_dusccreg_ctcr_w(UINT8 data)
+{
+ LOG(("%s(%02x) - not supported yet\n", FUNCNAME, data));
+ m_ctcr = data;
+ return;
+}
/* Output and Miscellaneous Register (OMRA, OMRB)
[7:5] Transmitted Residual Character Length - In BOP modes, this field determines the number of bits transmitted for the last
@@ -1281,7 +1710,6 @@ void duscc_channel::do_dusccreg_pcr_w(UINT8 data)
LOG(("- The GP02/RTS pin is %s\n", m_pcr & REG_PCR_GP02_RTS ? "RTS" : "GP02"));
LOG(("- The SYNOUT/RTS pin is %s\n", m_pcr & REG_PCR_SYNOUT_RTS ? "RTS" : "SYNOUT"));
-#if VERBOSE > 0
LOG(("- The RTxC pin is "));
switch ( m_pcr & REG_PCR_RTXC_MASK )
{
@@ -1305,9 +1733,7 @@ void duscc_channel::do_dusccreg_pcr_w(UINT8 data)
default: LOG(("Wrong programming\n")); break; // Should never happen
}
-#endif
-
- return;
+ return;
}
/*
@@ -1333,14 +1759,14 @@ void duscc_channel::do_dusccreg_ccr_w(UINT8 data)
set_tra_rate(0);
m_tx_fifo_wp = m_tx_fifo_rp = 0;
m_trsr &= 0x0f;
- m_gsr &= ~(m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
+ m_uart->m_gsr &= ~(m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
break;
/* Enable transmitter. Enables transmitter operation, conditioned by the state of
the CTS ENABLE Tx bit, TPR[2]. Has no effect if invoked when the transmitter has
previously been enabled.*/
- case REG_CCR_ENABLE_TX: LOG(("- Enable Tx\n"));
- m_gsr |= (m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
+ case REG_CCR_ENABLE_TX: LOG(("- Enable Tx\n"));
+ m_uart->m_gsr |= (m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
m_tra = 1;
set_tra_rate(m_brg_tx_rate);
break;
@@ -1353,7 +1779,7 @@ void duscc_channel::do_dusccreg_ccr_w(UINT8 data)
case REG_CCR_DISABLE_TX: LOG(("- Disable Tx\n"));
set_tra_rate(0);
m_tra = 0;
- m_gsr &= ~(m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
+ m_uart->m_gsr &= ~(m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
break;
// RECEIVER COMMANDS
@@ -1367,7 +1793,7 @@ void duscc_channel::do_dusccreg_ccr_w(UINT8 data)
m_rx_fifo_wp = m_rx_fifo_rp = 0;
m_trsr &= 0xf0;
m_rsr = 0;
- m_gsr &= ~(m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_RXREADY : REG_GSR_CHAN_B_RXREADY);
+ m_uart->m_gsr &= ~(m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_RXREADY : REG_GSR_CHAN_B_RXREADY);
break;
/* Enable receiver. Causes receiver operation to begin, conditioned by the state of the DCD
@@ -1376,14 +1802,13 @@ void duscc_channel::do_dusccreg_ccr_w(UINT8 data)
case REG_CCR_ENABLE_RX: LOG(("- Enable Rx\n"));
m_rcv = 1;
set_rcv_rate(m_brg_rx_rate);
- //m_gsr |= (m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_RXREADY : REG_GSR_CHAN_B_RXREADY);
break;
/* Disable receiver. Terminates operation of the receiver. Any character currently being assembled
will be lost. Does not affect FIFO or any status.*/
case REG_CCR_DISABLE_RX: LOG(("- Disable Rx\n"));
m_rcv = 0;
- m_gsr &= ~(m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_RXREADY : REG_GSR_CHAN_B_RXREADY);
+ m_uart->m_gsr &= ~(m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_RXREADY : REG_GSR_CHAN_B_RXREADY);
break;
default: LOG((" - command %02x not implemented yet\n", data));
}
@@ -1404,8 +1829,6 @@ void duscc_channel::do_dusccreg_txfifo_w(UINT8 data)
else // ..there is still room
{
m_tx_data_fifo[m_tx_fifo_wp++] = data;
- //m_rsr &= ~REG_RSR_OVERRUN_ERROR;
- //m_gsr |= (m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_RXREADY : REG_GSR_CHAN_B_RXREADY);
if (m_tx_fifo_wp >= m_tx_fifo_sz)
{
m_tx_fifo_wp = 0;
@@ -1425,35 +1848,122 @@ void duscc_channel::do_dusccreg_txfifo_w(UINT8 data)
// check if Tx FIFO is FULL and set TxREADY accordingly
if (m_tx_fifo_wp + 1 == m_tx_fifo_rp || ( (m_tx_fifo_wp + 1 == m_tx_fifo_sz) && (m_tx_fifo_rp == 0) ))
{
- m_gsr &= ~(m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
+ m_uart->m_gsr &= ~(m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
}
else
{
- m_gsr |= (m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
+ m_uart->m_gsr |= (m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
}
return;
}
-void duscc_channel::do_dusccreg_rsr_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
-void duscc_channel::do_dusccreg_trsr_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
-void duscc_channel::do_dusccreg_ictsr_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
-void duscc_channel::do_dusccreg_gsr_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
-void duscc_channel::do_dusccreg_ier_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
-void duscc_channel::do_dusccreg_ivr_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
-void duscc_channel::do_dusccreg_icr_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
+/* Receiver Status Register (RSRA, RSRB)
+ This register informs the CPU of receiver status. Bits indicated as 'not used';n a particular mode will read as zero. The logical OR of
+ these bits is presented in GSR[2] or GSR[6] (ORed with the bits of TRSR) for Channels A and B, respectively. Unless otherwise
+ indicated, asserted status bits are reset only be performing a write operation to the status register with the bits to be reset being ones in
+ the accompanying data word, or when the RESETN input is asserted, or when a 'reset receiver' command is issued.
+ Certain status bits are specified as being FIFOed. This means that they occupy positions in a status FIFO that correspond to the data
+ FIFO. As the data is brought to the top of the FIFO (the position read when the RxFIFO is read), the FIFOed status bits are logically
+ ORed with the previous contents of the corresponding bits in the status register. This permits the user to obtain status either
+ character by character or on a block basis. For character by character status, the SR bits should be read and then cleared
+ before reading the character data from RxFIFO. For block status, the status register is initially cleared and then read after the
+ message is received. Asserted status bits can be programmed to generate an interrupt (see Interrupt Enable Register).*/
+void duscc_channel::do_dusccreg_rsr_w(UINT8 data)
+{
+ LOG(("%s: %02x\n", FUNCNAME, data));
+ m_rsr &= ~data; // Clear only bits which are 1:s
+ return;
+}
+
+void duscc_channel::do_dusccreg_trsr_w(UINT8 data)
+{
+ LOG(("%s: %02x - not supported yet\n", FUNCNAME, data));
+ m_trsr = data;
+ return;
+}
-/* Short cutted non complex features */
-//void duscc_channel::do_dusccreg_rea_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
-//void duscc_channel::do_dusccreg_sea_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
+void duscc_channel::do_dusccreg_ictsr_w(UINT8 data)
+{
+ LOG(("%s: %02x - not supported yet\n", FUNCNAME, data));
+ m_ictsr = data;
+ return;
+}
-void duscc_channel::do_dusccreg_mrr_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
-void duscc_channel::do_dusccreg_ier1_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
-void duscc_channel::do_dusccreg_ier2_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
-void duscc_channel::do_dusccreg_ier3_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
-void duscc_channel::do_dusccreg_trcr_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
-void duscc_channel::do_dusccreg_ftlr_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
-void duscc_channel::do_dusccreg_trmsr_w(UINT8 data){ logerror("register access method %s is not implemented yet\n", FUNCNAME); return; }
+/* This register provides a 'quick look' at the overall status of both channels of the DUSCC. A write to this register with ls at the
+ corresponding bit pOSitions causes TxRDY (bits 5 and 1) and/or RxRDY (bits 4 and 0) to be reset. The other status bits can be reset
+ only by resetting the individual status bits that they point to.
+ [7] Channel 8 External or Coutnerrrimer Status - This bit indicates that one of the following status bits is asserted: ICTSRB[6:4].
+ [6] Channel B Receiver or Transmitter Status - This bit indicates that one of the following status bits is asserted: RSRB[7:0], TRSRB[7:3].
+ [5] Channel 8 Transmitter Ready - The assertion of this bit indicates that one or more characters may be loaded into the Channel B
+ transmitter FIFO to be serialized by the transmit shift register. See description of OMR[4j. This bit can be asserted only
+ when the transmitter is enabled. Reselling the transmitter negates TxRDY.
+ [4] Channel 8 Receiver Ready - The assertion of this bit indicates that one or more characters are available in the Channel B receiver
+ FIFO to be read by the CPU. See deSCription of OMR[3]. RxRDY is initially reset (negated) by a chip reset or when a 'reset Channel B
+ receiver' command is invoked.
+ [3] Channel A External or Countermmer Status - This bit indicates that one of the following status bits is asserted: ICTSRA[6:4].
+ [2] Channel A Receiver or Transmitter Status - This bit indicates that one of the following status bits is asserted: RSRA(7:0], TRSRA(7:3].
+ [1) Channel A Transmitter Ready - The assertion of this bit indicates that one or more characters may be loaded into the Channel A
+ transmitter FIFO to be serialized by the transmit shift register. See description of OMR[4]. This bit can be asserted only
+ when the transmitter is enabled. Resetting the transmitter negates TxRDY.
+ [0) Channel A Receiver Ready - The assertion of this bit indicates that one or more characters are available in the Channel A receiver
+ FIFO to be read by the CPU. See description of OMR[3]. RxRDY is initially reset (negated) by a chip reset or when a 'reset Channel A
+ receiver' command is invoked.*/
+void duscc_channel::do_dusccreg_gsr_w(UINT8 data)
+{
+ LOG(("%s(%02x)\n", FUNCNAME, data));
+ m_uart->m_gsr &= (data & REG_GSR_XXREADY_MASK); // Reset only XXREADY bits, the rest needs to be reset by the source
+ return; // TODO: Check of the XXREADY source bits should be reset too
+}
+
+/* Interrupt Enable Register (IERA, IERB)
+ This register controls whether the assertion of bits in the channel's status registers causes an interrupt to be generated. An additional
+ condition for an interrupt to be generated is that the channel's master interrupt enabled bit, ICR[O] or ICR[1], be asserted.*/
+void duscc_channel::do_dusccreg_ier_w(UINT8 data)
+{
+ m_ier = data;
+ LOG(("%s(%02x)\n", FUNCNAME, data));
+ m_uart->check_interrupts();
+ return;
+}
+
+void duscc_channel::do_dusccreg_ivr_w(UINT8 data)
+{
+ m_uart->m_ivr = data;
+ LOG(("%s(%02x)\n", FUNCNAME, data));
+ return;
+}
+
+void duscc_channel::do_dusccreg_icr_w(UINT8 data)
+{
+ m_uart->m_icr = data;
+ LOG(("%s(%02x)\n", FUNCNAME, data));
+ return;
+}
+
+void duscc_channel::do_dusccreg_sea_rea_w(UINT8 data)
+{
+ LOG(("%s(%02x)\n", FUNCNAME, data));
+ if ( m_uart->m_variant != SET_CMOS )
+ {
+ logerror("Attempt set/clear the CDUSCC A7 bit on an NDUSCC\n");
+ m_a7 = 0; // refuse access to CDUSCC registers on an NDUSCC
+ }
+ else
+ {
+ m_a7 = (m_index == duscc_device::CHANNEL_A ? 0x40 : 0); // Set or Reset depending in channel
+ }
+
+ return;
+}
+
+void duscc_channel::do_dusccreg_mrr_w(UINT8 data){ logerror("%s is not implemented yet\n", FUNCNAME); return; }
+void duscc_channel::do_dusccreg_ier1_w(UINT8 data){ logerror("%s is not implemented yet\n", FUNCNAME); return; }
+void duscc_channel::do_dusccreg_ier2_w(UINT8 data){ logerror("%s is not implemented yet\n", FUNCNAME); return; }
+void duscc_channel::do_dusccreg_ier3_w(UINT8 data){ logerror("%s is not implemented yet\n", FUNCNAME); return; }
+void duscc_channel::do_dusccreg_trcr_w(UINT8 data){ logerror("%s is not implemented yet\n", FUNCNAME); return; }
+void duscc_channel::do_dusccreg_ftlr_w(UINT8 data){ logerror("%s is not implemented yet\n", FUNCNAME); return; }
+void duscc_channel::do_dusccreg_trmsr_w(UINT8 data){ logerror("%s is not implemented yet\n", FUNCNAME); return; }
//-------------------------------------------------
// control_read - read register
@@ -1461,17 +1971,40 @@ void duscc_channel::do_dusccreg_trmsr_w(UINT8 data){ logerror("register access m
UINT8 duscc_channel::read(offs_t &offset)
{
UINT8 data = 0;
- int reg = offset | m_a7;
+ int reg = (offset | m_a7) & ~0x20; // Add extended rgisters and remove the channel B bit from offset
switch (reg)
{
- case REG_CID: data = do_dusccreg_cid_r(); break;
- case REG_CCR: data = do_dusccreg_ccr_r(); break;
- case REG_RXFIFO_0: data = do_dusccreg_rxfifo_r(); break;
- case REG_RXFIFO_1: data = do_dusccreg_rxfifo_r(); break;
- case REG_RXFIFO_2: data = do_dusccreg_rxfifo_r(); break;
- case REG_RXFIFO_3: data = do_dusccreg_rxfifo_r(); break;
- case REG_GSR: data = do_dusccreg_gsr_r(); break;
+ case REG_CMR1: data = do_dusccreg_cmr1_r(); break;
+ case REG_CMR2: data = do_dusccreg_cmr2_r(); break;
+ case REG_S1R: data = do_dusccreg_s1r_r(); break;
+ case REG_S2R: data = do_dusccreg_s2r_r(); break;
+ case REG_TPR: data = do_dusccreg_tpr_r(); break;
+ case REG_TTR: data = do_dusccreg_ttr_r(); break;
+ case REG_RPR: data = do_dusccreg_rpr_r(); break;
+ case REG_RTR: data = do_dusccreg_rtr_r(); break;
+ case REG_CTPRH: data = do_dusccreg_ctprh_r(); break;
+ case REG_CTPRL: data = do_dusccreg_ctprl_r(); break;
+ case REG_CTCR: data = do_dusccreg_ctcr_r(); break;
+ case REG_OMR: data = do_dusccreg_omr_r(); break;
+ case REG_CTH: data = do_dusccreg_cth_r(); break;
+ case REG_CTL: data = do_dusccreg_ctl_r(); break;
+ case REG_PCR: data = do_dusccreg_pcr_r(); break;
+ case REG_CCR: data = do_dusccreg_ccr_r(); break;
+ case REG_RXFIFO_0: data = do_dusccreg_rxfifo_r(); break;
+ case REG_RXFIFO_1: data = do_dusccreg_rxfifo_r(); break;
+ case REG_RXFIFO_2: data = do_dusccreg_rxfifo_r(); break;
+ case REG_RXFIFO_3: data = do_dusccreg_rxfifo_r(); break;
+ case REG_RSR: data = do_dusccreg_rsr_r(); break;
+ case REG_TRSR: data = do_dusccreg_trsr_r(); break;
+ case REG_ICTSR: data = do_dusccreg_ictsr_r(); break;
+ case REG_GSR: data = do_dusccreg_gsr_r(); break;
+ case REG_IER: data = do_dusccreg_ier_r(); break;
+ // case REG_IVR: data = do_dusccreg_ivr_r(); break; // Chan A = IVR, B = IVRM
+ case REG_IVRM: data = do_dusccreg_ivr_ivrm_r(); break;
+ case REG_ICR: data = do_dusccreg_icr_r(); break;
+ // CDUSCC Extended registers - requires A7 to be set through REG_SEA
+ case REG_CID: data = do_dusccreg_cid_r(); break;
default:
logerror(" \"%s\" %s: %c : Unsupported RRx register:%02x\n", m_owner->tag(), FUNCNAME, 'A' + m_index, reg);
}
@@ -1485,61 +2018,51 @@ UINT8 duscc_channel::read(offs_t &offset)
//-------------------------------------------------
void duscc_channel::write(UINT8 data, offs_t &offset)
-//WRITE8_MEMBER( duscc_channel::write)
{
- int reg = offset | m_a7;
+ int reg = (offset | m_a7) & ~0x20; // Add extended rgisters and remove the channel B bit from offset
+ LOG((" * %c Reg %02x <- %02x \n", 'A' + m_index, reg, data));
LOG(("\"%s\" %s: %c : Register write '%02x' -> [%02x]", m_owner->tag(), FUNCNAME, 'A' + m_index, data, reg ));
switch (reg)
{
- case REG_SEA: /*Also REG_REA depending on which channel is written to */
- if ( m_uart->m_variant != SET_CMOS )
- {
- logerror("Attempt set/clear the CDUSCC A7 bit on an NDUSCC\n");
- m_a7 = 0;
- }
- else
- m_a7 = (m_index == duscc_device::CHANNEL_A ? 0x40 : 0);
- break;
- case REG_CMR1: do_dusccreg_cmr1_w(data); break;
- case REG_CMR2: do_dusccreg_cmr2_w(data); break;
- case REG_S1R: LOG(("REG_S1R \n")); break;
- case REG_S2R: LOG(("REG_S2R \n")); break;
- case REG_TPR: do_dusccreg_tpr_w(data); break;
- case REG_TTR: do_dusccreg_ttr_w(data); break;
- case REG_RPR: do_dusccreg_rpr_w(data); break;
- case REG_RTR: do_dusccreg_rtr_w(data); break;
- case REG_CTPRH: LOG(("REG_CTPRH\n")); break;
- case REG_CTPRL: LOG(("REG_CTPRL\n")); break;
- case REG_CTCR: LOG(("REG_CTCR\n")); break;
- case REG_OMR: do_dusccreg_omr_w(data); break;
- case REG_CTH: LOG(("REG_CTH \n")); break;
- case REG_CTL: LOG(("REG_CTL \n")); break;
- case REG_PCR: do_dusccreg_pcr_w(data); break;
- case REG_CCR: do_dusccreg_ccr_w(data); break;
- case REG_TXFIFO_0: do_dusccreg_txfifo_w(data); break;
- case REG_TXFIFO_1: do_dusccreg_txfifo_w(data); break;
- case REG_TXFIFO_2: do_dusccreg_txfifo_w(data); break;
- case REG_TXFIFO_3: do_dusccreg_txfifo_w(data); break;
- case REG_RSR: LOG(("REG_RSR \n")); break;
- case REG_TRSR: LOG(("REG_TRSR\n")); break;
- case REG_ICTSR: LOG(("REG_ICTSR\n")); break;
- case REG_GSR: LOG(("REG_GSR \n")); break;
- case REG_IER: LOG(("REG_IER \n")); break;
-// case REG_CID: LOG(("REG_CID \n")); break;
- case REG_IVR: LOG(("REG_IVR \n")); break;
- case REG_ICR: LOG(("REG_ICR \n")); break;
-// case REG_SEA: LOG(("REG_SEA \n")); break;
-// case REG_IVRM: LOG(("REG_IVRM\n")); break;
-// case REG_MRR: LOG(("REG_MRR \n")); break;
- case REG_IER1: LOG(("REG_IER1\n")); break;
- case REG_IER2: LOG(("REG_IER2\n")); break;
- case REG_IER3: LOG(("REG_IER3\n")); break;
- case REG_TRCR: LOG(("REG_TRCR\n")); break;
- case REG_RFLR: LOG(("REG_RFLR\n")); break;
- case REG_FTLR: LOG(("REG_FTLR\n")); break;
- case REG_TRMSR: LOG(("REG_TRMSR\n")); break;
- case REG_TELR: LOG(("REG_TELR\n")); break;
+ case REG_CMR1: do_dusccreg_cmr1_w(data); break;
+ case REG_CMR2: do_dusccreg_cmr2_w(data); break;
+ case REG_S1R: do_dusccreg_s1r_w(data); break;
+ case REG_S2R: do_dusccreg_s2r_w(data); break;
+ case REG_TPR: do_dusccreg_tpr_w(data); break;
+ case REG_TTR: do_dusccreg_ttr_w(data); break;
+ case REG_RPR: do_dusccreg_rpr_w(data); break;
+ case REG_RTR: do_dusccreg_rtr_w(data); break;
+ case REG_CTPRH: do_dusccreg_ctprh_w(data); break;
+ case REG_CTPRL: do_dusccreg_ctprl_w(data); break;
+ case REG_CTCR: do_dusccreg_ctcr_w(data); break;
+ case REG_OMR: do_dusccreg_omr_w(data); break;
+// case REG_CTH: LOG(("REG_CTH \n")); break; // Read only register
+// case REG_CTL: LOG(("REG_CTL \n")); break; // Read only register
+ case REG_PCR: do_dusccreg_pcr_w(data); break;
+ case REG_CCR: do_dusccreg_ccr_w(data); break;
+ case REG_TXFIFO_0: do_dusccreg_txfifo_w(data); break;
+ case REG_TXFIFO_1: do_dusccreg_txfifo_w(data); break;
+ case REG_TXFIFO_2: do_dusccreg_txfifo_w(data); break;
+ case REG_TXFIFO_3: do_dusccreg_txfifo_w(data); break;
+ case REG_RSR: do_dusccreg_rsr_w(data); break;
+ case REG_TRSR: do_dusccreg_trsr_w(data); break;
+ case REG_ICTSR: do_dusccreg_ictsr_w(data); break;
+ case REG_GSR: do_dusccreg_gsr_w(data); break;
+ case REG_IER: do_dusccreg_ier_w(data); break;
+ case REG_IVR: do_dusccreg_ivr_w(data); break;
+ case REG_ICR: do_dusccreg_icr_w(data); break;
+// CDUSCC Extended registers - requires A7 to be set through REG_SEA
+// case REG_MRR: LOG(("REG_MRR \n")); break;
+ case REG_SEA: do_dusccreg_sea_rea_w(data); break; /* Also supports REG_REA depending on which channel is written to */
+ case REG_IER1: LOG(("REG_IER1\n")); break;
+ case REG_IER2: LOG(("REG_IER2\n")); break;
+ case REG_IER3: LOG(("REG_IER3\n")); break;
+ case REG_TRCR: LOG(("REG_TRCR\n")); break;
+ case REG_RFLR: LOG(("REG_RFLR\n")); break;
+ case REG_FTLR: LOG(("REG_FTLR\n")); break;
+ case REG_TRMSR: LOG(("REG_TRMSR\n")); break;
+ case REG_TELR: LOG(("REG_TELR\n")); break;
default:
logerror(" \"%s\" %s: %c : Unsupported WRx register:%02x(%02x)\n", m_owner->tag(), FUNCNAME, 'A' + m_index, reg, data);
@@ -1571,8 +2094,7 @@ void duscc_channel::m_rx_fifo_rp_step()
if (m_rx_fifo_rp == m_rx_fifo_wp)
{
// no more characters available in the FIFO
- // m_rr0 &= ~ RR0_RX_CHAR_AVAILABLE;
- m_gsr &= ~(m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_RXREADY : REG_GSR_CHAN_B_RXREADY);
+ m_uart->m_gsr &= ~(m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_RXREADY : REG_GSR_CHAN_B_RXREADY);
}
}
@@ -1598,20 +2120,23 @@ void duscc_channel::receive_data(UINT8 data)
{
// receive overrun error detected
m_rsr |= REG_RSR_OVERRUN_ERROR;
+ // m_rx_error_fifo[m_rx_fifo_wp] &= ~REG_RSR_OVERRUN_ERROR; // The overrun error is NOT fifoed obviously...
logerror("Receive_data() Error %02x\n", m_rsr);
}
else
{
m_rx_data_fifo[m_rx_fifo_wp] = data;
- m_rx_error_fifo[m_rx_fifo_wp] &= ~REG_RSR_OVERRUN_ERROR;
m_rsr &= ~REG_RSR_OVERRUN_ERROR;
- m_gsr |= (m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_RXREADY : REG_GSR_CHAN_B_RXREADY);
+ m_uart->m_gsr |= (m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_RXREADY : REG_GSR_CHAN_B_RXREADY);
m_rx_fifo_wp++;
if (m_rx_fifo_wp >= m_rx_fifo_sz)
{
m_rx_fifo_wp = 0;
}
+
+ // if (m_eir & REG_IER_)
+
}
}
@@ -1638,7 +2163,7 @@ WRITE_LINE_MEMBER( duscc_channel::cts_w )
if (m_tpr & REG_TPR_CTS && m_tra)
{
- m_gsr |= (m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
+ m_uart->m_gsr |= (m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
}
// set clear to send
diff --git a/src/devices/machine/scnxx562.h b/src/devices/machine/scnxx562.h
index cec9d6a8fb3..636122aa665 100644
--- a/src/devices/machine/scnxx562.h
+++ b/src/devices/machine/scnxx562.h
@@ -40,6 +40,7 @@
#define __SCNXX562_H__
#include "emu.h"
+#include "cpu/z80/z80daisy.h"
//**************************************************************************
// DEVICE CONFIGURATION MACROS
@@ -110,7 +111,7 @@
class duscc_device;
class duscc_channel : public device_t,
- public device_serial_interface
+ public device_serial_interface
{
friend class duscc_device;
@@ -152,9 +153,8 @@ public:
UINT8 do_dusccreg_gsr_r();
UINT8 do_dusccreg_ier_r();
UINT8 do_dusccreg_cid_r();
- UINT8 do_dusccreg_ivr_r();
+ UINT8 do_dusccreg_ivr_ivrm_r();
UINT8 do_dusccreg_icr_r();
- UINT8 do_dusccreg_ivrm_r();
UINT8 do_dusccreg_mrr_r();
UINT8 do_dusccreg_ier1_r();
UINT8 do_dusccreg_ier2_r();
@@ -189,7 +189,7 @@ public:
// void do_dusccreg_rea_w(UINT8 data); // Short cutted non complex feature
void do_dusccreg_ivr_w(UINT8 data);
void do_dusccreg_icr_w(UINT8 data);
- // void do_dusccreg_sea_w(UINT8 data); // Short cutted non complex feature
+ void do_dusccreg_sea_rea_w(UINT8 data); // Short cutted non complex feature
void do_dusccreg_mrr_w(UINT8 data);
void do_dusccreg_ier1_w(UINT8 data);
void do_dusccreg_ier2_w(UINT8 data);
@@ -231,12 +231,14 @@ public:
UINT8 m_ttr;
UINT8 m_rpr;
UINT8 m_rtr;
- UINT8 m_ctprh;
- UINT8 m_ctprl;
+ // UINT8 m_ctprh;
+ // UINT8 m_ctprl;
+ unsigned int m_ctpr;
UINT8 m_ctcr;
UINT8 m_omr;
- UINT8 m_cth;
- UINT8 m_ctl;
+ // UINT8 m_cth;
+ // UINT8 m_ctl;
+ unsigned int m_ct;
UINT8 m_pcr;
UINT8 m_ccr;
UINT8 m_txfifo[4];
@@ -244,14 +246,14 @@ public:
UINT8 m_rsr;
UINT8 m_trsr;
UINT8 m_ictsr;
- UINT8 m_gsr;
+ // UINT8 m_gsr; // moved to the device since it is global
UINT8 m_ier;
// UINT8 m_rea;
UINT8 m_cid;
- UINT8 m_ivr;
- UINT8 m_icr;
- // UINT8 m_sea;
- UINT8 m_ivrm;
+ //UINT8 m_ivr;
+ //UINT8 m_icr;
+ // UINT8 m_sea;
+ //UINT8 m_ivrm;
UINT8 m_mrr;
UINT8 m_ier1;
UINT8 m_ier2;
@@ -263,12 +265,12 @@ public:
UINT8 m_telr;
protected:
- enum
+ enum // Needs to be 0-3 in unmodified prio level
{
- INT_TRANSMIT = 0,
- INT_EXTERNAL = 1,
- INT_RECEIVE = 2,
- INT_SPECIAL = 3
+ INT_RXREADY = 0,
+ INT_TXREADY = 1,
+ INT_RXTXSTAT = 2,
+ INT_EXTCTSTAT = 3
};
enum
@@ -387,7 +389,19 @@ protected:
enum
{
- REG_RSR_OVERRUN_ERROR = 0x20,
+ REG_RSR_CHAR_COMPARE = 0x80,
+ REG_RSR_OVERRUN_ERROR = 0x20,
+ REG_RSR_FRAMING_ERROR = 0x02,
+ REG_RSR_PARITY_ERROR = 0x01,
+ };
+
+ enum
+ {
+ REG_GSR_CHAN_A_RXREADY = 0x01,
+ REG_GSR_CHAN_B_RXREADY = 0x10,
+ REG_GSR_CHAN_A_TXREADY = 0x02,
+ REG_GSR_CHAN_B_TXREADY = 0x20,
+ REG_GSR_XXREADY_MASK = 0x33
};
enum
@@ -399,10 +413,14 @@ protected:
enum
{
- REG_GSR_CHAN_A_RXREADY = 0x01,
- REG_GSR_CHAN_B_RXREADY = 0x10,
- REG_GSR_CHAN_A_TXREADY = 0x02,
- REG_GSR_CHAN_B_TXREADY = 0x20,
+ REG_IER_DCD_CTS = 0x80,
+ REG_IER_TXRDY = 0x40,
+ REG_IER_TRSR73 = 0x20,
+ REG_IER_RXRDY = 0x10,
+ REG_IER_RSR76 = 0x08,
+ REG_IER_RSR54 = 0x04,
+ REG_IER_RSR32 = 0x02,
+ REG_IER_RSR10 = 0x01,
};
// Register offsets, stripped from channel bit 0x20 but including A7 bit
@@ -521,7 +539,6 @@ protected:
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
@@ -551,7 +568,7 @@ protected:
class duscc_device : public device_t
-// ,public device_z80daisy_interface
+ ,public device_z80daisy_interface
{
friend class duscc_channel;
@@ -611,6 +628,11 @@ protected:
virtual void device_reset() override;
virtual machine_config_constructor device_mconfig_additions() const override;
+ // device_z80daisy_interface overrides
+ virtual int z80daisy_irq_state() override;
+ virtual int z80daisy_irq_ack() override;
+ virtual void z80daisy_irq_reti() override;
+
// internal interrupt management
void check_interrupts();
void reset_interrupts();
@@ -658,9 +680,29 @@ protected:
devcb_write_line m_out_rtsb_cb;
devcb_write_line m_out_syncb_cb;
- int m_int_state[6]; // interrupt state
+ devcb_write_line m_out_int_cb;
+
+
+ int m_int_state[8]; // interrupt state
int m_variant;
+ UINT8 m_gsr;
+ UINT8 m_ivr;
+ UINT8 m_ivrm;
+ UINT8 m_icr;
+
+ enum
+ {
+ REG_ICR_CHB = 0x01,
+ REG_ICR_CHA = 0x02,
+ REG_ICR_VEC_MOD = 0x04,
+ REG_ICR_V2V4_MOD = 0x08,
+ REG_ICR_PRIO_MASK = 0xC0,
+ REG_ICR_PRIO_AHI = 0x00,
+ REG_ICR_PRIO_BHI = 0x40,
+ REG_ICR_PRIO_AINT = 0x80,
+ REG_ICR_PRIO_BINT = 0xC0,
+ };
};
// device type definition
diff --git a/src/mame/drivers/fcisio.cpp b/src/mame/drivers/fcisio.cpp
new file mode 100644
index 00000000000..4e33d41c8a8
--- /dev/null
+++ b/src/mame/drivers/fcisio.cpp
@@ -0,0 +1,309 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+/***************************************************************************
+ *
+ * 10/06/2016
+ * Force SYS68K ISIO-1/2 driver - This driver will be converted into a slot device once the VME bus driver exists.
+ * The ISIO board is a VME slave board that reads command and returns results through dual ported RAM to the VME bus.
+ *
+ * ISIO-1: page 385 http://bitsavers.informatik.uni-stuttgart.de/pdf/forceComputers/1988_Force_VMEbus_Products.pdf
+ * ISIO-2: page 395 http://bitsavers.informatik.uni-stuttgart.de/pdf/forceComputers/1988_Force_VMEbus_Products.pdf
+ *
+ * Address Map - guessed/revenged no tech doc available
+ * ----------------------------------------------------------
+ * Address Range Description LOCAL
+ * ----------------------------------------------------------
+ * 00 0000 - 00 0007 Initialisation vectors from system EPROM
+ * 00 0008 - 01 FFFF Local SRAM
+ * E0 0000 - E0 01FF DUSCC0
+ * E2 0000 - E0 01FF DUSCC0
+ * E4 0000 - E0 01FF DUSCC0
+ * E6 0000 - E0 01FF DUSCC0
+ * E8 0000 - E8 0DFF PI/T
+ * f0 0000 - F7 0000 EPROMs
+ * ----------------------------------------------------------
+ * Address Range Description LOCAL
+ * ----------------------------------------------------------
+ *
+ * Interrupt sources
+ * ----------------------------------------------------------
+ * Description Device Lvl IRQ VME board
+ * /Board Vector Address
+ * ----------------------------------------------------------
+ * On board Sources
+ * ----------------------------------------------------------
+ *
+ * TODO:
+ * - add PIT and DUSCC interrupts
+ * - add port mapping to self test jumper
+ * - add VME bus driver
+ * - write and map a 68153 device (accessable from VME side)
+ *
+ * Status: passes Self test and get stuck on no ticks for the scheduler.
+ * Schematics of the IRQ routing needed or a good trace of how the
+ * PIT and DUSCCs are hooked up to the BIM to get further.
+ *
+ ****************************************************************************/
+#define TODO "Driver for 68153 BIM device needed\n"
+
+#include "emu.h"
+#include "cpu/m68000/m68000.h"
+#include "machine/scnxx562.h"
+#include "machine/68230pit.h"
+#include "bus/rs232/rs232.h"
+#include "machine/clock.h"
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+#if VERBOSE == 2
+#define logerror printf
+#endif
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#define LLFORMAT "%I64%"
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#define LLFORMAT "%lld"
+#endif
+
+#define CPU_CLOCK XTAL_20MHz /* HCJ */
+#define DUSCC_CLOCK XTAL_14_7456MHz /* HCJ */
+
+class fcisio1_state : public driver_device
+{
+public:
+fcisio1_state(const machine_config &mconfig, device_type type, const char *tag) :
+ driver_device (mconfig, type, tag),
+ m_maincpu (*this, "maincpu")
+ ,m_duscc0(*this, "duscc0")
+ ,m_duscc1(*this, "duscc1")
+ ,m_duscc2(*this, "duscc2")
+ ,m_duscc3(*this, "duscc3")
+ ,m_pit (*this, "pit")
+{
+}
+ DECLARE_READ16_MEMBER (bootvect_r);
+ DECLARE_READ8_MEMBER (config_rd);
+
+ /* Dummy driver routines */
+ DECLARE_READ8_MEMBER (not_implemented_r);
+ DECLARE_WRITE8_MEMBER (not_implemented_w);
+
+ virtual void machine_start () override;
+
+protected:
+
+private:
+ required_device<cpu_device> m_maincpu;
+ required_device<duscc68562_device> m_duscc0;
+ required_device<duscc68562_device> m_duscc1;
+ required_device<duscc68562_device> m_duscc2;
+ required_device<duscc68562_device> m_duscc3;
+
+ required_device<pit68230_device> m_pit;
+
+ // Pointer to System ROMs needed by bootvect_r
+ UINT16 *m_sysrom;
+};
+
+static ADDRESS_MAP_START (fcisio1_mem, AS_PROGRAM, 16, fcisio1_state)
+ ADDRESS_MAP_UNMAP_HIGH
+ AM_RANGE (0x000000, 0x000007) AM_ROM AM_READ (bootvect_r) /* Vectors mapped from System EPROM */
+ AM_RANGE (0x000000, 0x01ffff) AM_RAM /* SRAM */
+ AM_RANGE (0xe00000, 0xe001ff) AM_DEVREADWRITE8("duscc0", duscc68562_device, read, write, 0x00ff)
+ AM_RANGE (0xe20000, 0xe201ff) AM_DEVREADWRITE8("duscc1", duscc68562_device, read, write, 0x00ff)
+ AM_RANGE (0xe40000, 0xe401ff) AM_DEVREADWRITE8("duscc2", duscc68562_device, read, write, 0x00ff)
+ AM_RANGE (0xe60000, 0xe601ff) AM_DEVREADWRITE8("duscc3", duscc68562_device, read, write, 0x00ff)
+ AM_RANGE (0xe80000, 0xe80dff) AM_DEVREADWRITE8("pit", pit68230_device, read, write, 0x00ff)
+ AM_RANGE (0xf00000, 0xf7ffff) AM_ROM /* System EPROM Area 32Kb DEBUGGER supplied */
+// AM_RANGE (0xc40000, 0xc800ff) AM_READWRITE8 (not_implemented_r, not_implemented_w, 0xffff) /* Dummy mapping af address area to display message */
+ADDRESS_MAP_END
+
+/* Start it up */
+void fcisio1_state::machine_start ()
+{
+ LOG (("machine_start\n"));
+
+ /* Setup pointer to bootvector in ROM for bootvector handler bootvect_r */
+ m_sysrom = (UINT16*)(memregion ("maincpu")->base () + 0xf00000);
+}
+
+/* Boot vector handler, the PCB hardwires the first 8 bytes from 0x80000 to 0x0 */
+READ16_MEMBER (fcisio1_state::bootvect_r){
+ return m_sysrom [offset];
+}
+
+READ8_MEMBER (fcisio1_state::not_implemented_r){
+ static int been_here = 0;
+ if (!been_here++){
+ logerror(TODO);
+ printf(TODO);
+ }
+ return (UINT8) 0;
+}
+
+WRITE8_MEMBER (fcisio1_state::not_implemented_w){
+ static int been_here = 0;
+ if (!been_here++){
+ logerror(TODO);
+ printf(TODO);
+ }
+ return;
+}
+
+// TODO: Get a manual to understand the config options for real
+READ8_MEMBER (fcisio1_state::config_rd){
+ UINT8 ret = 0;
+ LOG(("%s\n", FUNCNAME));
+
+ // Port B bit #7, 0x80 Self test bit, choose either of these two lines
+ ret &= ~0x80; // 0 = selftest
+ // ret |= 0x80; // 1 = no selftest
+
+ return ret;
+}
+
+/* Input ports */
+static INPUT_PORTS_START (fcisio1)
+INPUT_PORTS_END
+
+static DEVICE_INPUT_DEFAULTS_START( fcisio_terminal )
+ DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_9600 )
+ DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_9600 )
+ DEVICE_INPUT_DEFAULTS( "RS232_STARTBITS", 0xff, RS232_STARTBITS_1 )
+ DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_8 )
+ DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_NONE )
+ DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_1 )
+DEVICE_INPUT_DEFAULTS_END
+
+/*
+ * Machine configuration
+ */
+static MACHINE_CONFIG_START (fcisio1, fcisio1_state)
+ /* basic machine hardware */
+ MCFG_CPU_ADD ("maincpu", M68010, CPU_CLOCK / 2)
+ MCFG_CPU_PROGRAM_MAP (fcisio1_mem)
+
+ MCFG_DUSCC68562_ADD("duscc0", DUSCC_CLOCK, 0, 0, 0, 0 )
+ MCFG_DUSCC_OUT_TXDA_CB(DEVWRITELINE("rs232trm", rs232_port_device, write_txd))
+ MCFG_DUSCC_OUT_DTRA_CB(DEVWRITELINE("rs232trm", rs232_port_device, write_dtr))
+ MCFG_DUSCC_OUT_RTSA_CB(DEVWRITELINE("rs232trm", rs232_port_device, write_rts))
+
+ MCFG_RS232_PORT_ADD ("rs232trm", default_rs232_devices, "terminal")
+ MCFG_RS232_RXD_HANDLER (DEVWRITELINE ("duscc0", duscc68562_device, rxa_w))
+ MCFG_RS232_CTS_HANDLER (DEVWRITELINE ("duscc0", duscc68562_device, ctsa_w))
+ MCFG_DEVICE_CARD_DEVICE_INPUT_DEFAULTS("terminal", fcisio_terminal)
+
+ MCFG_DUSCC68562_ADD("duscc1", DUSCC_CLOCK, 0, 0, 0, 0 )
+ MCFG_DUSCC68562_ADD("duscc2", DUSCC_CLOCK, 0, 0, 0, 0 )
+ MCFG_DUSCC68562_ADD("duscc3", DUSCC_CLOCK, 0, 0, 0, 0 )
+
+ MCFG_DEVICE_ADD ("pit", PIT68230, XTAL_20MHz / 2)
+ MCFG_PIT68230_PB_INPUT_CB(READ8(fcisio1_state, config_rd))
+MACHINE_CONFIG_END
+
+/* ROM definitions */
+ROM_START (fcisio1)
+ ROM_REGION (0x1000000, "maincpu", 0)
+
+/* ISIO ROM:s v2.1 information
+ * PIT setup sequence
+ * 00 -> REG_PGCR
+ * 18 -> REG_PSRR
+ * 0f -> Reg PADDR
+ * 0f -> REG_PBDDR
+ * fa -> REG_PACR
+ * 0f -> REG_PADDR
+ * fa -> REG_PBCR
+ * ff -> REG_PBDR
+ * 0f -> REG_PBDDR
+ * 10 -> REG_PGCR
+ * ff -> REG_PCDR
+ * 17 -> REG_PCDDR
+ * 40 -> Reg PIVR
+ * 00 -> REG_TCR - timer disabled, all C pins, use preload, CLK and prescaler are used
+ * a0 -> REG_TCR - timer disabled, The dual-function pin PC3/TOUT carries the TOUTfunction and is used as a timer interrupt request
+ * output. The timer interrupt is enabled ; thus, the pin is low when the timer ZDS status bit is one. The dual-function
+ * pin PC7/TIACK carries the TIACK function and is used as a timer interrupt acknowledge input.
+ * 00 -> Reg 0x12
+ * 00 -> REG_CPRH
+ * 09 -> REG_CPRM
+ * 00 -> REG_CPRL
+ * 00 -> Reg 0x16
+ * 00 -> Reg 0x17
+ * 09 -> Reg 0x18
+ * 00 -> Reg 0x19
+ * 1d -> Reg TIVR
+ * 0f <- REG_PBDR
+ * 0e -> REG_PBDR
+ * 0f <- REG_PBDR
+ * 0f <- REG_PBDR
+ * 0d -> REG_PDBR
+ * 0f <- REG_PBDR
+ * 0f <- REG_PBDR
+ * 0f <- REG_PBDR
+ * 0f <- REG_PBDR
+ * 0f <- REG_PBDR
+ * 0f <- REG_PBDR
+ * 0f <- REG_PBDR
+ * 0f <- REG_PBDR
+ * 0f <- REG_PBDR
+ * 0f -> REG_PBDR
+ * 0f <- REG_PBDR
+ * 0b -> REG_PBDR
+ * 0f <- REG_PBDR
+ * 0f <- REG_PBDR
+ * 0f -> REG_PBDR
+ * 0f <- REG_PBDR
+ * 0f -> REG_PBDR
+ * 0f <- REG_PBDR
+ * 00 <- REG_PCDR
+ * 00 -> REG_PCDR
+ * ------- repeated 16 times -------------------
+ * a1 -> REG_TCR - timer enabled, The dual-function pin PC3/TOUT carries the TOUTfunction and is used as a timer interrupt request
+ * output. The timer interrupt is enabled ; thus, the pin is low when the timer ZDS status bit is one. The dual-function
+ * pin PC7/TIACK carries the TIACK function and is used as a timer interrupt acknowledge input.
+ * ?? <- Reg 0x0c
+ * ---------------------------------------------
+ *
+ * DUSCC0 channel A setup sequence
+ * 0f 00 -> REG_CCR - Reset Tx
+ * 0f 40 -> REG_CCR - Reset Rx
+ * 00 07 -> REG_CMR1 - Async mode
+ * 01 38 -> REG_CMR2 - Normal polled or interrupt mode, no DMA
+ * 02 00 -> REG_S1R - SYN1, Secondary Address 1 Register, 0 = no sync
+ * 03 00 -> REG_S2R - SYN2, only used in COP dual Sync mode but alao 0 = no sync
+ * 04 7F -> REG_TPR - Tx 8 bits, CTS and RTS, 1 STOP bit
+ * 05 3d -> REG_TTR - Tx BRG 9600 (assuming a 14.7456 crystal)
+ * 06 1b -> REG_RPR - Rx RTS, 8 bits, no DCD, no parity
+ * 07 2d -> REG_RTR - Rx BRG 9600 (assuming a 14.7456 crystal)
+ * 0b e1 -> REG_OMR - RTS high, OUT1 = OUT2 = high, RxRdy asserted for each character,
+ * TxRdy asserted on threshold, Same Tx Residual Character Length as for REG_TPR
+ * 0a 00 -> REG_CTCR - Counter/Timer control register 00 = Zero Det Int: disabled, Zero Det Control: preset,
+ * Output Control: square, Prescaler: 1, Clock Source: RTxC pin
+ * 09 00 -> REG_CTPRL - Counter/Timer Prescaler Register Low = 0
+ * 08 00 -> REG_CTPRH - Counter/Timer Prescaler Register High = 0
+ * 0f 00 -> REG_CCR - Reset Tx
+ * 0f 02 -> REG_CCR - Enable Tx
+ * 0f 40 -> REG_CCR - Reset Rx
+ * 0f 42 -> REG_CCR - Enable Rx
+ * 0f 02 -> REG_CCR - Enable Tx
+ * 0f 42 -> REG_CCR - Enable Rx
+ * 0e 27 -> REG_PCR - TRxC = RxCLK 1x, RTxC is input, RTS, GPO2, crystal oscillator connected to X2
+ * 1c 10 -> REG_IER - Interrupt Enable Register: RxRdy generates interrupt
+ * ... chan B setup with same data....
+ * ---- DUSCC0 to DUSCC3, setup with same data except at the end of each setup:
+ * 1e 1c -> DUSCC0 REG_IVR -
+ * 1e 1b -> DUSCC1 REG_IVR
+ * 1e 1a -> DUSCC2 REG_IVR
+ * 1e 19 -> DUSCC3 REG_IVR
+ */
+ ROM_LOAD16_BYTE ("ISIO-1_V2.1_L.BIN", 0xf00001, 0x4000, CRC (0d47d80f) SHA1 (541b55966f464c1cf686e36998650720950a2242))
+ ROM_LOAD16_BYTE ("ISIO-1_V2.1_U.BIN", 0xf00000, 0x4000, CRC (67986768) SHA1 (215f7ff90d9dbe2bea54510e3722fb33d4e54193))
+ROM_END
+
+/* Driver */
+/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
+COMP( 1986, fcisio1, 0, 0, fcisio1, fcisio1, driver_device, 0, "Force Computers Gmbh", "SYS68K/ISIO-1", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW | MACHINE_TYPE_COMPUTER )
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index 15700e88d6d..752eca75e4e 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -12083,6 +12083,9 @@ fccpu30 //
@source:fcscsi.cpp
fcscsi1 //
+@source:fcisio.cpp
+fcisio1 //
+
@source:fcombat.cpp
fcombat // (c) 1985 Jaleco