summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author R. Belmont <rb6502@users.noreply.github.com>2016-06-10 11:26:20 -0400
committer GitHub <noreply@github.com>2016-06-10 11:26:20 -0400
commitbd5c95e2ebea06affd010f9932b995c3156fc638 (patch)
treea6fc37d373ace5cef51a393c2499412ccfe1ca86 /src
parentee19937a2bfef729724fbf541bcce388937670f9 (diff)
parentf022874d400841f40155cc894a3ba869b04046ea (diff)
Merge pull request #939 from JoakimLarsson/fccpu30_2
Drivers for Force Computers CPU-30 and Signetics DUSCC milestone 1
Diffstat (limited to 'src')
-rw-r--r--src/devices/machine/68230pit.cpp663
-rw-r--r--src/devices/machine/68230pit.h159
-rw-r--r--src/devices/machine/scnxx562.cpp1793
-rw-r--r--src/devices/machine/scnxx562.h698
-rw-r--r--src/mame/drivers/fccpu30.cpp802
-rw-r--r--src/mame/drivers/force68k.cpp4
-rw-r--r--src/mame/mame.lst3
7 files changed, 3891 insertions, 231 deletions
diff --git a/src/devices/machine/68230pit.cpp b/src/devices/machine/68230pit.cpp
index 927ece2cb75..fe84888ffbf 100644
--- a/src/devices/machine/68230pit.cpp
+++ b/src/devices/machine/68230pit.cpp
@@ -9,13 +9,31 @@
*
* Todo
* - Add clock and timers
+* - Add double buffering for each submode
* - Add all missing registers
* - Add configuration
**********************************************************************/
#include "68230pit.h"
-#define LOG(x) /* x */
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+#define LOGR(x) LOG(x)
+#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 LOG(x) x
+//#define logerror printf
//**************************************************************************
// DEVICE TYPE DEFINITIONS
@@ -27,22 +45,70 @@ 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)
- , m_write_pa (*this)
- , m_write_h2 (*this), m_pgcr(0), m_psrr(0), m_paddr(0), m_pbddr(0), m_pcddr(0), m_pacr(0), m_pbcr(0), m_padr(0), m_pbdr(0), m_psr(0)
- {
+ : device_t (mconfig, type, name, tag, owner, clock, shortname, source),
+ device_execute_interface (mconfig, *this)
+ , m_icount (0)
+ , m_pa_out_cb(*this)
+ , m_pa_in_cb(*this)
+ , m_pb_out_cb(*this)
+ , m_pb_in_cb(*this)
+ , m_pc_out_cb(*this)
+ , m_pc_in_cb(*this)
+ , m_h1_out_cb (*this)
+ , m_h2_out_cb (*this)
+ , m_h3_out_cb (*this)
+ , m_h4_out_cb (*this)
+ , m_pgcr(0)
+ , m_psrr(0)
+ , m_paddr(0)
+ , m_pbddr(0)
+ , m_pcddr(0)
+ , m_pacr(0)
+ , m_pbcr(0)
+ , m_padr(0)
+ , m_pbdr(0)
+ , m_psr(0)
+ , m_tcr(0)
+ , m_cpr(0)
+ // , m_cprh(0)
+ // , m_cprm(0)
+ // , m_cprl(0)
+ , m_cntr(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)
- , m_write_pa (*this)
- , m_write_h2 (*this), m_pgcr(0), m_psrr(0), m_paddr(0), m_pbddr(0), m_pcddr(0), m_pacr(0), m_pbcr(0), m_padr(0), m_pbdr(0), m_psr(0)
- {
+ : device_t (mconfig, PIT68230, "PIT68230", tag, owner, clock, "pit68230", __FILE__),
+ device_execute_interface (mconfig, *this)
+ , m_icount (0)
+ , m_pa_out_cb (*this)
+ , m_pa_in_cb(*this)
+ , m_pb_out_cb(*this)
+ , m_pb_in_cb(*this)
+ , m_pc_out_cb(*this)
+ , m_pc_in_cb(*this)
+ , m_h1_out_cb(*this)
+ , m_h2_out_cb(*this)
+ , m_h3_out_cb(*this)
+ , m_h4_out_cb(*this)
+ , m_pgcr(0)
+ , m_psrr(0)
+ , m_paddr(0)
+ , m_pbddr(0)
+ , m_pcddr(0)
+ , m_pacr(0)
+ , m_pbcr(0)
+ , m_padr(0)
+ , m_pbdr(0)
+ , m_psr(0)
+ , m_tcr(0)
+ , m_cpr(0)
+ // , m_cprh(0)
+ // , m_cprm(0)
+ // , m_cprl(0)
+ , m_cntr(0)
+{
}
//-------------------------------------------------
@@ -50,12 +116,18 @@ pit68230_device::pit68230_device(const machine_config &mconfig, const char *tag,
//-------------------------------------------------
void pit68230_device::device_start ()
{
- LOG (logerror ("PIT68230 device started\n"));
- m_icountptr = &m_icount;
-
- // resolve callbacks
- m_write_pa.resolve_safe ();
- m_write_h2.resolve_safe ();
+ 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_h1_out_cb.resolve_safe();
+ m_h2_out_cb.resolve_safe();
+ m_h3_out_cb.resolve_safe();
+ m_h4_out_cb.resolve_safe();
}
//-------------------------------------------------
@@ -63,17 +135,18 @@ void pit68230_device::device_start ()
//-------------------------------------------------
void pit68230_device::device_reset ()
{
- LOG (logerror ("PIT68230 device reseted\n"));
- m_pgcr = 0;
- m_psrr = 0;
- m_paddr = 0;
- m_pbddr = 0;
- m_pcddr = 0;
- m_pacr = 0; m_write_h2 (m_pacr);
- m_pbcr = 0;
- m_padr = 0; m_write_pa ((offs_t)0, m_padr); // TODO: check PADDR
- m_pbdr = 0;
- m_psr = 0;
+ LOG(("%s %s \n",tag(), FUNCNAME));
+
+ m_pgcr = 0;
+ m_psrr = 0;
+ m_paddr = 0;
+ m_pbddr = 0;
+ m_pcddr = 0;
+ 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_psr = 0;
}
//-------------------------------------------------
@@ -85,16 +158,16 @@ void pit68230_device::device_timer (emu_timer &timer, device_timer_id id, INT32
void pit68230_device::h1_set (UINT8 state)
{
- LOG (logerror ("h1_set %d @ m_psr %2x => ", state, m_psr));
- if (state) m_psr |= 1; else m_psr &= ~1;
- LOG (logerror ("%02x %lld\n", m_psr, machine ().firstcpu->total_cycles ()));
+ LOG(("%s %s %d @ m_psr %2x => ",tag(), FUNCNAME, state, m_psr));
+ if (state) m_psr |= 1; else m_psr &= ~1;
+ LOG(("%02x %lld\n", m_psr, machine ().firstcpu->total_cycles ()));
}
void pit68230_device::portb_setbit (UINT8 bit, UINT8 state)
{
- LOG (logerror ("portb_setbit %d/%d @ m_pbdr %2x => ", bit, state, m_pbdr));
- if (state) m_pbdr |= (1 << bit); else m_pbdr &= ~(1 << bit);
- LOG (logerror ("%02x %lld\n", m_pbdr, machine ().firstcpu->total_cycles ()));
+ LOG(("%s %s %d/%d @ m_pbdr %2x => ", tag(), FUNCNAME, bit, state, m_pbdr));
+ if (state) m_pbdr |= (1 << bit); else m_pbdr &= ~(1 << bit);
+ LOG(("%02x %lld\n", m_pbdr, machine ().firstcpu->total_cycles ()));
}
//-------------------------------------------------
@@ -109,157 +182,373 @@ void pit68230_device::execute_run ()
} while (m_icount > 0);
}
-LOG (static INT32 ow_cnt = 0)
-LOG (static INT32 ow_data = 0)
-LOG (static INT32 ow_ofs = 0)
-
-WRITE8_MEMBER (pit68230_device::write){
- switch (offset) {
- case PIT_68230_PGCR:
- m_pgcr = data;
- break;
-
- case PIT_68230_PSRR:
- m_psrr = data;
- break;
-
- case PIT_68230_PADDR:
- m_paddr = data;
- break;
-
- case PIT_68230_PBDDR:
- m_pbddr = data;
- break;
-
- case PIT_68230_PCDDR:
- m_pcddr = data;
- break;
-
- case PIT_68230_PACR:
- m_pacr = data;
- // callbacks
- /*PACR in Mode 0
- * 5 43 H2 Control in Submode 00 && 01
- * ------------------------------------
- * 0 XX Input pin - edge-sensitive status input, H2S is set on an asserted edge.
- * 1 00 Output pin - negated, H2S is always clear.
- * 1 01 Output pin - asserted, H2S is always clear.
- * 1 10 Output pin - interlocked input handshake protocol, H2S is always clear.
- * 1 11 Output pin - pulsed input handshake protocol, H2S is always clear.
- *
- * 5 43 H2 Control in Submode 1x
- * ------------------------------------
- * 0 XX Input pin - edge-sensitive status input, H2S is set on an asserted edge.
- * 1 X0 Output pin - negated, H2S is always cleared.
- * 1 X1 Output pin - asserted, H2S is always cleared.
- */
- m_write_h2 (m_pacr & 0x08 ? 1 : 0); // TODO: Check mode and submodes
- break;
-
- case PIT_68230_PBCR:
- m_pbcr = data;
- break;
-
- case PIT_68230_PADR:
- m_padr = data;
- // callbacks
- m_write_pa ((offs_t)0, m_padr); // TODO: check PADDR
- break;
-
- case PIT_68230_PSR:
- m_psr = data;
- break;
-
- default:
- LOG (logerror ("unhandled register %02x", offset));
- }
-
- LOG (if (offset != ow_ofs || data != ow_data || ow_cnt >= 1000) {
- logerror ("\npit68230_device::write: previous identical operation performed %02x times\n", ow_cnt);
- ow_cnt = 0;
- ow_data = data;
- ow_ofs = offset;
- logerror ("pit68230_device::write: offset=%02x data=%02x %lld\n", ow_ofs, ow_data, machine ().firstcpu->total_cycles ());
- }
- else
- ow_cnt++; )
-}
-
-LOG (static INT32 or_cnt = 0)
-LOG (static INT32 or_data = 0)
-LOG (static INT32 or_ofs = 0)
+#if VERBOSE > 2
+static INT32 ow_cnt = 0;
+static INT32 ow_data = 0;
+static INT32 ow_ofs = 0;
+#endif
+
+void pit68230_device::wr_pitreg_pgcr(UINT8 data)
+{
+ LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
+ m_pgcr = data;
+}
+
+void pit68230_device::wr_pitreg_psrr(UINT8 data)
+{
+ LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
+ m_psrr = data;
+}
+
+void pit68230_device::wr_pitreg_paddr(UINT8 data)
+{
+ LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
+ m_paddr = data;
+}
+
+void pit68230_device::wr_pitreg_pbddr(UINT8 data)
+{
+ LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
+ m_pbddr = data;
+}
+
+void pit68230_device::wr_pitreg_pcddr(UINT8 data)
+{
+ LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
+ m_pcddr = data;
+}
+
+void pit68230_device::wr_pitreg_pacr(UINT8 data)
+{
+ LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
+ m_pacr = data;
+ // callbacks
+ /*PACR in Mode 0
+ * 5 43 H2 Control in Submode 00 && 01
+ * ------------------------------------
+ * 0 XX Input pin - edge-sensitive status input, H2S is set on an asserted edge.
+ * 1 00 Output pin - negated, H2S is always clear.
+ * 1 01 Output pin - asserted, H2S is always clear.
+ * 1 10 Output pin - interlocked input handshake protocol, H2S is always clear.
+ * 1 11 Output pin - pulsed input handshake protocol, H2S is always clear.
+ *
+ * 5 43 H2 Control in Submode 1x
+ * ------------------------------------
+ * 0 XX Input pin - edge-sensitive status input, H2S is set on an asserted edge.
+ * 1 X0 Output pin - negated, H2S is always cleared.
+ * 1 X1 Output pin - asserted, H2S is always cleared.
+ */
+ m_h2_out_cb (m_pacr & 0x08 ? 1 : 0); // TODO: Check mode and submodes
+}
+
+void pit68230_device::wr_pitreg_pbcr(UINT8 data)
+{
+ LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
+ m_pbcr = 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;
+ // callbacks
+ m_pa_out_cb ((offs_t)0, m_padr); // TODO: check PADDR
+}
+
+void pit68230_device::wr_pitreg_psr(UINT8 data)
+{
+ LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, m_owner->tag(), FUNCNAME, data));
+ m_psr = data;
+}
+
+/* The timer control register (TCR) determines all operations of the timer. Bits 7-5 configure the PC3/TOUT
+and PC7/TIACKpins for port C, square wave, vectored interrupt, or autovectored interrupt operation bit
+4 specifies whether the counter receives data from the counter preload register or continues counting when
+zero detect is reached ; bit 3 is unused and is read as zero bits 2 and 1 configure the path from the CLK
+and TINpins to the counter controller ; and bit 0 ena-bles the timer. This register is readable and writable
+at all times. All bits are cleared to zero when the RESET pin is asserted.
+
+TCR bits
+ 7 6 5 TOUT/TIACK Control
+----------------------------
+ 0 0 X The dual-function pins PC3/TOUT and PC7/TIACK carry the port C function.
+ 0 1 X The dual-function pinPC3/TOUT carries the TOUT function. In the run state it is used as a squarewave
+ output and is toggled on zero detect. The TOUT pin is high while in the halt state. The dualfunction
+ pin PC7/TIACK carries the PC7 function.
+ 1 0 0 The dual-function pin PC3/TOUT carries the TOUT function. In the run or halt state it is used as
+ a timer interrupt request output. The timer interrupt is disabled, thus, the pin is always three stated.
+ The dual-function pin PC7/TIACK carries the TIACK function ; however, since interrupt request is
+ negated, the PI/T produces no response (i.e., no data or DTACK) to an asserted TIACK. Refer to
+ 5.1.3. Timer Interrupt Acknowledge Cycles for details.
+ 1 0 1 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. Refer to the5.1.3. Timer InterruptAcknowledge Cycles fordetails. Thiscombination
+ supports vectored timer interrupts.
+ 1 1 0 The dual-function pin PC3/TOUT function. In the run or halt state it is used as a timer interrupt
+ request output. The timer interrupt is disabled ; thus, the pin is always three-stated. The dual-function
+ pin PC7/TIACK carries the PC7 function.
+ 1 1 1 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 PC7 function and autovectored interrupts are supported.
+
+TCR bit 4 - Zero Detect Control
+ 0 The counter is loaded fromthe counter preload register on the first clock to the 24-bit counter after
+ zero detect, then resumes counting.
+ 1 The counter rolls over on zero detect, then continues counting.
+
+TCR bit 3 - Unused and is always read as zero.
+
+TCR bits
+ 2 1 Clock Control
+ 0 0 The PC2/TIN input pin carries the port C function, and the CLK pin and prescaler are used. The
+ prescaler is decremented on the falling transition of the CLKpin ; the 24-bit counter is decremented,
+ rolls over, or is loaded from the counter preload registers when the prescaler rolls over from $OO
+ to $1F. The timer enable bit determines whether the timer is in the run or halt state.
+ 0 1 The PC2/TIN pin serves as a timer input, and the CLK pin and prescaler are used. The prescaler
+ is decremented on the falling transition of the CLK pin ; the 24-bit counter is decremented, rolls
+ over, or is loaded from the counter preload registers when the prescaler rolls over from $00 to $1F.
+ The timer is in the run state when the timer enable bit is one and the TIN pin is high ; otherwise,
+ the timer is in the halt state.
+ 1 0 The PC2/TIN pin serves as a timer input and the prescaler is used. The prescaler is decremented
+ following the rising transition of the TIN pin after being synchronized with the internal clock. The
+ 24-bit counter is decremented, rolls over, or is loaded from the counter preload registers when the
+ prescaler rolls over from $00 to $1F. The timer enable bit determines whether the timer is in the
+ run or halt state.
+ 1 1 The PC2/TIN pin serves as a timer input and the prescaler is not used. The 24-bit counter is decremented,
+ rolls over, or is loaded from the counter preload registers following the rising edge of
+ the TIN pin after being synchronized with the internal clock. The timer enable bit determines whether
+ the timer is in the run or halt state.
+TCR bit 0 - Timer Enable
+ 0 Disabled
+ 1 Enabled
+*/
+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"));
+ m_tcr = data;
+}
+
+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)
+{
+ 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)
+{
+ 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;
+}
+
+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;
+ default:
+ LOG (("Unhandled Write of %02x to register %02x", data, offset));
+ }
+
+#if VERBOSE > 2
+ if (offset != ow_ofs || data != ow_data || ow_cnt >= 1000) {
+ logerror ("\npit68230_device::write: previous identical operation performed %02x times\n", ow_cnt);
+ ow_cnt = 0;
+ ow_data = data;
+ ow_ofs = offset;
+ logerror ("pit68230_device::write: offset=%02x data=%02x %lld\n", ow_ofs, ow_data, machine ().firstcpu->total_cycles ());
+ }
+ else
+ ow_cnt++;
+#endif
+
+}
+
+#if VERBOSE > 2
+static INT32 or_cnt = 0;
+static INT32 or_data = 0;
+static INT32 or_ofs = 0;
+#endif
+
+UINT8 pit68230_device::rr_pitreg_pgcr()
+{
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pgcr));
+ return m_pgcr;
+}
+
+UINT8 pit68230_device::rr_pitreg_psrr()
+{
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_psrr));
+ return m_psrr;
+}
+
+UINT8 pit68230_device::rr_pitreg_paddr()
+{
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_paddr));
+ return m_paddr;
+}
+
+UINT8 pit68230_device::rr_pitreg_pbddr()
+{
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pbddr));
+ return m_pbddr;
+}
+
+UINT8 pit68230_device::rr_pitreg_pcddr()
+{
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pcddr));
+ return m_pcddr;
+}
+
+UINT8 pit68230_device::rr_pitreg_pacr()
+{
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pacr));
+ return m_pacr;
+}
+
+UINT8 pit68230_device::rr_pitreg_pbcr()
+{
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pbcr));
+ return m_pbcr;
+}
+
+UINT8 pit68230_device::rr_pitreg_padr()
+{
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_padr));
+ return m_padr;
+}
+
+/* 4.6.2. PORT B DATA REGISTER (PBDR). The port B data register is a holding
+ * register for moving data to and from port B pins. The port B data direction
+ * register determines whether each pin is an input (zero) or an output (one).
+ * This register is readable and writable at all times. Depending on the chosen
+ * mode/submode, reading or writing may affect the double-buffered handshake
+ * mechanism. The port B data register is not affected by the assertion of the
+ * RESET pin. PB0-PB7 sits on pins 17-24 on a 48 pin DIP package */
+UINT8 pit68230_device::rr_pitreg_pbdr()
+{
+ 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.
+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.*/
+UINT8 pit68230_device::rr_pitreg_paar()
+{
+ // NOTE: no side effect emulated so using ..padr
+ UINT8 ret;
+ ret = m_pa_in_cb();
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, ret));
+ return ret;
+}
+
+/* The port B alternate register is an alternate register for reading the port B 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.*/
+UINT8 pit68230_device::rr_pitreg_pbar()
+{
+ // NOTE: no side effect emulated so using ..pbdr
+ UINT8 ret;
+ ret = m_pb_in_cb();
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, ret));
+ return ret;
+}
+
+/* 4.8. PORT STATUS REGISTER (PSR) The port status register contains information about
+ * handshake pin activity. Bits 7-4 show the instantaneous level of the respective handshake
+ * pin, and are independent of the handshake pin sense bits in the port general control
+ * register. Bits 3-0 are the respective status bits referred to throughout this document.
+ * Their interpretation depends on the programmed mode/submode of the PI/T. For bits
+ * 3-0 a one is the active or asserted state. */
+UINT8 pit68230_device::rr_pitreg_psr()
+{
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_psr));
+ return m_psr;
+}
+
+UINT8 pit68230_device::rr_pitreg_cntrh()
+{
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, (m_cntr >> 16) & 0xff));
+ return (m_cntr >> 16) & 0xff;
+}
+
+UINT8 pit68230_device::rr_pitreg_cntrm()
+{
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, (m_cntr >> 8) & 0xff));
+ return (m_cntr >> 8) & 0xff;
+}
+
+UINT8 pit68230_device::rr_pitreg_cntrl()
+{
+ LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, (m_cntr >> 0) & 0xff));
+ return (m_cntr >> 0) & 0xff;
+}
READ8_MEMBER (pit68230_device::read){
- UINT8 data;
-
- switch (offset) {
- case PIT_68230_PGCR:
- data = m_pgcr;
- break;
-
- case PIT_68230_PSRR:
- data = m_psrr;
- break;
-
- case PIT_68230_PADDR:
- data = m_paddr;
- break;
-
- case PIT_68230_PBDDR:
- data = m_pbddr;
- break;
-
- case PIT_68230_PCDDR:
- data = m_pcddr;
- break;
-
- case PIT_68230_PACR:
- data = m_pacr;
- break;
-
- case PIT_68230_PBCR:
- data = m_pbcr;
- break;
-
- case PIT_68230_PADR:
- data = m_padr;
- break;
-
- case PIT_68230_PBDR:
- /* 4.6.2. PORT B DATA REGISTER (PBDR). The port B data register is a holding
- * register for moving data to and from port B pins. The port B data direction
- * register determines whether each pin is an input (zero) or an output (one).
- * This register is readable and writable at all times. Depending on the chosen
- * mode/submode, reading or writing may affect the double-buffered handshake
- * mechanism. The port B data register is not affected by the assertion of the
- * RESET pin. PB0-PB7 sits on pins 17-24 on a 48 pin DIP package */
- data = m_pbdr;
- break;
-
- case PIT_68230_PSR:
- /* 4.8. PORT STATUS REGISTER (PSR) The port status register contains information about
- * handshake pin activity. Bits 7-4 show the instantaneous level of the respective handshake
- * pin, and are independent of the handshake pin sense bits in the port general control
- * register. Bits 3-0 are the respective status bits referred to throughout this document.
- * Their interpretation depends on the programmed mode/submode of the PI/T. For bits
- * 3-0 a one is the active or asserted state. */
- data = m_psr;
- break;
-
- default:
- LOG (logerror ("unhandled register %02x", offset));
- data = 0;
- }
-
- LOG (if (offset != or_ofs || data != or_data || or_cnt >= 1000) {
- logerror ("\npit68230_device::read: previous identical operation performed %02x times\n", or_cnt);
- or_cnt = 0;
- or_data = data;
- or_ofs = offset;
- logerror ("pit68230_device::read: offset=%02x data=%02x %lld\n", or_ofs, or_data, machine ().firstcpu->total_cycles ());
- }
- else
- or_cnt++; )
-
- return data;
+ 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;
+ default:
+ LOG (("Unhandled read register %02x\n", offset));
+ data = 0;
+ }
+
+#if VERBOSE > 2
+ if (offset != or_ofs || data != or_data || or_cnt >= 1000) {
+ logerror ("\npit68230_device::read: previous identical operation performed %02x times\n", or_cnt);
+ or_cnt = 0;
+ or_data = data;
+ or_ofs = offset;
+ logerror ("pit68230_device::read: offset=%02x data=%02x %lld\n", or_ofs, or_data, machine ().firstcpu->total_cycles ());
+ }
+ else
+ or_cnt++;
+#endif
+
+ return data;
}
diff --git a/src/devices/machine/68230pit.h b/src/devices/machine/68230pit.h
index 2a2f2c6824c..7712419f7fc 100644
--- a/src/devices/machine/68230pit.h
+++ b/src/devices/machine/68230pit.h
@@ -43,14 +43,35 @@
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
-#define MCFG_PIT68230_PA_OUTPUT_CALLBACK(_write) \
- devcb = &pit68230_device::set_pa_wr_callback (*device, DEVCB_ ## _write);
+#define MCFG_PIT68230_PA_INPUT_CB(_devcb) \
+ devcb = &pit68230_device::set_pa_in_callback (*device, DEVCB_##_devcb);
-#define MCFG_PIT68230_PB_OUTPUT_CALLBACK(_write) \
- devcb = &pit68230_device::set_pb_wr_callback (*device, DEVCB_ ## _write);
+#define MCFG_PIT68230_PA_OUTPUT_CB(_devcb) \
+ devcb = &pit68230_device::set_pa_out_callback (*device, DEVCB_##_devcb);
-#define MCFG_PIT68230_H2_CALLBACK(_write) \
- devcb = &pit68230_device::set_h2_wr_callback (*device, DEVCB_ ## _write);
+#define MCFG_PIT68230_PB_INPUT_CB(_devcb) \
+ devcb = &pit68230_device::set_pb_in_callback (*device, DEVCB_##_devcb);
+
+#define MCFG_PIT68230_PB_OUTPUT_CB(_devcb) \
+ devcb = &pit68230_device::set_pb_out_callback (*device, DEVCB_##_devcb);
+
+#define MCFG_PIT68230_PC_INPUT_CB(_devcb) \
+ devcb = &pit68230_device::set_pc_in_callback (*device, DEVCB_##_devcb);
+
+#define MCFG_PIT68230_PC_OUTPUT_CB(_devcb) \
+ devcb = &pit68230_device::set_pc_out_callback (*device, DEVCB_##_devcb);
+
+#define MCFG_PIT68230_H1_CB(_devcb) \
+ devcb = &pit68230_device::set_h1_out_callback (*device, DEVCB_##_devcb);
+
+#define MCFG_PIT68230_H2_CB(_devcb) \
+ devcb = &pit68230_device::set_h2_out_callback (*device, DEVCB_##_devcb);
+
+#define MCFG_PIT68230_H3_CB(_devcb) \
+ devcb = &pit68230_device::set_h3_out_callback (*device, DEVCB_##_devcb);
+
+#define MCFG_PIT68230_H4_CB(_devcb) \
+ devcb = &pit68230_device::set_h4_out_callback (*device, DEVCB_##_devcb);
/*-----------------------------------------------------------------------
* Registers RS1-RS5 R/W Description
@@ -84,46 +105,100 @@
//**************************************************************************
class pit68230_device : public device_t, public device_execute_interface
{
-public:
-// construction/destruction
-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);
-pit68230_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-template<class _Object> static devcb_base &set_pa_wr_callback (device_t &device, _Object object)
-{
- return downcast<pit68230_device &>(device).m_write_pa.set_callback (object);
-}
-template<class _Object> static devcb_base &set_h2_wr_callback (device_t &device, _Object object)
-{
- return downcast<pit68230_device &>(device).m_write_h2.set_callback (object);
-}
+ public:
+ // construction/destruction
+ 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);
+ pit68230_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ template<class _Object> static devcb_base &set_pa_in_callback (device_t &device, _Object object){ return downcast<pit68230_device &>(device).m_pa_in_cb.set_callback (object); }
+ template<class _Object> static devcb_base &set_pa_out_callback (device_t &device, _Object object){ return downcast<pit68230_device &>(device).m_pa_out_cb.set_callback (object); }
+ template<class _Object> static devcb_base &set_pb_in_callback (device_t &device, _Object object){ return downcast<pit68230_device &>(device).m_pb_in_cb.set_callback (object); }
+ template<class _Object> static devcb_base &set_pb_out_callback (device_t &device, _Object object){ return downcast<pit68230_device &>(device).m_pb_out_cb.set_callback (object); }
+ template<class _Object> static devcb_base &set_pc_in_callback (device_t &device, _Object object){ return downcast<pit68230_device &>(device).m_pc_in_cb.set_callback (object); }
+ template<class _Object> static devcb_base &set_pc_out_callback (device_t &device, _Object object){ return downcast<pit68230_device &>(device).m_pc_out_cb.set_callback (object); }
+ template<class _Object> static devcb_base &set_h1_out_callback (device_t &device, _Object object){ return downcast<pit68230_device &>(device).m_h1_out_cb.set_callback (object); }
+ template<class _Object> static devcb_base &set_h2_out_callback (device_t &device, _Object object){ return downcast<pit68230_device &>(device).m_h2_out_cb.set_callback (object); }
+ template<class _Object> static devcb_base &set_h3_out_callback (device_t &device, _Object object){ return downcast<pit68230_device &>(device).m_h3_out_cb.set_callback (object); }
+ template<class _Object> static devcb_base &set_h4_out_callback (device_t &device, _Object object){ return downcast<pit68230_device &>(device).m_h4_out_cb.set_callback (object); }
+
+ DECLARE_WRITE8_MEMBER (write);
+ DECLARE_READ8_MEMBER (read);
-DECLARE_WRITE8_MEMBER (write);
-DECLARE_READ8_MEMBER (read);
+ void h1_set (UINT8 state);
+ void portb_setbit (UINT8 bit, UINT8 state);
-void h1_set (UINT8 state);
-void portb_setbit (UINT8 bit, UINT8 state);
+ void wr_pitreg_pgcr(UINT8 data);
+ void wr_pitreg_psrr(UINT8 data);
+ void wr_pitreg_paddr(UINT8 data);
+ void wr_pitreg_pbddr(UINT8 data);
+ void wr_pitreg_pcddr(UINT8 data);
+ void wr_pitreg_pacr(UINT8 data);
+ void wr_pitreg_pbcr(UINT8 data);
+ void wr_pitreg_padr(UINT8 data);
+ void wr_pitreg_paar(UINT8 data);
+ void wr_pitreg_pbar(UINT8 data);
+ void wr_pitreg_psr(UINT8 data);
+ void wr_pitreg_tcr(UINT8 data);
+ void wr_pitreg_cprh(UINT8 data);
+ void wr_pitreg_cprm(UINT8 data);
+ void wr_pitreg_cprl(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_pacr();
+ UINT8 rr_pitreg_pbcr();
+ UINT8 rr_pitreg_padr();
+ UINT8 rr_pitreg_pbdr();
+ UINT8 rr_pitreg_paar();
+ UINT8 rr_pitreg_pbar();
+ UINT8 rr_pitreg_psr();
+ UINT8 rr_pitreg_cntrh();
+ UINT8 rr_pitreg_cntrm();
+ UINT8 rr_pitreg_cntrl();
protected:
-// 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;
-int m_icount;
-devcb_write8 m_write_pa;
-devcb_write_line m_write_h2;
-
-// peripheral ports
-UINT8 m_pgcr; // Port General Control register
-UINT8 m_psrr; // Port Service Request register
-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_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_psr; // Port Status Register
+
+ enum {
+ REG_TCR_ENABLE = 0x01
+ };
+
+ // 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;
+ int m_icount;
+
+ devcb_write8 m_pa_out_cb;
+ devcb_read8 m_pa_in_cb;
+ devcb_write8 m_pb_out_cb;
+ devcb_read8 m_pb_in_cb;
+ devcb_write8 m_pc_out_cb;
+ devcb_read8 m_pc_in_cb;
+ devcb_write_line m_h1_out_cb;
+ devcb_write_line m_h2_out_cb;
+ devcb_write_line m_h3_out_cb;
+ devcb_write_line m_h4_out_cb;
+
+ // peripheral ports
+ UINT8 m_pgcr; // Port General Control register
+ UINT8 m_psrr; // Port Service Request register
+ 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_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_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
};
// device type definition
diff --git a/src/devices/machine/scnxx562.cpp b/src/devices/machine/scnxx562.cpp
new file mode 100644
index 00000000000..b7ec3b80109
--- /dev/null
+++ b/src/devices/machine/scnxx562.cpp
@@ -0,0 +1,1793 @@
+// license:BSD-3-Clause copyright-holders: Joakim Larsson Edstrom
+/***************************************************************************
+
+ DUSCC Dual Serial Communications Controller emulation
+
+ The DUSCC was introduced in the mid 80:ies by Signetics, a part of Philips
+ Semiconductor that later became NXP, and apparantly trying to dig into
+ the huge success of the Zilog SCC with a very similar feature set but not
+ software compatible at all.
+
+ The variants in the DUSCC family are as follows:
+
+ Bus type
+ Intel Motorola
+----------------------------------
+ NMOS 26562 68562
+ CMOS 26C562 68C562
+----------------------------------
+ For more info see:
+ page 511: http://bitsavers.informatik.uni-stuttgart.de/pdf/signetics/_dataBooks/1986_Signetics_Microprocessor.pdf
+ page 514: http://bitsavers.informatik.uni-stuttgart.de/pdf/signetics/_dataBooks/1994_Signetics_Data_Communications.pdf
+
+Designs known of including one or more DUSCCs
+------------------------------------------------
+ Force Computers
+ CPU VME boards: CPU-22, CPU-26, CPU-30, CPU-33, CPU-386, CPU-40, CPU-41
+ Graphics VME boards: AGC-1
+ Serial VME boards: ISIO-1, ISIO-2
+ Digital Equipment
+ DEC MicroServer DEMSA, DECrouter-150, DECrouter-250
+------------------------------------------------
+
+TODO/ "NDUSCC" "CDUSCC"
+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
+ x1,x16 Y Y
+ break det/gen Y Y
+ parity, framing & Y Y
+ overrun error det
+ -- byte oriented synchrounous features --
+ Int/ext char sync Y Y
+ 1/2 synch chars ? ?
+ Aut CRC gen/det Y Y
+ -- SDLC/HDLC capabilities ---------------
+ Abort seq gen/chk Y Y
+ Aut zero ins/det Y Y
+ Aut flag insert Y Y
+ Addr field rec Y Y
+ I-fld resid hand Y Y
+ 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
+ FM2 enc/dec
+ Manchester dec Y Y
+ Baud gen per chan Y Y
+ DPLL clock recov Y Y
+ -- Additional features CMOS versions -----
+ Status FIFO N Y
+ Watchdog timer N Y
+ Fifo Fill status N Y
+ DMA frame status N Y
+ Rx/TxRDY on FIFO lvl N Y
+ TxFifo Empty status N Y
+ Interrupt enable bits N Y
+ X.21 pattern recogn N Y
+ Improved BiSync support N Y
+ -------------------------------------------------------------------------
+ x/p = Features that has been implemented n/a = features that will not
+***************************************************************************/
+
+#include "scnxx562.h"
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+/* 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 LOG(x) do { if (VERBOSE) logerror x; } while (0)
+#define LOGR(x)
+#if VERBOSE == 0
+#define logerror printf
+#endif
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#define LLFORMAT "%I64%"
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#define LLFORMAT "%lld"
+#endif
+
+#define CHANA_TAG "cha"
+#define CHANB_TAG "chb"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+// device type definition
+const device_type DUSCC = &device_creator<duscc_device>;
+const device_type DUSCC_CHANNEL = &device_creator<duscc_channel>;
+const device_type DUSCC26562 = &device_creator<duscc26562_device>;
+const device_type DUSCC26C562 = &device_creator<duscc26C562_device>;
+const device_type DUSCC68562 = &device_creator<duscc68562_device>;
+const device_type DUSCC68C562 = &device_creator<duscc68C562_device>;
+
+//-------------------------------------------------
+// device_mconfig_additions -
+//-------------------------------------------------
+MACHINE_CONFIG_FRAGMENT( duscc )
+ MCFG_DEVICE_ADD(CHANA_TAG, DUSCC_CHANNEL, 0)
+ MCFG_DEVICE_ADD(CHANB_TAG, DUSCC_CHANNEL, 0)
+MACHINE_CONFIG_END
+
+machine_config_constructor duscc_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( duscc );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// duscc_device - constructor
+//-------------------------------------------------
+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),
+#if 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)
+{
+ for (auto & elem : m_int_state)
+ elem = 0;
+}
+
+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)
+{
+ for (auto & elem : m_int_state)
+ elem = 0;
+}
+
+duscc26562_device::duscc26562_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : duscc_device(mconfig, DUSCC26562, "DUSCC 26562", tag, owner, clock, TYPE_DUSCC26562, "duscc26562", __FILE__){ }
+
+duscc26C562_device::duscc26C562_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : duscc_device(mconfig, DUSCC26C562, "DUSCC 26C562", tag, owner, clock, TYPE_DUSCC26C562, "duscc26C562", __FILE__){ }
+
+duscc68562_device::duscc68562_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : duscc_device(mconfig, DUSCC68562, "DUSCC 68562", tag, owner, clock, TYPE_DUSCC68562, "duscc68562", __FILE__){ }
+
+duscc68C562_device::duscc68C562_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : duscc_device(mconfig, DUSCC68C562, "DUSCC 68C562", tag, owner, clock, TYPE_DUSCC68C562, "duscc68C562", __FILE__){ }
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void duscc_device::device_start()
+{
+ LOG(("%s\n", FUNCNAME));
+ // resolve callbacks
+ m_out_txda_cb.resolve_safe();
+ 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();
+
+ // state saving
+ //save_item(NAME(m_int_state));
+
+ LOG((" - DUSCC variant %02x\n", m_variant));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void duscc_device::device_reset()
+{
+ LOG(("%s %s \n",tag(), FUNCNAME));
+
+ m_chanA->reset();
+ m_chanB->reset();
+}
+
+//-------------------------------------------------
+// check_interrupts -
+//-------------------------------------------------
+
+void duscc_device::check_interrupts()
+{
+ LOG(("%s %s - not implemented\n",tag(), FUNCNAME));
+ // m_out_int_cb(state);
+}
+
+
+//-------------------------------------------------
+// reset_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)
+ {
+ elem = 0;
+ }
+
+ // check external interrupt sources
+ check_interrupts();
+#endif
+}
+
+UINT8 duscc_device::modify_vector(UINT8 vec, int i, UINT8 src)
+{
+ LOG(("%s %s - not implemented\n",tag(), FUNCNAME));
+ return vec;
+}
+
+
+//-------------------------------------------------
+// trigger_interrupt -
+//-------------------------------------------------
+void duscc_device::trigger_interrupt(int index, int state)
+{
+ LOG(("%s %s - not implemented\n",tag(), FUNCNAME));
+}
+
+READ8_MEMBER( duscc_device::read )
+{
+ if ( offset & 0x20 )
+ return m_chanB->read(offset);
+ else
+ return m_chanA->read(offset);
+}
+
+WRITE8_MEMBER( duscc_device::write )
+{
+ if ( offset & 0x20 )
+ m_chanB->write(data, offset);
+ else
+ m_chanA->write(data, offset);
+ return;
+}
+
+//**************************************************************************
+// DUSCC CHANNEL
+//**************************************************************************
+duscc_channel::duscc_channel(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, DUSCC_CHANNEL, "DUSCC channel", tag, owner, clock, "duscc_channel", __FILE__),
+ device_serial_interface(mconfig, *this),
+ m_brg_rx_rate(0),
+ m_brg_tx_rate(0),
+ m_brg_const(1),
+ m_rx_error(0),
+ m_rx_clock(0),
+ m_rx_first(0),
+ m_rx_break(0),
+ m_rxd(0),
+ m_cts(0),
+ m_dcd(0),
+ m_tx_data(0),
+ m_tx_clock(0),
+ m_dtr(0),
+ m_rts(0),
+ m_sync(0)
+{
+ LOG(("%s\n",FUNCNAME));
+
+ // Reset all registers
+ m_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_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;
+ }
+}
+
+//-------------------------------------------------
+// start - channel startup
+//-------------------------------------------------
+
+void duscc_channel::device_start()
+{
+ LOG(("%s\n", FUNCNAME));
+ m_uart = downcast<duscc_device *>(owner());
+ m_index = m_uart->get_channel_index(this);
+
+ m_rx_fifo_sz = (m_uart->m_variant & SET_CMOS) ? 16 : 4;
+ m_rx_fifo_wp = m_rx_fifo_rp = 0;
+
+ m_tx_fifo_sz = (m_uart->m_variant & SET_CMOS) ? 16 : 4;
+ m_tx_fifo_wp = m_tx_fifo_rp = 0;
+
+ m_cid = (m_uart->m_variant & SET_CMOS) ? 0x7f : 0xff; // TODO: support CMOS rev A = 0xbf
+
+ // state saving
+ save_item(NAME(m_cmr1));
+ save_item(NAME(m_cmr2));
+ save_item(NAME(m_s1r));
+ save_item(NAME(m_s2r));
+ save_item(NAME(m_tpr));
+ 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_ctcr));
+ save_item(NAME(m_omr));
+ save_item(NAME(m_cth));
+ save_item(NAME(m_ctl));
+ save_item(NAME(m_pcr));
+ save_item(NAME(m_ccr));
+ save_item(NAME(m_txfifo[4]));
+ save_item(NAME(m_rxfifo[4]));
+ 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_ier));
+ // 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_mrr));
+ save_item(NAME(m_ier1));
+ save_item(NAME(m_ier2));
+ save_item(NAME(m_ier3));
+ save_item(NAME(m_trcr));
+ save_item(NAME(m_rflr));
+ save_item(NAME(m_ftlr));
+ save_item(NAME(m_trmsr));
+ save_item(NAME(m_telr));
+ save_item(NAME(m_rx_data_fifo));
+ save_item(NAME(m_rx_error_fifo));
+ save_item(NAME(m_rx_fifo_rp));
+ save_item(NAME(m_rx_fifo_wp));
+ save_item(NAME(m_rx_fifo_sz));
+ save_item(NAME(m_rx_clock));
+ save_item(NAME(m_rx_first));
+ save_item(NAME(m_rx_break));
+ save_item(NAME(m_ri));
+ save_item(NAME(m_cts));
+ save_item(NAME(m_dcd));
+ save_item(NAME(m_tx_data));
+ save_item(NAME(m_tx_clock));
+ save_item(NAME(m_dtr));
+ save_item(NAME(m_rts));
+ save_item(NAME(m_sync));
+
+ device_serial_interface::register_save_state(machine().save(), this);
+}
+
+
+//-------------------------------------------------
+// reset - reset channel status
+//-------------------------------------------------
+
+void duscc_channel::device_reset()
+{
+ LOG(("%s\n", FUNCNAME));
+
+ // Reset RS232 emulation
+ receive_register_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;
+
+ // reset external lines TODO: check relation to control bits and reset
+ set_rts(1);
+ set_dtr(1);
+
+ // reset interrupts
+ if (m_index == duscc_device::CHANNEL_A)
+ {
+ m_uart->reset_interrupts();
+ }
+
+ m_a7 = 0;
+}
+
+void duscc_channel::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ // LOG(("%s %d\n", FUNCNAME, id));
+ device_serial_interface::device_timer(timer, id, param, ptr);
+}
+
+
+//-------------------------------------------------
+// tra_callback -
+//-------------------------------------------------
+
+void duscc_channel::tra_callback()
+{
+ if (!is_transmit_register_empty())
+ {
+ int db = transmit_register_get_data_bit();
+
+ LOGR((LLFORMAT " %s() \"%s \"Channel %c transmit data bit %d\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, db));
+
+ // transmit data
+ if (m_index == duscc_device::CHANNEL_A)
+ m_uart->m_out_txda_cb(db);
+ else
+ m_uart->m_out_txdb_cb(db);
+ }
+ else
+ {
+ LOG((LLFORMAT " %s() \"%s \"Channel %c Failed to transmit \n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index));
+ logerror("%s \"%s \"Channel %c Failed to transmit\n", FUNCNAME, m_owner->tag(), 'A' + m_index);
+ }
+}
+
+
+//------------------------------------------
+// tra_complete -
+// TODO:
+// - Fix mark and space tx support
+//------------------------------------------
+
+void duscc_channel::tra_complete()
+{
+ if (m_tra == 1) // transmitter enabled?
+ {
+ if (m_tx_fifo_rp != m_tx_fifo_wp) // there are more characters to send?
+ {
+ transmit_register_setup(m_tx_data_fifo[m_tx_fifo_rp]); // Reload the shift register
+ m_tx_fifo_rp_step();
+ }
+ 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);
+ }
+ else // Always ready for more!
+ m_gsr |= (m_index == duscc_device::CHANNEL_A ? REG_GSR_CHAN_A_TXREADY : REG_GSR_CHAN_B_TXREADY);
+ }
+}
+
+
+//-------------------------------------------------
+// rcv_callback -
+//-------------------------------------------------
+
+void duscc_channel::rcv_callback()
+{
+ if (m_rcv == 1)
+ {
+ LOG((LLFORMAT " %s() \"%s \"Channel %c received data bit %d\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_rxd));
+ receive_register_update_bit(m_rxd);
+ }
+}
+
+
+//-------------------------------------------------
+// rcv_complete -
+//-------------------------------------------------
+
+void duscc_channel::rcv_complete()
+{
+ UINT8 data;
+
+ receive_register_extract();
+ data = get_received_char();
+ LOG((LLFORMAT " %s() \"%s \"Channel %c Received Data %c\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, data));
+ receive_data(data);
+}
+
+
+//-------------------------------------------------
+// get_xx_clock_mode - get clock divisor
+// TODO
+// - support all the other clock divisors
+// - actually use the divisors when calculating baud
+//-------------------------------------------------
+
+int duscc_channel::get_rx_clock_mode()
+{
+ int clocks = 1;
+
+ if ( (m_rtr & REG_RTR_RXCLK_MASK) == REG_RTR_RXCLK_BRG )
+ clocks = 32;
+
+ return clocks;
+}
+
+int duscc_channel::get_tx_clock_mode()
+{
+ int clocks = 1;
+
+ if ( (m_ttr & REG_TTR_TXCLK_MASK) == REG_TTR_TXCLK_BRG )
+ clocks = 32;
+
+ return clocks;
+}
+
+void duscc_channel::set_rts(int state)
+{
+ LOG(("%s(%d) \"%s\": %c \n", FUNCNAME, state, m_owner->tag(), 'A' + m_index));
+ if (m_index == duscc_device::CHANNEL_A)
+ m_uart->m_out_rtsa_cb(state);
+ else
+ m_uart->m_out_rtsb_cb(state);
+}
+
+/* --------------------------------------------------------------------------
+ * get_stop_bits - get number of stop bits
+ * The DUSCC supports from 1/2 stop bit to 2 stop bits in 1/16th bit increments
+ * This is not yet supported by diserial so we need to translate into 1, 1.5
+ * or 2 stop bits. It is also dependent on the data bit length
+ * TODO: Support finer granularity of stop bits in diserial if/when nessesarry
+ * ---------------------------------------------------------------------------
+ * TPR[4:7] TPR[0:1]
+ * 5 bits 6-8 bits
+ * 00 01,10,11
+ * ---------------------------
+ * 0 0 0 0 1.063 0.563
+ * 0 0 0 1 1.125 0.625
+ * 0 0 1 0 1.188 0.688
+ * 0 0 1 1 1.250 0.750
+ * 0 1 0 0 1.313 0.813
+ * 0 1 0 1 1.375 0.875
+ * 0 1 1 0 1.438 0.938
+ * 0 1 1 1 1.500 1.000
+ * 1 0 0 0 1.563 1.563
+ * 1 0 0 1 1.625 1.625
+ * 1 0 1 0 1.688 1.688
+ * 1 0 1 1 1.750 1.750
+ * 1 1 0 0 1.813 1.813
+ * 1 1 0 1 1.875 1.875
+ * 1 1 1 0 1.938 1.938
+ * 1 1 1 1 2.000 2.000
+ * --------------------------------------------------------------------------
+ */
+device_serial_interface::stop_bits_t duscc_channel::get_stop_bits()
+{
+ const stop_bits_t bits5[] =
+ { STOP_BITS_1, STOP_BITS_1, STOP_BITS_1, STOP_BITS_1, STOP_BITS_1_5, STOP_BITS_1_5, STOP_BITS_1_5, STOP_BITS_1_5,
+ STOP_BITS_1_5, STOP_BITS_1_5, STOP_BITS_1_5, STOP_BITS_2, STOP_BITS_2, STOP_BITS_2, STOP_BITS_2, STOP_BITS_2 };
+ const stop_bits_t bits6to8[] =
+ { STOP_BITS_1, STOP_BITS_1, STOP_BITS_1, STOP_BITS_1, STOP_BITS_1, STOP_BITS_1, STOP_BITS_1, STOP_BITS_1,
+ STOP_BITS_1, STOP_BITS_1_5, STOP_BITS_1_5, STOP_BITS_2, STOP_BITS_2, STOP_BITS_2, STOP_BITS_2, STOP_BITS_2 };
+
+ /* 5 data bits */
+ if (get_tx_word_length() == 5)
+ {
+ return bits5[((m_tpr & REG_TPR_STOP_BITS_MASK) >> 4) & 0x0f];
+ }
+ else /* 6-8 data bits */
+ {
+ return bits6to8[((m_tpr & REG_TPR_STOP_BITS_MASK) >> 4) & 0x0f];
+ }
+
+ return STOP_BITS_0;
+}
+
+//-------------------------------------------------
+// get_rx_word_length - get receive word length
+//-------------------------------------------------
+
+int duscc_channel::get_rx_word_length()
+{
+ int bits = 5;
+
+ switch (m_rpr & REG_RPR_DATA_BITS_MASK)
+ {
+ case REG_RPR_DATA_BITS_5BIT: bits = 5; break;
+ case REG_RPR_DATA_BITS_6BIT: bits = 6; break;
+ case REG_RPR_DATA_BITS_7BIT: bits = 7; break;
+ case REG_RPR_DATA_BITS_8BIT: bits = 8; break;
+ }
+
+ return bits;
+}
+
+
+//-------------------------------------------------
+// get_tx_word_length - get transmit word length
+//-------------------------------------------------
+
+int duscc_channel::get_tx_word_length()
+{
+ int bits = 5;
+
+ switch (m_tpr & REG_TPR_DATA_BITS_MASK)
+ {
+ case REG_TPR_DATA_BITS_5BIT: bits = 5; break;
+ case REG_TPR_DATA_BITS_6BIT: bits = 6; break;
+ case REG_TPR_DATA_BITS_7BIT: bits = 7; break;
+ case REG_TPR_DATA_BITS_8BIT: bits = 8; break;
+ }
+
+ 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; }
+
+/* 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). */
+UINT8 duscc_channel::do_dusccreg_ccr_r()
+{
+ LOG(("%s\n", FUNCNAME));
+ return (UINT8) m_ccr | 1 << 4 | 1 << 5;
+}
+
+UINT8 duscc_channel::do_dusccreg_rxfifo_r()
+{
+ UINT8 data = 0;
+
+ LOG(("%s\n", FUNCNAME));
+ LOG((" - RX rp:%d wp:%d sz:%d\n", m_rx_fifo_rp, m_rx_fifo_wp, m_rx_fifo_sz));
+
+ /* So is there a character in the FIFO? */
+ if (m_rx_fifo_rp != m_rx_fifo_wp)
+ {
+ data = m_rx_data_fifo[m_rx_fifo_rp];
+ m_rx_fifo_rp_step();
+ LOG((" - RX reading out data:%02x '%c'\n", data, isalnum(data) ? data : ' '));
+ }
+ else
+ {
+ logerror("- RX FIFO empty despite RxREADY\n");
+ LOG(("- RX FIFO empty despite RxREADY\n"));
+ }
+
+ 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()
+{
+ logerror("register access method %s is not implemented yet\n", FUNCNAME);
+ return (UINT8) m_ictsr;
+}
+
+/* General Status Register (GSR)
+ 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 B External or Counter/timer 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: TRSRB[7:1], TRSRB[7:3].
+ [5] Channel B 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.
+ Resetting the transmitter negates TxRDY.
+ [4] Channel B 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: TRSRA[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.
+*/
+UINT8 duscc_channel::do_dusccreg_gsr_r()
+{
+ LOGR(("%s <- %02x\n", FUNCNAME, m_gsr));
+ return (UINT8) 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_cid_r()
+{
+ LOG(("%s\n", FUNCNAME));
+ if ( m_uart->m_variant != SET_CMOS )
+ {
+ logerror("Attempt read out CDUSCC register CID on an NDUSCC\n");
+ return 0;
+ }
+ if ( m_index != duscc_device::CHANNEL_B )
+ {
+ logerror("Attempt read out CID on channel B not allowed\n");
+ return 0;
+ }
+ else
+ 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).
+ 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.
+ 11 FM 1. Bi-phase mark.
+ [5] Extended Control (BOP) -
+ 0 No. A one-octet control field follows the address field.
+ 1 Yes. A two-octet control field follows the address field.
+ [5] Parity (COP/ ASYNC), Code Select (BISYNC)
+ 0 Even parity if with parity is selected by [4:3] or a 0 in the parity bit position if force parity is
+ selected by [4:3]. In BISYNC protocol mode, internal character comparisons are made using EBCDIC coding.
+ 1 Odd parity if with parity is selected by [4:3] or a 1 in the parity bit position if force parity is selected by [4:3].
+ In BISYNC protocol mode, internal character comparisons are made using Bbit ASCII coding.
+ [4:3] Address Mode (BOP) -
+ This field controls whether a single octet or multiple octets follow the opening FLAG(s) for both the receiver and the transmitter.
+ This field is activated by selection of BOP secondary mode through the channel protocol mode bits CMR1_[2:0] (see Detailed Operation).
+ 00 Single octet address.
+ 01 Extended address.
+ 10 Dual octet address.
+ 11 Dual octet address with group.
+ [4:3] Parity Mode (COP/ASYNC) -
+ This field selects the parity mode for both the receiver and the transmitter. A parity bit is added to the programmed character length if
+ with parity or force parity is selected:
+ 00 No parity. Required when BISYNC protocol mode is programmed.
+ 01 Reserved.
+ 10 With parity. Odd or even parity is selected by [5].
+ 11 Force parity. The parity bit is forced to the state selected by [5].
+ [2:0] Channel Protocol Mode -
+ This field selects the operational protocol and submode for both the receiver and transmitter:
+ 000 - BOP Primary. No address comparison is performed. For receive, all characters received after the opening FLAG(s) are transferred to the FIFO.
+ 001 - BOP Secondary. This mode activates the address modes selected by [4:3]. Except in the case of extended address ([4:3]=01), an address comparison
+ is performed to determine if a frame should be received. Refer to Detailed Operation for details of the various addressing modes. If a valid comparison
+ occurs, the receiver is activated and the address octets and all subsequent received characters of the frame are transferred to the receive FIFO.
+ 010 - BOP Loop. The DUSCC acts as a secondary station in a loop. The GO-ON-LOOP and GO-OFF-LOOP commands are used to cause the DUSCC to go on and off the
+ loop. Normally, the TXD output echoes the RXD input with a three bit time delay. If the transmitter is enabled and the 'go active on poll' command has been
+ asserted, the transmitter will begin sending when an EOP sequence consisting of a zero followed by seven ones is detected. The DUSCC changes the last one of
+ the EOP to zero, making it another FLAG, and then operates as described in the detailed operation section. The loop sending status bit (TRSR[6]) is asserted
+ concurrent with the beginning of transmission. The frame should normally be terminated with an EOM followed by an echo of the marking RXD line so that secondary
+ stations further down the loop can append their messages to the messages from up-loop stations by the same process. If the 'go active on poll'command is not
+ asserted, the transmitter remains inactive (other than echOing the received data) even when the EOP sequence is received.
+ 011 - BOP Loop without address comparison. Same as normal loop mode except that address field comparisons are disabled. All received frames aretransmitted to the CPU.
+ 100 - COP Dual SYN. Character sync is achieved upon receipt of a bit sequence matching the contents of the appropriate bits of SIR and S2R (SYNI-SYN2), including
+ parity bits if any.
+ 101 - COP Dual SYN (BISYNC). Character sync is achieved upon receipt of a bit sequence matching the contents of the appropriate bits of SI Rand S2R
+ (SYN1·SYN2). In this mode, special transmitter and receive logic is activated. Transmitter and receiver character length must be programmed to 8 bits and no parity
+ 110 - COP Single SYN. Character sync is achieved upon receipt of a bit sequence matching the contents of the appropriate bits of Sl R (SYN1), including parity bit if any.
+ This mode is required when the external sync mode is selected.
+ 111 Asynchronous. Start/stop format.
+*/
+void duscc_channel::do_dusccreg_cmr1_w(UINT8 data)
+{
+ LOG(("%s(%02x)\n", FUNCNAME, data));
+ m_cmr1 = data;
+ LOG(("- Setting up %s mode\n", (m_cmr1 & REG_CMR1_CPMODE_MASK) == REG_CMR1_CPMODE_ASYNC ? "ASYNC" : "SYNC"));
+ LOG(("- Parity: %s\n", ((m_cmr1 & REG_CMR1_PMMODE_MASK) == REG_CMR1_PMMODE_PARITY ? (m_cmr1 & REG_CMR1_PARITY ? "odd" : "even") : "none")));
+ return;
+}
+
+/* CMR2 register
+ [7:6] Channel Connection - This field selects the mode of operation of the channel. The user must exercise care when switching into and out of the various modes. The
+ selected mode will be activated immediately upon mode selection, even if this occurs in the middle of a received or transmitted character.
+
+ 00 - Normal mode. The 1ransmitter and receiver operate independently in either half or full-duplex, controlled by the respective enable commands.
+
+ 01 - Automatic echo mode. Automatically retransmits the received data with a half-bit time delay (ASYNC, 16X clock mode) or a one-bit time delay (allother modes).
+ The following conditions are true while in automatic echo mode:
+ 1. Received data is reclocked and retransmitted on the TXD output.
+ 2. The receiver clock is used for the transmitter.
+ 3. The receiver must be enabled, but the transmitter need not be enabled.
+ 4. The TXRDY and underrun status bits are inactive.
+ 5. The received parity and/or FCS are checked if required, but are not regenerated for transmission,
+ i.e., transmitted parity and/ or FCS are as received.
+ 6. In ASYNC mode, character framing is checked, but the stop bits are retransmitted as received.
+ A received break is echoed as received.
+ 7. CPU to receiver communication continues normally, but the CPU to transmitter link is disabled.
+
+ 10 - Local loopback mode. In this mode:
+ 1. The transmitter output is internally connected to the receiver input.
+ 2. The transmit clock is used for the receiver if NRZI or NRZ encoding is used. For FM or Manchester encoding because the receiver clock is derived from the DPLL,
+ the DPLL source clock must be maintained.
+ 3. The TXD output is held high.
+ 4. The RXD input is ignored.
+ 5. The receiver and transmitter must be enabled.
+ 6. CPU to transmitter and receiver communications continue normally.
+
+ 11 - Reserved.
+
+ [5:3] Data Transfer Interface - This field specifies the type of data transfer between the DUSCC's RX and TX FIFOs and the CPU.
+ All interrupt and status functions operate normally regardless of the data transfer interface programmed.
+ 000 - Half duplex single address DMA.
+ 001 - Half duplex dual address DMA.
+ 010 - Full duplex single address DMA.
+ 011 - Full duplex dual address DMA.
+ 100 - Wait on receive only. In this mode a read of a non-empty receive FIFO results in a normal bus cycle. However, if the receive FIFO of the channel
+ is empty when a read RX FIFO cycle is initiated, the DTACKN output remains negated until a character is received and loaded into the FIFO.
+ DT ACKN is then asserted and the cycle is completed normally.
+ 101 - Wait on transmit only. In this mode a write to a non-full transmit FI Fa results in a normal bus cycle. However, if the transmit FIFO of the channel is
+ full when a write TX FIFO cycle is initiated, the DTACKN output remains negated until a FI Fa position becomes available for the new character. DT ACKN
+ is then asserted and the cycle is completed normally.
+ 110 - Wait on transmit and receive. As above for both wait on receive and transmit operations.
+ 111 - Polled or interrupt. DMA and wait functions of the channel are not activated. Data transfers to the RX and TX FIFOs are via normal bus read and
+ write cycles in response to polling of the status registers and/or interrupts.
+
+ [2:0] Frame Check Sequence Select - This field selects the optional frame check sequence (FCS) to be appended at the end of a transmitted frame.
+ When CRC is selected in COP, then no parity and 8-bit character length must be used. The selected FCS is transmitted as follows:
+ 1. Following the transmission of a FIFO'ed character tagged with the 'send EOM' command.
+ 2. If underrun control (TPR[7:6]) is programmed for TEOM, upon occurrence of an underrun.
+ 3. If TEOM on zero count or done (TPR[4]) is asserted and the counter/timer is counting transmitted characters, after transmission of the character which
+ causes the counter to reach zero count.
+ 4. In DMA mode with TEOM on zero count or done (TPR[4]) set, after transmission of a character if DONEN is asserted when that character was loaded into the
+ TX FIFO by the DMA controller.
+
+ 000 - No frame check sequence.
+ 001 - Reserved
+ 010 - LRC8: Divisor ~ x8+ 1, dividend preset to zeros. The TX sends the calculated LRC non-inverted. The RX indicates an error if the computed LRC is
+ not equal to O. Valid for COP modes only.
+ 011 - LRC8: Divisor ~ x8+ 1, dividend preset to ones. The TX sends the calculated LRC non-inverted. The RX indicates
+ an error if the computed LRC is not equal to O. Valid for COP modes only.
+ 100 - CRCI6: Divisor ~ x16+x15+x2+1, dividend preset to zeros. The TX sends the calculated CRC non-inverted. The RX indicates an error if the
+ computed CRC is not equal to O. Not valid for ASYNC mode.
+ 101 - CRCI6: Divisor ~ x16+x15+x2+1, dividend preset to ones. The TX sends the calculated CRC non-inverted. The RX indicates an error if the
+ computed CRC is not equal to O. Not valid for ASYNC mode.
+ 110 - CRC-CCITT: Divisor ~ x16+x12+x5+1, dividend preset to zeros. The TX sends the calculated CRC non-inverted. The RX indicates an error if the
+ computed CRC is not equal to O. Not valid for ASYNC mode.
+ 111 CRC-CCITT: Divisor ~ x16+x12+x5+1, dividend preset to ones. The TX sends the calculated CRC inverted. The RX indicates an error if the computed
+ CRC is not equal to H' FOB8'. Not valid for ASYNC mode.
+*/
+void duscc_channel::do_dusccreg_cmr2_w(UINT8 data)
+{
+ LOG(("%s(%02x)\n", FUNCNAME, data));
+ m_cmr2 = data;
+ LOG(("- Preparing for %s driven transfers\n", (m_cmr2 & REG_CMR2_DTI_MASK) == REG_CMR2_DTI_NODMA ? "polled or interrupt" : "dma"));
+ 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; }
+
+/* Transmitter Parameter Register (TPRA, TPRB)
+ SYNC mode
+ [7:6] Underrun Control - In BOP and COP modes, this field selects the transmitter response in the event of an underrun (i.e., the TX FIFO is empty).
+ 00 - Normal end of message termination. In BOP, the transmitter sends the FCS (if selected by CMR2[2:011 followed by a FLAG and then either MARKs or
+ FLAGs, as specified by [5]. In COP, the transmitter sends the FCS (if selected by CMR2[2:0]) and then either MARKs or SYNs, as specified by [5].
+ 01 - Reserved.
+ l0 - in BOP, the transmitter sends an ABORT (11111111) and then places the TXD output in a marking condition until receipt of further instructions.
+ In COP, the transmitter places the TXD output in a marking condition until receipt of further instructions.
+ 11 - In BOP, the transmitter sends an ABORT (11111111) and then sends FLAGs until receipt of further instructions. In COP, the transmitter sends
+ SYNs until receipt of further instructions.
+ [5] Idle - In BOP and COP modes, this bit selects the transmitter output during idle. Idle is defined as the state following a normal end of message until
+ receipt of the next transmitter command.
+ 0 - Idle in marking condition.
+ 1 - Idle sending SYNs (COP) or FLAGs (BOP).
+ [4] Transmit EOM on Zero Count or Done - In BOP and COP modes, the assertion of this bit causes the end of message (FCS in COP, FCS-FLAG in BOP) to be transmitted
+ upon the following events:
+ 1. If the counterltimer is counting transmitted characters, after transmission of the character which causes the counter to reach zero count. (DONEN is also asserted
+ as an output if the channel is in a DMA operation.)
+ 2. If the channel is operating in DMA mode, after transmission of a character if DONEN was asserted when that character was loaded into the TX FIFO by the DMA controller.
+
+ ASYNC mode
+ [7:4] Stop Bits per Character - In ASYNC mode, this field programs the length of the stop bit appended to the transmitted character
+ Stop bit lengths of 9/16 to 1 and 1-9/16 to 2 bits, in increments of 1/16 bit, can be programmed for character lengths of 6, 7, and 8 bits.
+ For a character length of 5 bits, 1-1/16 to 2 stop bits can be programmed in increments of 1/16 bit. The receiver only checks for a 'mark'
+ condition at the center of the first stop bit position (one bit time after the last data bit, or after the parity bit if parity is enabled) in all cases.
+ If an external 1 X clock is used for the transmitter, [7) = 0 selects one stop bit and [7) = 1 selects two stop bits to be transmitted.
+ If Manchester, NRZI, or FM data encoding is selected, only integral stop bit lengths should be used.
+ [3] Transmitter Request-to-Send Control - This bit controls the deactivation of the RTS_N output by the transmitter
+ 0 - RTS_N is not affected by status of transmitter.
+ 1 - RTS_N changes state as a function of transmitter status.
+ [2] Clear-ta-Send Enable Transmitter - The state of this bit determines if the CTS N input controls the operation of the channels transmitter
+ The duration of CTS level change is described in the discussion of ICTSR[4).
+ 0 - CTS_N has no affect on the transmitter.
+ 1 - CTS_N affects the state of the transmitter.
+ [1:0] Transmitted Bits per Character - This field selects the number of data bits per character to be transmitted. The character length does not
+ include the start, parity, and stop bits in ASYNC or the parity bit in COP. In BOP modes the character length for the address and control
+ fields is always 8 bits, and the value of this field only applies to the information (I) field, except for the last character of the I field,
+ whose length is specified by OMR[7:5).
+*/
+void duscc_channel::do_dusccreg_tpr_w(UINT8 data)
+{
+ LOG(("%s(%02x) Setting up Transmit Parameters\n", FUNCNAME, data));
+ m_tpr = data;
+ LOG(("- RTS %u\n", (m_tpr & REG_TPR_RTS) ? 1 : 0));
+ LOG(("- CTS %u\n", (m_tpr & REG_TPR_CTS) ? 1 : 0));
+ LOG(("- Stop Bits %s\n", stop_bits_tostring(get_stop_bits())));
+ LOG(("- Data Tx bits %u\n", get_tx_word_length()));
+
+ update_serial();
+ return;
+}
+
+/* Transmitter Timing Register (TTRA, TTRB)
+ [7] External Source - This bit selects the RTxC pin or the TRxC pin of the channel as the transmitter clock input when [6:4] specifies
+ external. When used for input, the selected pin must be programmed as an input in the PCR [4:3] or [2:0].
+ 0 External input form RTxC pin.
+ 1 External input from TRxC pin.
+ [6:4] Transmitter Clock Select - This field selects the clock for the transmitter.
+ 000 External clock from TRxC or RTXC at 1 X the shift (baud) rate.
+ 001 External clock from TRXC or RTxC at 16X the shift rate.
+ 010 Internal clock from the phase-locked loop at IX the bit rate. It should be used only in half-duplex operation since the
+ DPLL will periodically resync itself to the received data if in full-duplex operation.
+ 0ll Internal clock from the bit rate generator at 32X the shift rate. The clock signal is divided by two before use in the
+ transmitter which operates at 16X the baud rate. Rate selected by [3:0].
+ 100 Internal clock from counter/timer of other channel. The C/T should be programmed to produce a clock at 2X the shift rate.
+ 101 Internal clock from counter/timer of other channel. The C/T should be programmed to produce a clock at 32X the shift rate.
+ 110 Internal clock from the counter/timer of own channel. The C/T should be programmed to produce a clock at 2X the shift rate.
+ 111 Internal clock from the counter/timer of own channel. The C/T should be programmed to produce a clock at 32X the shift rate.
+ [3:0] Bit Rate Select - This field selects an output from the bit rate generator to be used by the transmitter circuits. The actual
+ frequency output from the BRG is 32X the bit rate shown in Table 5. With a crystal or external clock of 14.7456MHz the bit rates are as
+ given in Table 5 (this input is divided by two before being applied to the oscillator circuit).
+
+ Table 5. Receiver/Transmitter Baud Rates
+ [3:0] BIT RATE [3:0] BIT RATE
+ 0000 50 1000 1050
+ 0001 75 1001 1200
+ 0010 110 1010 2000
+ 0011 134.5 1011 2400
+ 0100 150 1100 4800
+ 0101 200 1101 9600
+ 0110 300 1110 19.2K
+ 0111 600 1111 38.4K
+*/
+void duscc_channel::do_dusccreg_ttr_w(UINT8 data)
+{
+ LOG(("%s(%02x) Setting up Transmit Timing\n", FUNCNAME, 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;
+ case REG_TTR_TXCLK_16XEXT: LOG(("16x External - not implemented\n")); break;
+ case REG_TTR_TXCLK_DPLL: LOG(("DPLL - not implemented\n")); break;
+ case REG_TTR_TXCLK_BRG:
+ LOG(("BRG\n"));
+ m_brg_tx_rate = get_baudrate(m_ttr & REG_TTR_BRG_RATE_MASK);
+ break;
+ case REG_TTR_TXCLK_2X_OTHER: LOG(("2x other channel C/T - not implemented\n")); break;
+ case REG_TTR_TXCLK_32X_OTHER: LOG(("32x other channel C/T - not implemented\n")); break;
+ case REG_TTR_TXCLK_2X_OWN: LOG(("2x own channel C/T - not implemented\n")); break;
+ 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();
+
+ return;
+}
+
+/* Receiver Parameter Resgister (RPRA, RPRB)
+ [7] SYN Stripping - This bit controls the DUSCC processing in COP modes of SYN 'character patterns' that occur after the initial
+ character synchronization. Refer to Detailed Operation of the receiver for details and definition of SYN 'patterns', and their
+ accumulation of FCS.
+ 0 Strip only leading SYN 'patterns' (i.e. before a message).
+ 1 Strip all SYN 'patterns' (including all odd DLE's in BISYNC transparent mode).
+
+ [6] Transfer Received FCS to FIFO - In BISYNC and BOP modes, the assertion of this bit causes the received FCS to be loaded into the
+ RxFIFO. When this bit is set, BOP mode operates correctly only if a minimum of two extra FLAGs (without shared zeros) are appended
+ to the frame. If the FCS is specified to be transferred to the FI FO, the EOM status bit will be tagged onto the last byte of the
+ FCS instead of to the last character of the message.
+ 0 Do not transfer FCS to RxFIFO.
+ 1 Transfer FCS to RxFIFO.
+
+ [5] Auto-Hunt and Pad Check (BISYNC) -In BISYNC rnode, the assertion of this bit causes the receiver to go into hunt for character
+ sync mode after detecting certain End-Ol-Message (EOM) characters. These are defined in the Detailed Operations section for
+ COP receiver operation. After the EOT and NAK sequences, the receiver also does a check for a closing PAD of four 1 s.
+ 0 Disable auto-hunt and PAD check.
+ 1 Enable auto-hunt and PAD check.
+ [5] Overrun Mode (BOP) - The state of this control bit deterrnines the operation of the receiver in the event of a data overrun, i.e.,
+ when a character is received while the RxFIFO and the Rx shift register are both full.
+ 0 The receiver terrninates receiving the current frame and goes into hunt phase, looking for a FLAG to be received.
+ 1 The receiver continues receiving the current frame. The overrunning character is lost. (The five characters already
+ assembled in the RxFIFO and Rx shift register are protected).
+
+ [4] Receiver Request-to-Send Control (ASYNC)
+ 0 Receiver does not control RTSN output.
+ 1 Receiver can negate RTSN output.
+ [4] External Sync (COP) - In COP single SYN mode, the assertion of this bit enables external character synchronization and
+ receipt of SYN patterns is not required. In order to use this feature, the DUSCC must be programmed to COP single SYN mode,
+ CMR1[2:0] = 110, which is used to set up the internal data paths. In all other respects, however, the external sync mode operation is
+ protocol transparent. A negative signal on the DCDN/SYNIN pin will cause the receiver to establish synchronization on the next rising
+ edge of the receiver clock. Character assembly will start at this edge with the RxD input pin considered to have the second bit of
+ data. The sync signal can then be negated. Receipt of the Active-High external sync input causes the SYN detect status bit
+ (RSR[2]) to be set and the SYNBOUTN pin to be asserted for one bit time. When this mode is enable, the internal SYN (COP mode)
+ detection and special character recognition (e.g., IDLE, STX, ETX, etc.) circuits are disabled. Character assembly begins as ~ in the
+ I-field with character length as programmed in RPR[I :)]. Incoming COP frames with parity specified optionally can have it stripped by
+ programming RPR[3J. The user must wait at least eight bit times after Rx is enabled before applying the SYNIN signal. This time is
+ required to flush the internal data paths. The receiver remains in this mode and further external sync pulses are ignored until the
+ receiver is disabled and then reenabled to resynchronize or to return to normal mode.
+ 0 External sync not enabled.
+ 1 External sync enabled.
+ Note that EXT SYNC and DCD ENABLE Rx cannot be asserted simultaneously since they use the same pin.
+
+ [3] Strip Parity - In COP and ASYNC modes with parity enabled, this bit controls whether the received parity bit is stripped from the
+ data placed in the receiver FIFO. It is valid ony for programmed character lengths of 5, 6, and 7 bits. If the bit is stripped, the
+ corresponding bit in the received data is set to zero.
+ 0 Transfer parity bit as received.
+ 1 Stop parity bit from data.
+ [3] All Parties Address - In BOP secondary modes, the assertion of this bit causes the receiver to 'wake-up' upon receipt of the
+ address H'FF' or H'FF, FF', for single- and dual-octet address modes, respectively, in addition to its normal station address. This
+ feature allows all stations to receive a message.
+ 0 Don't recognize all parties address.
+ 1 Recognize all parties address.
+
+ [2] DCD Enable Receiver - If this bit is asserted, the DCDN/SYNIN input must be Low in order for the receiver to operate.
+ If the input is negated (goes High) while a character is being received, the receiver terminates receipt of the current message
+ (this action in effect disables the receiver). If DCD is subsequently asserted, the receiver will search for the start bit, SYN pattern, or
+ FLAG, depending on the channel protocol. (Note that the change of input can be programmed to generate an interrupt; the duration of
+ the DCD level change is described in the discussion of the input and counter/timer status register (CTSR[5]).
+ 0 DCD not used to enabled receiver.
+ 1 DCD used to enabled receiver.
+ NOTE that EXT SYNC and DCD ENABLE Rx cannot be asserted simultaneously since they use the same pin.
+
+ [1:0] Received Bits per Character - This field selects the number of data bits per character to be assembled by the receiver. The
+ character length does not include the start, parity, and stop bits in the ASYNC or the parity bit in COP. In BOP modes, the character
+ length for the address and control field is always 8 bits, and the value of this field only applies to the information field. lithe number
+ of bits assembled for the last character of the l-field is less than the value programmed in this field, RCL not zero (RSR[O]) is asserted
+ and the actual number of bits received is given in TRSR[2:0].
+*/
+void duscc_channel::do_dusccreg_rpr_w(UINT8 data)
+{
+ LOG(("%s(%02x) Setting up Receiver Parameters\n", FUNCNAME, data));
+ m_rpr = data;
+ LOG(("- RTS output %u\n", (m_rpr & REG_RPR_RTS) ? 1 : 0));
+ LOG(("- Strip Parity %u\n", (m_rpr & REG_RPR_STRIP_PARITY && get_rx_word_length() < 8) ? 1 : 0));
+ LOG(("- DCD/SYNIN input %u\n", (m_rpr & REG_RPR_DCD) ? 1 : 0));
+ LOG(("- Data Rx bits %u\n", get_rx_word_length()));
+
+ update_serial();
+ return;
+}
+
+/* Receiver Timing Register (RTRA, RTRB)
+ [7] External Source - This M selects the RTxC pin or the TRxC pin of the channel as the receiver or DPLL clock input, when [6:4J
+ specifies external. When used for input, the selected pin must be programmed as an input in the PCR [4:3] or [2:0].
+ 0 External input form RTxC pin.
+ 1 External input form TRxC pin.
+ [6:4] Receiver Clock Select- This field selects the clock for the receiver.
+ 000 External clock from TRxC or RTxC at 1 X the shift (baud) rate.
+ 001 External clock fromTRxC or RTxC at 16X the shift rate. Used for ASYNC mode only.
+ 010 Internal clock from the bit rate generator at 32X the shift rate. Clock is divided by two before used by the receiver
+ logic, which operates at 16X the baud rate. Rate selected
+ by [3:0J. Used for ASYNC mode only.
+ 011 Internal clock from counter/timer of own channel. The CIT should be programmed to produce a clock at 32X the shift
+ rate. Clock is divided by two before use in the receiver logic. Used for ASYNC mode only.
+ 100 Internal clock from the digital phase- locked loop. The clock for the DPLL is a 64X clock from the crystal oscillator or
+ system clock input. (The input to the oscillator is divided by two).
+ 101 Internal clock from the digital phase- locked loop. The clock for the DPLL is an external 32X clock from the RTxC or
+ TRxC pin, as selected by [7J.
+ 110 Internal clock from the digital phase- locked loop. The clock for the DPLL is a 32X clock from the BRG. The frequency
+ is programmed by [3:0].
+ 111 Internal clock from the digital phase- locked loop. The clock for the DPLL is a 32X clock from the counter/timer of the
+ channel.
+ [3:0] Bit Rate Select- This field selects an output from the bit rate generator to be used by the receiver circuits. The actual frequency
+ output from the BRG is 32X the bit rate shown in Table 5.*/
+
+void duscc_channel::do_dusccreg_rtr_w(UINT8 data)
+{
+ LOG(("%s(%02x) Setting up Receiver Timing\n", FUNCNAME, data));
+ m_rtr = 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;
+ case REG_RTR_RXCLK_16XEXT: LOG(("16x External - not implemented\n")); break;
+ case REG_RTR_RXCLK_BRG:
+ LOG(("BRG\n"));
+ m_brg_rx_rate = get_baudrate(m_rtr & REG_RTR_BRG_RATE_MASK);
+ break;
+ case REG_RTR_RXCLK_CT: LOG(("C/T of channel - not implemented\n")); break;
+ case REG_RTR_RXCLK_DPLL_64X_X1: LOG(("DPLL, source = 64X X1/CLK - not implemented\n")); break;
+ case REG_RTR_RXCLK_DPLL_32X_EXT:LOG(("DPLL, source = 32X External - not implemented\n")); break;
+ case REG_RTR_RXCLK_DPLL_32X_BRG:LOG(("DPLL, source = 32X BRG - not implemented\n")); break;
+ 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();
+
+ 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; }
+
+/* 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
+ character in the information field. This length applies to:
+ - The character in the transmit FIFO accompanied by the FIFOed TEOM command.
+ - The character loaded into the FIFO by the DMA controller if DONEN is simultaneously asserted and TPR(4) is asserted.
+ - The character loaded into the FIFO which causes the counter to reach zero count when TPR[4J is asserted.
+ The length of all other characters in the frame's information field is selected by TPR[I :OJ. If this field is 111,
+ the number of bits in the last character is the same as programmed in TPR[1:0].
+ [4] TxRDY Activate Mode -
+ 0 FIFO not full. The channel's TxRDY status bit is asserted each time a character is transferred from the transmit FIFO
+ to the transmit shift register. If not reset by the CPU, TxRDY remains asserted until the FIFO is full, at which time
+ it is automatically negated.
+ 1 FIFO empty. The channel's TxRDY status bit is asserted when a character transfer from the transmit FIFO to the
+ transmit shift register causes the FI FO to become empty. If not reset by the CPU, TxRDY remains asserted until the
+ FIFO is full, at which time it is negated.
+ If the TxRDY status bit is reset by the CPU, it will remain negated regardless of the current state of the transmit
+ FIFO, until it is asserted again due to the occurrence of one of the above conditions.
+ [3] RxRDY Activate Mode -
+ 0 FIFO not empty. The channel's RxRDY status bit is asserted each time a character is transferred from the
+ receive shift register to the receive FIFO. If not reset by the CPU, RxRDY remains asserted until the receive FIFO is
+ empty, at which time it is automatically negated.
+ 1 FIFO full. The channel's RxRDY status bit is asserted when a character transfer from the receive shift register to the
+ receive FIFO causes the FIFO to become full. If not reset by the CPU, RxRDY reamins asserted until the FIFO is empty,
+ at which time it is negated.
+ The RxRDY status bit will also be asserted, regardless of the receiver FIFO full condition, when an end-of-message
+ character is loaded in the RxFIFO (BOP/BISYNC), when a BREAK condition (ASYNC mode) is detected in RSR[2), or
+ when the counterltimer is programmed to count received characters and the character which causes it to reach zero
+ is loaded in the FIFO (all modes). If reset by the CPU, the RxRDY status bit will remain negated, regardless of the
+ current state of the receiver FIFO, until it is asserted again due to one of the above conditions.
+ [2] General Purpose Output 2 -
+ This general purpose bit is used to control the TxDRQN/GP02lRTSN pin, when it is used as an output. The output is
+ High when the bit is a 0 and is Low when the bit is a 1.
+ [1] General Purpose Output 1 - This bit is used to control the RTxDRQN/GPOl N output, which is a general purpose output
+ when the channel is not in DMA mode. The output is High when the bit is a 0 and is Low when the bit is a 1.
+ [0] Request-to-Send Output - This bit controls the TxDRQN/GP02N/RTSN and SYNOUTN/RTSN pin, when either is
+ used as a RTS output. The output is High when the bit is a 0 and is Low when the bit is a 1.
+*/
+void duscc_channel::do_dusccreg_omr_w(UINT8 data)
+{
+ LOG(("%s(%02x) Output and Miscellaneous Register\n", FUNCNAME, data));
+ m_omr = data;
+ LOG(("- Tx Residual Character Length is "));
+ if ((m_omr & REG_OMR_TXRCL_MASK) == REG_OMR_TXRCL_8BIT)
+ LOG(("determined by TPR[1:0], the Transmitter Parameter Register\n"));
+ else
+ LOG(("%u bits\n", (((m_omr & REG_OMR_TXRCL_MASK) >> 5) & 0x07) + 1));
+ LOG(("- TxRDY activated by %s\n", m_omr & REG_OMR_TXRDY_ACTIVATED ? "FIFO empty" : "FIFO not full"));
+ LOG(("- RxRDY activated by %s\n", m_omr & REG_OMR_RXRDY_ACTIVATED ? "FIFO full" : "FIFO not empty"));
+ LOG(("- GP02, if configured as output, is: %u\n", m_omr & REG_OMR_GP02 ? 0 : 1));
+ LOG(("- GP01, if configured as output, is: %u\n", m_omr & REG_OMR_GP01 ? 0 : 1));
+ LOG(("- RTS, either pin if configured as output, is: %u\n", m_omr & REG_OMR_RTS ? 0 : 1));
+ return;
+}
+
+/* Pin Configuration Register (PCRA, PCRB)
+ This register selects the functions for multipurpose 1/0 pins.
+ [7] X2IIDC - This bit is defined only for PCRA. It is not used in PCRB.
+ 0 The X2/IDCN pin is used as a crystal connection.
+ 1 The X2/IDCN pin is the interrupt daisy chain output.
+ [6] GP02/RTS - The function of this pin is programmable only when not operating in full-duplex DMA mode.
+ 0 The TxDRQN/GP02N/RTSN pin is a general purpose output. It is Low when OMR[2] is a 1 and High when OMR[2] is a O.
+ 1 The pin is a request-to-send output The logical stale of the pin is controlled by OMR[O]. When OMR[O] is set, the output is Low.
+ [5] SYNOUT/RTS -
+ 0 The SYNOUTN/RTSN pin is an active-Low output which is asserted one bit time after a SYN pattern (COP modes) in HSRH/HSRL or FLAG
+ (BOP modes) is detected in CCSR.The output remains asserted for one receiver clock period.
+ 1 The pin is a request-to-send output The,logical state of the pin Is controlled by OMR[O] when OMR[O] is set, the output is Low.
+ [4:3] RTxC-
+ 00 The pin is an input. It must be programmed for input when used as the input for the receiver or transmitter clock, the DPLL, or the CIT.
+ 01 The pin is an output for the counterltimer.
+ 10 The pin is an output for the transmitter shift register clock.
+ 11 The pin is an output for the receiver shift register clock.
+ [2:0]TRxC-
+ 000 The pin is an input. It must be programmed for input when used as the input for the receiver or transmitter clock, the DPLL, or the CIT.
+ 001 The pin is an output from the crystal oscillator divided by two.
+ 010 The pin is an outputfor the DPLL output clock.
+ 011 The pin is an output for the counterltimer. Refer to CTCRAIB description.
+ 100 The pin is an output for the transmitter BRG at 16X the rate selected by TTR [3:0].
+ 101 The pin is an output for the receiver BRG at 16X the rate selected by RTR [3:0].
+ 110 The pin is an output for the transmitter shift register clock.
+ 111 The pin is an output for the receiver shift register clock.
+*/
+void duscc_channel::do_dusccreg_pcr_w(UINT8 data)
+{
+ LOG(("%s(%02x) Pin Configuration Register\n", FUNCNAME, data));
+ m_pcr = data;
+ LOG(("- The X2/IDCN pin is %s\n", m_index == duscc_device::CHANNEL_B ? "ignored for channel B" :
+ ((m_pcr & REG_PCR_X2_IDC) ? "crystal input" : "daisy chain interrupt output")));
+ 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 )
+ {
+ case REG_PCR_RTXC_INPUT: LOG(("- an input\n")); break;
+ case REG_PCR_RTXC_CNTR_OUT: LOG(("- a counter/timer output\n")); break;
+ case REG_PCR_RTXC_TXCLK_OUT:LOG(("- a Tx clock output\n")); break;
+ case REG_PCR_RTXC_RXCLK_OUT:LOG(("- a Rx clock output\n")); break;
+ default: LOG(("Wrong programming\n")); break; // Should never happen
+ }
+ LOG(("- The TRxC pin is "));
+ switch( m_pcr & REG_PCR_TRXC_MASK )
+ {
+ case REG_PCR_TRXC_INPUT: LOG(("- an input\n")); break;
+ case REG_PCR_TRXC_CRYST_OUT:LOG(("- a crystal/2 output\n")); break;
+ case REG_PCR_TRXC_DPLL_OUT: LOG(("- a DPLL output\n")); break;
+ case REG_PCR_TRXC_CNTR_OUT: LOG(("- a counter/timer output\n")); break;
+ case REG_PCR_TRXC_TXBRG_OUT:LOG(("- a Tx BRG output\n")); break;
+ case REG_PCR_TRXC_RXBRG_OUT:LOG(("- a Rx BRG output\n")); break;
+ case REG_PCR_TRXC_TXCLK_OUT:LOG(("- a Tx CLK output\n")); break;
+ case REG_PCR_TRXC_RXCLK_OUT:LOG(("- a Rx CLK output\n")); break;
+ default: LOG(("Wrong programming\n")); break; // Should never happen
+ }
+
+#endif
+
+ return;
+}
+
+/*
+ * Commands to the DUSCC are entered through the CCR channel command register.
+ *
+ * TODO:
+ * - support enable/disable of Tx/Rx using m_tra/m_rcv respectivelly
+ */
+void duscc_channel::do_dusccreg_ccr_w(UINT8 data)
+{
+ m_ccr = data;
+ LOG(("%s\n", FUNCNAME));
+ switch(m_ccr)
+ {
+
+ // TRANSMITTER COMMANDS
+
+ /* Reset transmitter. Causes the transmitter to cease operation immediately.
+ The transmit FIFO is cleared and the TxD output goes into the marking state.
+ Also clears the transmitter status bits (TRSR[7:4]) and resets the TxRDY
+ status bit (GSR[I] or GSR[5] for Channels A and B, respectively).
+ The counter/timer and other registers are not affected*/
+ case REG_CCR_RESET_TX: LOG(("- Reset Tx\n"));
+ 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);
+ 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);
+ m_tra = 1;
+ set_tra_rate(m_brg_tx_rate);
+ break;
+
+ /* Disable transmitter. Terminates transmitter operation and places the TXD output in the
+ marking state at the next occurrence of a transmit FIFO empty condition. All characters
+ currently in the FIFO, or any loaded subsequently prior to attaining an empty condition,
+ will be transmitted.
+ TODO: let all the chararcters be transmitted before shutting down shifter */
+ 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);
+ break;
+
+ // RECEIVER COMMANDS
+
+ /* Reset Receiver. Causes the receiver to cease operation, clears the receiver FIFO,
+ clears the data path, and clears the receiver status (RSR[7:0], TRSR[3:0], and either
+ GSR[O] or GSR[4] for Channels A and B, respectively). The counter/timer and other
+ registers are not affected.*/
+ case REG_CCR_RESET_RX: LOG(("- Reset Rx\n"));
+ set_rcv_rate(0);
+ 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);
+ break;
+
+ /* Enable receiver. Causes receiver operation to begin, conditioned by the state of the DCD
+ ENABLED Rx bit, RPR[2]. Receiver goes into START, SYN, or FLAG search mode depending on
+ channel protocol mode. Has no effect if invoked when the receiver has previously been enabled.*/
+ 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);
+ break;
+ default: LOG((" - command %02x not implemented yet\n", data));
+ }
+ return;
+}
+
+void duscc_channel::do_dusccreg_txfifo_w(UINT8 data)
+{
+ LOG(("%s(%02x)'%c'\n", FUNCNAME,data, isalnum(data) ? data : ' '));
+ LOG((" - TX wp:%d rp:%d sz:%d\n", m_tx_fifo_wp, m_tx_fifo_rp, m_tx_fifo_sz));
+
+ /* Tx FIFO is full or...? */
+ if (m_tx_fifo_wp + 1 == m_tx_fifo_rp || ( (m_tx_fifo_wp + 1 == m_tx_fifo_sz) && (m_tx_fifo_rp == 0) ))
+ {
+ logerror("- TX FIFO is full, discarding data\n");
+ LOG(("- TX FIFO is full, discarding data\n"));
+ }
+ 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;
+ }
+ }
+
+ /* Transmitter enabled? */
+ if ( m_tra == 1 )
+ {
+ if ( is_transmit_register_empty()) // Is the shift register loaded?
+ {
+ LOG(("- Setting up transmitter\n"));
+ transmit_register_setup(m_tx_data_fifo[m_tx_fifo_rp]); // Load the shift register, reload is done in tra_complete()
+ m_tx_fifo_rp_step();
+ }
+ }
+ // 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);
+ }
+ else
+ {
+ 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; }
+
+/* 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_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; }
+
+//-------------------------------------------------
+// control_read - read register
+//-------------------------------------------------
+UINT8 duscc_channel::read(offs_t &offset)
+{
+ UINT8 data = 0;
+ int reg = offset | m_a7;
+
+ 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;
+ default:
+ logerror(" \"%s\" %s: %c : Unsupported RRx register:%02x\n", m_owner->tag(), FUNCNAME, 'A' + m_index, reg);
+ }
+
+ //LOG(("%s \"%s\": %c : Register R%d read '%02x'\n", FUNCNAME, m_owner->tag(), 'A' + m_index, reg, data));
+ return data;
+}
+
+//-------------------------------------------------
+// write - write register
+//-------------------------------------------------
+
+void duscc_channel::write(UINT8 data, offs_t &offset)
+//WRITE8_MEMBER( duscc_channel::write)
+{
+ int reg = offset | m_a7;
+
+ 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;
+
+ default:
+ logerror(" \"%s\" %s: %c : Unsupported WRx register:%02x(%02x)\n", m_owner->tag(), FUNCNAME, 'A' + m_index, reg, data);
+ }
+}
+
+/* Get data from top of fifo data but restore read pointer in case of exit latch lock */
+UINT8 duscc_channel::m_rx_fifo_rp_data()
+{
+ UINT8 data;
+ UINT8 old_rp = m_rx_fifo_rp;
+ m_rx_fifo_rp_step();
+ data = m_rx_data_fifo[m_rx_fifo_rp];
+ m_rx_fifo_rp = old_rp;
+
+ return data;
+}
+
+/* Step read pointer */
+void duscc_channel::m_rx_fifo_rp_step()
+{
+ m_rx_fifo_rp++;
+ if (m_rx_fifo_rp >= m_rx_fifo_sz)
+ {
+ m_rx_fifo_rp = 0;
+ }
+
+ // check if FIFO is empty
+ 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);
+ }
+}
+
+/* Step TX read pointer */
+void duscc_channel::m_tx_fifo_rp_step()
+{
+ m_tx_fifo_rp++;
+ if (m_tx_fifo_rp >= m_tx_fifo_sz)
+ {
+ m_tx_fifo_rp = 0;
+ }
+}
+
+//-------------------------------------------------
+// receive_data - receive data word into fifo
+//-------------------------------------------------
+
+void duscc_channel::receive_data(UINT8 data)
+{
+ LOG(("\"%s\": %c : Receive Data Byte '%02x'\n", m_owner->tag(), 'A' + m_index, data));
+#
+ if (m_rx_fifo_wp + 1 == m_rx_fifo_rp || ( (m_rx_fifo_wp + 1 == m_rx_fifo_sz) && (m_rx_fifo_rp == 0) ))
+ {
+ // receive overrun error detected
+ m_rsr |= REG_RSR_OVERRUN_ERROR;
+ 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_rx_fifo_wp++;
+ if (m_rx_fifo_wp >= m_rx_fifo_sz)
+ {
+ m_rx_fifo_wp = 0;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// cts_w - clear to send handler
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( duscc_channel::cts_w )
+{
+ LOG(("\"%s\" %s: %c : CTS %u\n", m_owner->tag(), FUNCNAME, 'A' + m_index, state));
+
+ if (m_cts != state)
+ {
+ // enable transmitter if in auto enables mode
+ if (!state)
+ {
+ m_ictsr |= REG_ICTSR_DELTA_CTS;
+ }
+ else
+ {
+ m_ictsr &= ~REG_ICTSR_DELTA_CTS;
+ }
+
+ 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);
+ }
+
+ // set clear to send
+ m_cts = state;
+ }
+}
+
+
+//-------------------------------------------------
+// dcd_w - data carrier detected handler
+//-------------------------------------------------
+WRITE_LINE_MEMBER( duscc_channel::dcd_w )
+{
+ LOG(("\"%s\" %s: %c : DCD %u - not implemented\n", m_owner->tag(), FUNCNAME, 'A' + m_index, state));
+#if 0
+
+ if (m_dcd != state)
+ {
+ // enable receiver if in auto enables mode
+ if (!state)
+ if (reg & REG_AUTO_ENABLES)
+ {
+ reg |= REG_RX_ENABLE;
+ }
+
+ // set data carrier detect
+ m_dcd = state;
+ }
+#endif
+}
+
+//-------------------------------------------------
+// ri_w - ring indicator handler
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( duscc_channel::ri_w )
+{
+ LOG(("\"%s\" %s: %c : RI %u - not implemented\n", m_owner->tag(), FUNCNAME, 'A' + m_index, state));
+#if 0
+ if (m_ri != state)
+ {
+ // set ring indicator state
+ m_ri = state;
+ }
+#endif
+}
+
+//-------------------------------------------------
+// sync_w - sync handler
+//-------------------------------------------------
+WRITE_LINE_MEMBER( duscc_channel::sync_w )
+{
+ LOG(("\"%s\" %s: %c : SYNC %u - not implemented\n", m_owner->tag(), FUNCNAME, 'A' + m_index, state));
+}
+
+//-------------------------------------------------
+// rxc_w - receive clock
+//-------------------------------------------------
+WRITE_LINE_MEMBER( duscc_channel::rxc_w )
+{
+ LOG(("\"%s\" %s: %c : RXC %u - not implemented\n", m_owner->tag(), FUNCNAME, 'A' + m_index, state));
+}
+
+//-------------------------------------------------
+// txc_w - transmit clock
+//-------------------------------------------------
+WRITE_LINE_MEMBER( duscc_channel::txc_w )
+{
+ LOG(("\"%s\" %s: %c : TXC %u - not implemented\n", m_owner->tag(), FUNCNAME, 'A' + m_index, state));
+}
+
+//-------------------------------------------------
+// update_serial -
+//-------------------------------------------------
+void duscc_channel::update_serial()
+{
+ int data_bit_count = get_rx_word_length();
+ stop_bits_t stop_bits = get_stop_bits();
+ parity_t parity;
+
+ if ((m_cmr1 & REG_CMR1_PMMODE_MASK) == REG_CMR1_PMMODE_PARITY)
+ {
+ if ( (m_cmr1 & REG_CMR1_PARITY) == 0)
+ parity = PARITY_EVEN;
+ else
+ parity = PARITY_ODD;
+ }
+ else
+ parity = PARITY_NONE;
+
+ LOG((LLFORMAT " %s() \"%s \"Channel %c setting data frame %d+%d%c%d\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, 1,
+ data_bit_count, parity == PARITY_NONE ? 'N' : parity == PARITY_EVEN ? 'E' : 'O', (stop_bits + 1) / 2));
+
+ set_data_frame(1, data_bit_count, parity, stop_bits);
+
+ int clocks = get_rx_clock_mode();
+
+ if (m_rxc > 0)
+ {
+ set_rcv_rate(m_rxc / clocks);
+ LOG((" - Receiver clock: %d mode: %d rate: %d/%xh\n", m_rxc, clocks, m_rxc / clocks, m_rxc / clocks));
+ }
+
+ clocks = get_tx_clock_mode();
+ if (m_txc > 0)
+ {
+ set_tra_rate(m_txc / clocks);
+ LOG((" - Transmit clock: %d mode: %d rate: %d/%xh\n", m_rxc, clocks, m_rxc / clocks, m_rxc / clocks));
+ }
+
+ if (m_brg_rx_rate != 0)
+ {
+ if (m_brg_rx_rate == 1) m_brg_rx_rate = 0; // BRG beeing disabled
+ set_rcv_rate(m_brg_rx_rate);
+ LOG((" - Baud Rate Generator: %d mode: RX:%dx\n", m_brg_rx_rate, get_rx_clock_mode()));
+ }
+ if (m_brg_tx_rate != 0)
+ {
+ if (m_brg_tx_rate == 1) m_brg_tx_rate = 0; // BRG beeing disabled
+ set_tra_rate(m_brg_tx_rate);
+ LOG((" - Baud Rate Generator: %d mode: TX:%dx\n", m_brg_tx_rate, get_tx_clock_mode()));
+ }
+}
+
+//-------------------------------------------------
+// set_dtr -
+//-------------------------------------------------
+void duscc_channel::set_dtr(int state)
+{
+ LOG(("%s(%d)\n", FUNCNAME, state));
+ m_dtr = state;
+
+ if (m_index == duscc_device::CHANNEL_A)
+ m_uart->m_out_dtra_cb(m_dtr);
+ else
+ m_uart->m_out_dtrb_cb(m_dtr);
+}
+
+
+
+//-------------------------------------------------
+// write_rx - called by terminal through rs232/diserial
+// when character is sent to board
+//-------------------------------------------------
+WRITE_LINE_MEMBER(duscc_channel::write_rx)
+{
+ m_rxd = state;
+ //only use rx_w when self-clocked
+ if(m_rxc != 0 || m_brg_rx_rate != 0)
+ device_serial_interface::rx_w(state);
+}
diff --git a/src/devices/machine/scnxx562.h b/src/devices/machine/scnxx562.h
new file mode 100644
index 00000000000..917f816228a
--- /dev/null
+++ b/src/devices/machine/scnxx562.h
@@ -0,0 +1,698 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+/***************************************************************************
+
+ Philips DUSCC - Dual Serial Communications Controller emulation
+
+****************************************************************************
+
+ Chan B Chan A Chan B Chan A
+ ======= _____ _____ ======== ======= _____ _____ ========
+ IACKN 1|* \_/ |48 VCC IACKN 1|* \_/ |48 VDD
+ A3 2| |47 A4 A3 2| |47 A4
+ A2 3| |46 A5 A2 3| |46 A5
+ A1 4| |45 A6 A1 4| |45 A6
+ RTxDAK/GPI1 5| |44 RTxDAK/GPI1 5| |44 RTxDAK/GP1
+ IRQN 6| |43 X1/CLK IRQN 6| |43 X1/CLK
+ RDYN 7| |42 X2 RESETN 7| |42 X2
+ RTS/SYNOUT 8| |41 RTS/SYNOUT 8| |41 RTS/SYNOUT
+ TRxC 9| |40 TRxC TRxC 9| |40 TRxC
+ RTxC 10| |39 RTxC RTxC 10| |39 RTxC
+ DCD/SYNI 11| |38 DCD/SYNI 11| |38 DCD/SYNI
+ RxD 12| |37 RxD RxD 12| |37 RxD
+ TxD 13| SCN26562 |36 TxD TxD 13| SCN68562 |36 TxD
+ TxDAK/GPI2 14| SCN26C562 |35 TxDAK/GPI2 14| SCN68C562 |35 TxDAK/GPI2
+ RTxDRQ/GPO1 15| |34 RTxDRQ/GPO1 15| |34 RTxDRQ/GPO1
+ TxDRQ/RTS/GPO2 16| |33 TxDRQ/RTS/GPO2 16| |33 TxDRQ/RTS/GPO2
+ CTS/LC 17| |32 CTS/LC CTS/LC 17| |32 CTS/LC
+ D7 18| |31 D0 D7 18| |31 D0
+ D6 19| |30 D1 D6 19| |30 D1
+ D5 20| |29 D2 D5 20| |29 D2
+ D4 21| |28 D3 D4 21| |28 D3
+ RDN 22| |27 EOPN DTACKN 22| |27 DONEN
+ RESETN 23| |26 WRN DTCN 23| |26 R/WN
+ GND 24|_____________|25 CEN CND 24|_____________|25 CSN
+ Intel Bus Motorola Bus
+
+***************************************************************************/
+
+#ifndef __SCNXX562_H__
+#define __SCNXX562_H__
+
+#include "emu.h"
+
+//**************************************************************************
+// DEVICE CONFIGURATION MACROS
+//**************************************************************************
+
+#define LOCAL_BRG 0
+
+/* Variant ADD macros - use the right one to enable the right feature set! */
+#define MCFG_DUSCC26562_ADD(_tag, _clock, _rxa, _txa, _rxb, _txb) \
+ MCFG_DEVICE_ADD(_tag, DUSCC26562, _clock) \
+ MCFG_DUSCC_OFFSETS(_rxa, _txa, _rxb, _txb)
+
+#define MCFG_DUSCC26C562_ADD(_tag, _clock, _rxa, _txa, _rxb, _txb) \
+ MCFG_DEVICE_ADD(_tag, DUSCC26C562, _clock) \
+ MCFG_DUSCC_OFFSETS(_rxa, _txa, _rxb, _txb)
+
+#define MCFG_DUSCC68562_ADD(_tag, _clock, _rxa, _txa, _rxb, _txb) \
+ MCFG_DEVICE_ADD(_tag, DUSCC68562, _clock) \
+ MCFG_DUSCC_OFFSETS(_rxa, _txa, _rxb, _txb)
+
+#define MCFG_DUSCC68C562_ADD(_tag, _clock, _rxa, _txa, _rxb, _txb) \
+ MCFG_DEVICE_ADD(_tag, DUSCC68C562, _clock) \
+ MCFG_DUSCC_OFFSETS(_rxa, _txa, _rxb, _txb)
+
+/* generic ADD macro - Avoid using it directly, see above for correct variant instead */
+#define MCFG_DUSCC_ADD(_tag, _clock, _rxa, _txa, _rxb, _txb) \
+ MCFG_DEVICE_ADD(_tag, DUSCC, _clock) \
+ MCFG_DUSCC_OFFSETS(_rxa, _txa, _rxb, _txb)
+
+/* Generic macros */
+#define MCFG_DUSCC_OFFSETS(_rxa, _txa, _rxb, _txb) \
+ duscc_device::configure_channels(*device, _rxa, _txa, _rxb, _txb);
+
+// Port A callbacks
+#define MCFG_DUSCC_OUT_TXDA_CB(_devcb) \
+ devcb = &duscc_device::set_out_txda_callback(*device, DEVCB_##_devcb);
+
+#define MCFG_DUSCC_OUT_DTRA_CB(_devcb) \
+ devcb = &duscc_device::set_out_dtra_callback(*device, DEVCB_##_devcb);
+
+#define MCFG_DUSCC_OUT_RTSA_CB(_devcb) \
+ devcb = &duscc_device::set_out_rtsa_callback(*device, DEVCB_##_devcb);
+
+#define MCFG_DUSCC_OUT_SYNCA_CB(_devcb) \
+ devcb = &duscc_device::set_out_synca_callback(*device, DEVCB_##_devcb);
+
+// Port B callbacks
+#define MCFG_DUSCC_OUT_TXDB_CB(_devcb) \
+ devcb = &duscc_device::set_out_txdb_callback(*device, DEVCB_##_devcb);
+
+#define MCFG_DUSCC_OUT_DTRB_CB(_devcb) \
+ devcb = &duscc_device::set_out_dtrb_callback(*device, DEVCB_##_devcb);
+
+#define MCFG_DUSCC_OUT_RTSB_CB(_devcb) \
+ devcb = &duscc_device::set_out_rtsb_callback(*device, DEVCB_##_devcb);
+
+#define MCFG_DUSCC_OUT_SYNCB_CB(_devcb) \
+ devcb = &duscc_device::set_out_syncb_callback(*device, DEVCB_##_devcb);
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> duscc_channel
+
+class duscc_device;
+
+class duscc_channel : public device_t,
+ public device_serial_interface
+{
+ friend class duscc_device;
+
+public:
+ duscc_channel(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // 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;
+
+ // device_serial_interface overrides
+ virtual void tra_callback() override;
+ virtual void tra_complete() override;
+ virtual void rcv_callback() override;
+ virtual void rcv_complete() override;
+
+ // read register handlers
+ UINT8 do_dusccreg_cmr1_r();
+ UINT8 do_dusccreg_cmr2_r();
+ UINT8 do_dusccreg_s1r_r();
+ UINT8 do_dusccreg_s2r_r();
+ UINT8 do_dusccreg_tpr_r();
+ UINT8 do_dusccreg_ttr_r();
+ UINT8 do_dusccreg_rpr_r();
+ UINT8 do_dusccreg_rtr_r();
+ UINT8 do_dusccreg_ctprh_r();
+ UINT8 do_dusccreg_ctprl_r();
+ UINT8 do_dusccreg_ctcr_r();
+ UINT8 do_dusccreg_omr_r();
+ UINT8 do_dusccreg_cth_r();
+ UINT8 do_dusccreg_ctl_r();
+ UINT8 do_dusccreg_pcr_r();
+ UINT8 do_dusccreg_ccr_r();
+ UINT8 do_dusccreg_rxfifo_r();
+ UINT8 do_dusccreg_rsr_r();
+ UINT8 do_dusccreg_trsr_r();
+ UINT8 do_dusccreg_ictsr_r();
+ UINT8 do_dusccreg_gsr_r();
+ UINT8 do_dusccreg_ier_r();
+ UINT8 do_dusccreg_cid_r();
+ UINT8 do_dusccreg_ivr_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();
+ UINT8 do_dusccreg_ier3_r();
+ UINT8 do_dusccreg_trcr_r();
+ UINT8 do_dusccreg_rflr_r();
+ UINT8 do_dusccreg_ftlr_r();
+ UINT8 do_dusccreg_trmsr_r();
+ UINT8 do_dusccreg_telr_r();
+
+ // write register handlers
+ void do_dusccreg_cmr1_w(UINT8 data);
+ void do_dusccreg_cmr2_w(UINT8 data);
+ void do_dusccreg_s1r_w(UINT8 data);
+ void do_dusccreg_s2r_w(UINT8 data);
+ void do_dusccreg_tpr_w(UINT8 data);
+ void do_dusccreg_ttr_w(UINT8 data);
+ void do_dusccreg_rpr_w(UINT8 data);
+ void do_dusccreg_rtr_w(UINT8 data);
+ void do_dusccreg_ctprh_w(UINT8 data);
+ void do_dusccreg_ctprl_w(UINT8 data);
+ void do_dusccreg_ctcr_w(UINT8 data);
+ void do_dusccreg_omr_w(UINT8 data);
+ void do_dusccreg_pcr_w(UINT8 data);
+ void do_dusccreg_ccr_w(UINT8 data);
+ void do_dusccreg_txfifo_w(UINT8 data);
+ void do_dusccreg_rsr_w(UINT8 data);
+ void do_dusccreg_trsr_w(UINT8 data);
+ void do_dusccreg_ictsr_w(UINT8 data);
+ void do_dusccreg_gsr_w(UINT8 data);
+ void do_dusccreg_ier_w(UINT8 data);
+ // 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_mrr_w(UINT8 data);
+ void do_dusccreg_ier1_w(UINT8 data);
+ void do_dusccreg_ier2_w(UINT8 data);
+ void do_dusccreg_ier3_w(UINT8 data);
+ void do_dusccreg_trcr_w(UINT8 data);
+ void do_dusccreg_ftlr_w(UINT8 data);
+ void do_dusccreg_trmsr_w(UINT8 data);
+
+ UINT8 read(offs_t &offset);
+ void write(UINT8 data, offs_t &offset);
+
+ // UINT8 data_read();
+ // void data_write(UINT8 data);
+
+ void receive_data(UINT8 data);
+ void m_tx_fifo_rp_step();
+ void m_rx_fifo_rp_step();
+ UINT8 m_rx_fifo_rp_data();
+
+ DECLARE_WRITE_LINE_MEMBER( write_rx );
+ DECLARE_WRITE_LINE_MEMBER( cts_w );
+ DECLARE_WRITE_LINE_MEMBER( dcd_w );
+ DECLARE_WRITE_LINE_MEMBER( ri_w );
+ DECLARE_WRITE_LINE_MEMBER( rxc_w );
+ DECLARE_WRITE_LINE_MEMBER( txc_w );
+ DECLARE_WRITE_LINE_MEMBER( sync_w );
+
+ int m_rxc;
+ int m_txc;
+ int m_tra;
+ int m_rcv;
+
+ // Register state
+ UINT8 m_cmr1;
+ UINT8 m_cmr2;
+ UINT8 m_s1r;
+ UINT8 m_s2r;
+ UINT8 m_tpr;
+ UINT8 m_ttr;
+ UINT8 m_rpr;
+ UINT8 m_rtr;
+ UINT8 m_ctprh;
+ UINT8 m_ctprl;
+ UINT8 m_ctcr;
+ UINT8 m_omr;
+ UINT8 m_cth;
+ UINT8 m_ctl;
+ UINT8 m_pcr;
+ UINT8 m_ccr;
+ UINT8 m_txfifo[4];
+ UINT8 m_rxfifo[4];
+ UINT8 m_rsr;
+ UINT8 m_trsr;
+ UINT8 m_ictsr;
+ UINT8 m_gsr;
+ UINT8 m_ier;
+ // UINT8 m_rea;
+ UINT8 m_cid;
+ UINT8 m_ivr;
+ UINT8 m_icr;
+ // UINT8 m_sea;
+ UINT8 m_ivrm;
+ UINT8 m_mrr;
+ UINT8 m_ier1;
+ UINT8 m_ier2;
+ UINT8 m_ier3;
+ UINT8 m_trcr;
+ UINT8 m_rflr;
+ UINT8 m_ftlr;
+ UINT8 m_trmsr;
+ UINT8 m_telr;
+
+protected:
+ enum
+ {
+ INT_TRANSMIT = 0,
+ INT_EXTERNAL = 1,
+ INT_RECEIVE = 2,
+ INT_SPECIAL = 3
+ };
+
+ enum
+ {
+ REG_CCR_RESET_TX = 0x00,
+ REG_CCR_ENABLE_TX = 0x02,
+ REG_CCR_DISABLE_TX = 0x03,
+ REG_CCR_RESET_RX = 0x40,
+ REG_CCR_ENABLE_RX = 0x42,
+ REG_CCR_DISABLE_RX = 0x43
+ };
+
+ enum
+ {
+ REG_CMR1_PARITY = 0x20,
+ REG_CMR1_PMMODE_MASK = 0x18,
+ REG_CMR1_PMMODE_NONE = 0x00,
+ REG_CMR1_PMMODE_RES = 0x01,
+ REG_CMR1_PMMODE_PARITY = 0x10,
+ REG_CMR1_PMMODE_FORCED = 0x11,
+ REG_CMR1_CPMODE_MASK = 0x07,
+ REG_CMR1_CPMODE_ASYNC = 0x07
+ };
+
+ enum
+ {
+ REG_CMR2_DTI_MASK = 0x38,
+ REG_CMR2_DTI_NODMA = 0x38
+ };
+
+ enum
+ {
+ REG_RPR_DATA_BITS_MASK = 0x03,
+ REG_RPR_DATA_BITS_5BIT = 0x00,
+ REG_RPR_DATA_BITS_6BIT = 0x01,
+ REG_RPR_DATA_BITS_7BIT = 0x02,
+ REG_RPR_DATA_BITS_8BIT = 0x03,
+ REG_RPR_DCD = 0x04,
+ REG_RPR_STRIP_PARITY = 0x08,
+ REG_RPR_RTS = 0x10
+ };
+
+ enum
+ {
+ REG_TPR_DATA_BITS_MASK = 0x03,
+ REG_TPR_DATA_BITS_5BIT = 0x00,
+ REG_TPR_DATA_BITS_6BIT = 0x01,
+ REG_TPR_DATA_BITS_7BIT = 0x02,
+ REG_TPR_DATA_BITS_8BIT = 0x03,
+ REG_TPR_CTS = 0x04,
+ REG_TPR_RTS = 0x08,
+ REG_TPR_STOP_BITS_MASK = 0xf0
+ };
+
+ enum
+ {
+ REG_TTR_EXT = 0x80,
+ REG_TTR_TXCLK_MASK = 0x70,
+ REG_TTR_TXCLK_1XEXT = 0x00,
+ REG_TTR_TXCLK_16XEXT = 0x10,
+ REG_TTR_TXCLK_DPLL = 0x20,
+ REG_TTR_TXCLK_BRG = 0x30,
+ REG_TTR_TXCLK_2X_OTHER = 0x40,
+ REG_TTR_TXCLK_32X_OTHER = 0x50,
+ REG_TTR_TXCLK_2X_OWN = 0x60,
+ REG_TTR_TXCLK_32X_OWN = 0x70,
+ REG_TTR_BRG_RATE_MASK = 0x0f,
+ };
+
+ enum
+ {
+ REG_RTR_EXT = 0x80,
+ REG_RTR_RXCLK_MASK = 0x70,
+ REG_RTR_RXCLK_1XEXT = 0x00,
+ REG_RTR_RXCLK_16XEXT = 0x10,
+ REG_RTR_RXCLK_BRG = 0x20,
+ REG_RTR_RXCLK_CT = 0x30,
+ REG_RTR_RXCLK_DPLL_64X_X1 = 0x40,
+ REG_RTR_RXCLK_DPLL_32X_EXT = 0x50,
+ REG_RTR_RXCLK_DPLL_32X_BRG = 0x60,
+ REG_RTR_RXCLK_DPLL_32X_CT = 0x70,
+ REG_RTR_BRG_RATE_MASK = 0x0f,
+ };
+
+ enum
+ {
+ REG_PCR_X2_IDC = 0x80,
+ REG_PCR_GP02_RTS = 0x40,
+ REG_PCR_SYNOUT_RTS = 0x20,
+ REG_PCR_RTXC_MASK = 0x18,
+ REG_PCR_RTXC_INPUT = 0x00,
+ REG_PCR_RTXC_CNTR_OUT = 0x08,
+ REG_PCR_RTXC_TXCLK_OUT = 0x10,
+ REG_PCR_RTXC_RXCLK_OUT = 0x18,
+ REG_PCR_TRXC_MASK = 0x07,
+ REG_PCR_TRXC_INPUT = 0x00,
+ REG_PCR_TRXC_CRYST_OUT = 0x01,
+ REG_PCR_TRXC_DPLL_OUT = 0x02,
+ REG_PCR_TRXC_CNTR_OUT = 0x03,
+ REG_PCR_TRXC_TXBRG_OUT = 0x04,
+ REG_PCR_TRXC_RXBRG_OUT = 0x05,
+ REG_PCR_TRXC_TXCLK_OUT = 0x06,
+ REG_PCR_TRXC_RXCLK_OUT = 0x07,
+ };
+
+ enum
+ {
+ REG_OMR_TXRCL_MASK = 0xe0,
+ REG_OMR_TXRCL_8BIT = 0xe0,
+ REG_OMR_TXRDY_ACTIVATED = 0x10,
+ REG_OMR_RXRDY_ACTIVATED = 0x08,
+ REG_OMR_GP02 = 0x04,
+ REG_OMR_GP01 = 0x02,
+ REG_OMR_RTS = 0x01,
+ };
+
+ enum
+ {
+ REG_RSR_OVERRUN_ERROR = 0x20,
+ };
+
+ enum
+ {
+ REG_ICTSR_DELTA_CTS = 0x10,
+ REG_ICTSR_DCD = 0x08,
+ REG_ICTSR_CTS = 0x04,
+ };
+
+ 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,
+ };
+
+ // Register offsets, stripped from channel bit 0x20 but including A7 bit
+ enum
+ {
+ REG_CMR1 = 0x00,
+ REG_CMR2 = 0x01,
+ REG_S1R = 0x02,
+ REG_S2R = 0x03,
+ REG_TPR = 0x04,
+ REG_TTR = 0x05,
+ REG_RPR = 0x06,
+ REG_RTR = 0x07,
+ REG_CTPRH = 0x08,
+ REG_CTPRL = 0x09,
+ REG_CTCR = 0x0a,
+ REG_OMR = 0x0b,
+ REG_CTH = 0x0c,
+ REG_CTL = 0x0d,
+ REG_PCR = 0x0e,
+ REG_CCR = 0x0f,
+ REG_TXFIFO_0= 0x10,
+ REG_TXFIFO_1= 0x11,
+ REG_TXFIFO_2= 0x12,
+ REG_TXFIFO_3= 0x13,
+ REG_RXFIFO_0= 0x14,
+ REG_RXFIFO_1= 0x15,
+ REG_RXFIFO_2= 0x16,
+ REG_RXFIFO_3= 0x17,
+ REG_RSR = 0x18,
+ REG_TRSR = 0x19,
+ REG_ICTSR = 0x1a,
+ REG_GSR = 0x1b,
+ REG_IER = 0x1c,
+ REG_REA = 0x1d,
+ REG_CID = 0x1d,
+ REG_IVR = 0x1e,
+ REG_ICR = 0x1f,
+ REG_SEA = 0x1d,
+ REG_IVRM = 0x1e,
+ REG_MRR = 0x1f,
+ REG_IER1 = 0x42,
+ REG_IER2 = 0x43,
+ REG_IER3 = 0x45,
+ REG_TRCR = 0x47,
+ REG_RFLR = 0x4e,
+ REG_FTLR = 0x5c,
+ REG_TRMSR = 0x5e,
+ REG_TELR = 0x5f,
+ };
+
+ enum
+ {
+ TIMER_ID_BAUD,
+ TIMER_ID_XTAL,
+ TIMER_ID_RTXC,
+ TIMER_ID_TRXC
+ };
+
+ UINT16 m_brg_rx_rate;
+ UINT16 m_brg_tx_rate;
+ UINT16 m_brg_const;
+
+ // TODO: Implement the 14.4K, 56K and 64K bauds available on the CDUSCC
+ static unsigned int get_baudrate(unsigned int br)
+ {
+ switch (br)
+ {
+ case 0x00: return 50; break;
+ case 0x01: return 75; break;
+ case 0x02: return 110; break;
+ case 0x03: return 134; break;
+ case 0x04: return 150; break;
+ case 0x05: return 200; break;
+ case 0x06: return 300; break;
+ case 0x07: return 600; break;
+ case 0x08: return 1050; break;
+ case 0x09: return 1200; break;
+ case 0x0a: return 2000; break;
+ case 0x0b: return 2400; break;
+ case 0x0c: return 4800; break;
+ case 0x0d: return 9600; break;
+ case 0x0e: return 19200; break;
+ case 0x0f: return 38400; break;
+ };
+ return 0;
+ }
+
+ void update_serial();
+ void set_dtr(int state);
+ void set_rts(int state);
+
+ int get_tx_clock_mode();
+ int get_rx_clock_mode();
+ stop_bits_t get_stop_bits();
+ int get_rx_word_length();
+ int get_tx_word_length();
+
+ /* FIFOs and rx/tx status */
+ /* Receiver */
+ UINT8 m_rx_data_fifo[16]; // data FIFO
+ UINT8 m_rx_error_fifo[16]; // error FIFO
+ int m_rx_fifo_rp; // FIFO read pointer
+ int m_rx_fifo_wp; // FIFO write pointer
+ int m_rx_fifo_sz; // FIFO size
+ UINT8 m_rx_error; // current error
+
+ /* Transmitter */
+ UINT8 m_tx_data_fifo[16]; // data FIFO
+ UINT8 m_tx_error_fifo[16]; // error FIFO
+ int m_tx_fifo_rp; // FIFO read pointer
+ int m_tx_fifo_wp; // FIFO write pointer
+ int m_tx_fifo_sz; // FIFO size
+ UINT8 m_tx_error; // current error
+
+ int m_rx_clock; // receive clock pulse count
+ int m_rx_first; // first character received
+ int m_rx_break; // receive break condition
+ // UINT8 m_rx_rr0_latch; // read register 0 latched
+
+ int m_rxd;
+ int m_ri; // ring indicator latch
+ int m_cts; // clear to send latch
+ int m_dcd; // data carrier detect latch
+
+ // transmitter state
+ UINT8 m_tx_data; // transmit data register
+ int m_tx_clock; // transmit clock pulse count
+
+ int m_dtr; // data terminal ready
+ int m_rts; // request to send
+
+ // synchronous state
+ UINT16 m_sync; // sync character
+
+ int m_rcv_mode;
+ int m_index;
+ duscc_device *m_uart;
+
+ // CDUSCC specifics
+ int m_a7; // Access additional registers
+};
+
+
+// ======================> duscc_device
+
+
+class duscc_device : public device_t
+// ,public device_z80daisy_interface
+{
+ friend class duscc_channel;
+
+public:
+ // construction/destruction
+ 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);
+ duscc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ template<class _Object> static devcb_base &set_out_txda_callback(device_t &device, _Object object) { return downcast<duscc_device &>(device).m_out_txda_cb.set_callback(object); }
+ template<class _Object> static devcb_base &set_out_dtra_callback(device_t &device, _Object object) { return downcast<duscc_device &>(device).m_out_dtra_cb.set_callback(object); }
+ template<class _Object> static devcb_base &set_out_rtsa_callback(device_t &device, _Object object) { return downcast<duscc_device &>(device).m_out_rtsa_cb.set_callback(object); }
+ template<class _Object> static devcb_base &set_out_synca_callback(device_t &device, _Object object) { return downcast<duscc_device &>(device).m_out_synca_cb.set_callback(object); }
+
+ template<class _Object> static devcb_base &set_out_txdb_callback(device_t &device, _Object object) { return downcast<duscc_device &>(device).m_out_txdb_cb.set_callback(object); }
+ template<class _Object> static devcb_base &set_out_dtrb_callback(device_t &device, _Object object) { return downcast<duscc_device &>(device).m_out_dtrb_cb.set_callback(object); }
+ template<class _Object> static devcb_base &set_out_rtsb_callback(device_t &device, _Object object) { return downcast<duscc_device &>(device).m_out_rtsb_cb.set_callback(object); }
+ template<class _Object> static devcb_base &set_out_syncb_callback(device_t &device, _Object object) { return downcast<duscc_device &>(device).m_out_syncb_cb.set_callback(object); }
+
+ static void configure_channels(device_t &device, int rxa, int txa, int rxb, int txb)
+ {
+#if 0 // TODO: Fix this, need a way to set external rx/tx clocks for the channels
+ duscc_device &dev = downcast<duscc_device &>(device);
+ dev.m_chanA->m_rxc = rxa;
+ dev.m_chanA->m_txc = txa;
+ dev.m_chanB->m_rxc = rxb;
+ dev.m_chanB->m_txc = txb;
+#endif
+ }
+
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+
+ // interrupt acknowledge
+ // int m1_r();
+
+ DECLARE_WRITE_LINE_MEMBER( rxa_w ) { m_chanA->write_rx(state); }
+ DECLARE_WRITE_LINE_MEMBER( rxb_w ) { m_chanB->write_rx(state); }
+ DECLARE_WRITE_LINE_MEMBER( ctsa_w ) { m_chanA->cts_w(state); }
+ DECLARE_WRITE_LINE_MEMBER( ctsb_w ) { m_chanB->cts_w(state); }
+ DECLARE_WRITE_LINE_MEMBER( dcda_w ) { m_chanA->dcd_w(state); }
+ DECLARE_WRITE_LINE_MEMBER( dcdb_w ) { m_chanB->dcd_w(state); }
+ DECLARE_WRITE_LINE_MEMBER( ria_w ) { m_chanA->ri_w(state); }
+ DECLARE_WRITE_LINE_MEMBER( rib_w ) { m_chanB->ri_w(state); }
+#if 0
+ DECLARE_WRITE_LINE_MEMBER( rxca_w ) { m_chanA->rxc_w(state); }
+ DECLARE_WRITE_LINE_MEMBER( rxcb_w ) { m_chanB->rxc_w(state); }
+ DECLARE_WRITE_LINE_MEMBER( txca_w ) { m_chanA->txc_w(state); }
+ DECLARE_WRITE_LINE_MEMBER( txcb_w ) { m_chanB->txc_w(state); }
+ DECLARE_WRITE_LINE_MEMBER( rxtxcb_w ) { m_chanB->rxc_w(state); m_chanB->txc_w(state); }
+#endif
+ DECLARE_WRITE_LINE_MEMBER( synca_w ) { m_chanA->sync_w(state); }
+ DECLARE_WRITE_LINE_MEMBER( syncb_w ) { m_chanB->sync_w(state); }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual machine_config_constructor device_mconfig_additions() const override;
+
+ // internal interrupt management
+ void check_interrupts();
+ void reset_interrupts();
+ UINT8 modify_vector(UINT8 vect, int i, UINT8 src);
+ void trigger_interrupt(int index, int state);
+ int get_channel_index(duscc_channel *ch) { return (ch == m_chanA) ? 0 : 1; }
+
+ // Variants in the DUSCC family
+ enum
+ {
+ TYPE_DUSCC = 0x001,
+ TYPE_DUSCC26562 = 0x002,
+ TYPE_DUSCC26C562 = 0x004,
+ TYPE_DUSCC68562 = 0x008,
+ TYPE_DUSCC68C562 = 0x010,
+ };
+
+#define SET_NMOS ( duscc_device::TYPE_DUSCC26562 | duscc_device::TYPE_DUSCC68562 )
+#define SET_CMOS ( duscc_device::TYPE_DUSCC26C562 | duscc_device::TYPE_DUSCC68C562 )
+
+ enum
+ {
+ CHANNEL_A = 0,
+ CHANNEL_B
+ };
+
+ required_device<duscc_channel> m_chanA;
+ required_device<duscc_channel> m_chanB;
+
+ // internal state
+#if 0
+ int m_rxca;
+ int m_txca;
+ int m_rxcb;
+ int m_txcb;
+#endif
+
+ devcb_write_line m_out_txda_cb;
+ devcb_write_line m_out_dtra_cb;
+ devcb_write_line m_out_rtsa_cb;
+ devcb_write_line m_out_synca_cb;
+
+ devcb_write_line m_out_txdb_cb;
+ devcb_write_line m_out_dtrb_cb;
+ devcb_write_line m_out_rtsb_cb;
+ devcb_write_line m_out_syncb_cb;
+
+ int m_int_state[6]; // interrupt state
+
+ int m_variant;
+};
+
+// device type definition
+extern const device_type DUSCC;
+extern const device_type DUSCC_CHANNEL;
+extern const device_type DUSCC26562;
+extern const device_type DUSCC26C562;
+extern const device_type DUSCC68562;
+extern const device_type DUSCC68C562;
+
+class duscc26562_device : public duscc_device
+{
+public :
+ duscc26562_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class duscc26C562_device : public duscc_device
+{
+public :
+ duscc26C562_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class duscc68562_device : public duscc_device
+{
+public :
+ duscc68562_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class duscc68C562_device : public duscc_device
+{
+public :
+ duscc68C562_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+#endif // __SCNXX562_H__
diff --git a/src/mame/drivers/fccpu30.cpp b/src/mame/drivers/fccpu30.cpp
new file mode 100644
index 00000000000..2be0284abe7
--- /dev/null
+++ b/src/mame/drivers/fccpu30.cpp
@@ -0,0 +1,802 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+/***************************************************************************
+ *
+ * Force SYS68K CPU-30 VME SBC drivers
+ *
+ * 21/05/2016
+ *
+ * Thanks to Al Kossow his site http://www.bitsavers.org/ I got the information
+ * required to start the work with this driver.
+ *
+ * The driver is currently starting up and the Boot ROM asks for input do start FGA-002
+ * diagnostics and do SRAM setup, which it does. After that it jumps to zeroed memory
+ * and crashes so needs some more work to be useful
+ *
+ *
+ * ||
+ * || || CPU-30
+ * ||||--||_____________________________________________________________
+ * ||||--|| |
+ * || || _ |__
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | |VME|
+ * || | | |
+ * || | |P1 |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || |_| |
+ * || |___|
+ * || |
+ * || |
+ * || |
+ * || |
+ * || |
+ * || |
+ * || |
+ * || |
+ * || |___
+ * || _| |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | |VME|
+ * || | | |
+ * || | |P2 |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || |_| |
+ * || |___|
+ * || || +
+ * ||||--|| |
+ * ||||--||--------------------------------------------------------------+
+ * ||
+ *
+ * History of Force Computers
+ *---------------------------
+ *
+ * Misc links about Force Computes and this board:
+ *------------------------------------------------
+ * http://bitsavers.trailing-edge.com/pdf/forceComputers/CPU30/204030_CPU-30_R4_Technical_Reference_Oct96.pdf
+ * http://www.artisantg.com/info/P_wUovN.pdf
+ *
+ * Description(s)
+ * -------------
+ * CPU-30 has the following feature set
+ * - 16.7 or 25 MHz MC68030 enhanced 32-bit microprocessor
+ * - 16.7 or 25 MHz MC68882 floating-point coprocessor
+ * - 32-512 Kb of SRAM with battery backup
+ * - 4, 8, 16, or 32MB of shared DRAM, with byte parity
+ * - Up to 8Mb Flash memory
+ * - 128,256 or 512 Mb boot flash or upto 1Mb of boot OTP PROM
+ * - Double High (6U) VMEmodule
+ * - A32/D32 VMEbus master/slave interface with system controller function (VMEchip ASIC)
+ * - Ethernet transceiver interface (AM79C90)
+ * - SCSI bus interface with independent data bus on P2 connector (MB87033/34)
+ * - Flopyy disk interface on P2 connector (FCD37C65C)
+ * - Four serial ports (DUSCC SCN68562 x 2)
+ * - 20 bit digital i/o for user applications( 2 x 68230 PI/T )
+ * - Real-Time Clock with interrupt (72423)
+ * - 4-level requester, 7-level interrupter, and 7-level interrupt handler for VMEbus (VMEchip ASIC)
+ *
+ * NOTE: This driver currently mimics the CPU-30xyz configuration: 16MHz, 4Mb RAM, no parity, no ethernet (See TODO)
+ *
+ * Address Map
+ * --------------------------------------------------------------------------
+ * Range Decscription
+ * --------------------------------------------------------------------------
+ * 00000000-0xxFFFFF Shared DRAM D8-D32 xx=0x1F-0x03 for 32Mb-4Mb
+ * 0yy00000-FAFFFFFF VME A32 D8-D32 yy=xx+1
+ * FB000000-FBFEFFFF VME A24 D8-D32
+ * FBFF0000-FBFFFFFF VME A16 D8-D32
+ * FC000000-FCFEFFFF VME A24 D8-D16
+ * FCFF0000-FCFFFFFF VME A16 D8-D16
+ * FD000000-FEEFFFFF Reserved
+ * FEF00000-FEF7FFFF LAN RAM D8-D32
+ * FEF80000-FEFFFFFF LAN Controller D16 (AM79C90)
+ * FF000000-FF7FFFFF System PROM D8-D32 (read) D32 (flash write)
+ * FF800000-FF800BFF Reserved
+ * FF800C00-FF800DFF PIT1 D8 (68230)
+ * FF800E00-FF800FFF PIT2 D8 (68230)
+ * FF801000-FF801FFF Reserved
+ * FF802000-FF8021FF DUSCC1 D8 (SCN68562)
+ * FF802200-FF8023FF DUSCC2 D8 (SCN68562)
+ * FF802400-FF802FFF Reserved
+ * FF803000-FF8031FF RTC (72423) D8
+ * FF803200-FF8033FF Reserved
+ * FF803400-FF8035FF SCSI controller (MB87033/34) D8
+ * FF803600-FF8037FF Reserved
+ * FF803800-FF80397F Floppy controller (FDC37C65C) D8
+ * FF803980-FF8039FF Slot 1 status register (read) D8
+ * FFC00000-FFCFFFFF Local SRAM D8-D32
+ * FFD00000-FFDFFFFF FGA-002 Gate Array D8-D32
+ * FFE00000-FFEFFFFF Boot PROM D8-D32
+ * FFF00000-FFFFFFFF Reserved
+ * --------------------------------------------------------------------------
+ *
+ * Interrupt sources MVME
+ * ----------------------------------------------------------
+ * Description Device Lvl IRQ VME board
+ * /Board Vector Address
+ * ----------------------------------------------------------
+ * On board Sources
+ *
+ * Off board Sources (other VME boards)
+ *
+ * ----------------------------------------------------------
+ *
+ * DMAC Channel Assignments
+ * ----------------------------------------------------------
+ * Channel MVME147
+ * ----------------------------------------------------------
+ *
+ *
+ * TODO:
+ * - Investigate and fix crash
+ * - Add VxWorks proms
+ * - Add more devices
+ * - Write VME device
+ * - Add variants of boards
+ *
+ ****************************************************************************/
+
+#include "emu.h"
+#include "cpu/m68000/m68000.h"
+#include "machine/scnxx562.h"
+#include "machine/68230pit.h"
+#include "machine/nvram.h"
+#include "bus/rs232/rs232.h"
+#include "machine/clock.h"
+//#include "machine/timekpr.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__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+#define DUSCC_CLOCK XTAL_14_7456MHz /* Verified */
+
+class fccpu30_state : public driver_device
+{
+public:
+fccpu30_state(const machine_config &mconfig, device_type type, const char *tag) :
+ driver_device (mconfig, type, tag),
+ m_maincpu (*this, "maincpu")
+ ,m_dusccterm(*this, "duscc")
+ ,m_pit1 (*this, "pit1")
+ ,m_pit2 (*this, "pit2")
+ {
+ }
+
+ DECLARE_READ32_MEMBER (bootvect_r);
+ DECLARE_WRITE32_MEMBER (bootvect_w);
+ /* FGA-002 - Force Gate Array */
+ DECLARE_READ8_MEMBER (fga8_r);
+ DECLARE_WRITE8_MEMBER (fga8_w);
+
+ /* Rotary switch PIT input */
+ DECLARE_READ8_MEMBER (rotary_rd);
+ DECLARE_READ8_MEMBER (board_mem_id_rd);
+
+ /* VME bus accesses */
+ //DECLARE_READ16_MEMBER (vme_a24_r);
+ //DECLARE_WRITE16_MEMBER (vme_a24_w);
+ //DECLARE_READ16_MEMBER (vme_a16_r);
+ //DECLARE_WRITE16_MEMBER (vme_a16_w);
+ virtual void machine_start () override;
+ virtual void machine_reset () override;
+protected:
+
+private:
+ required_device<cpu_device> m_maincpu;
+ required_device<duscc68562_device> m_dusccterm;
+
+ required_device<pit68230_device> m_pit1;
+ required_device<pit68230_device> m_pit2;
+
+ // Pointer to System ROMs needed by bootvect_r and masking RAM buffer for post reset accesses
+ UINT32 *m_sysrom;
+ UINT32 m_sysram[2];
+
+ // FGA-002
+ UINT8 m_fga002[0x500];
+};
+
+static ADDRESS_MAP_START (fccpu30_mem, AS_PROGRAM, 32, fccpu30_state)
+ ADDRESS_MAP_UNMAP_HIGH
+ AM_RANGE (0x00000000, 0x00000007) AM_ROM AM_READ (bootvect_r) /* ROM mirror just during reset */
+ AM_RANGE (0x00000000, 0x00000007) AM_RAM AM_WRITE (bootvect_w) /* After first write we act as RAM */
+ AM_RANGE (0x00000008, 0x003fffff) AM_RAM /* 4 Mb RAM */
+ AM_RANGE (0xff000000, 0xff7fffff) AM_ROM AM_REGION("maincpu", 0xff000000)
+ AM_RANGE (0xff802000, 0xff8021ff) AM_DEVREADWRITE8("duscc", duscc68562_device, read, write, 0xffffffff) /* Port 1&2 - Dual serial port DUSCC */
+ AM_RANGE (0xff800c00, 0xff800dff) AM_DEVREADWRITE8("pit1", pit68230_device, read, write, 0xffffffff)
+ AM_RANGE (0xff800e00, 0xff800fff) AM_DEVREADWRITE8("pit2", pit68230_device, read, write, 0xffffffff)
+ AM_RANGE (0xffc00000, 0xffcfffff) AM_RAM AM_SHARE ("nvram") /* On-board SRAM with battery backup (nvram) */
+ AM_RANGE (0xffd00000, 0xffd004ff) AM_READWRITE8(fga8_r, fga8_w, 0xffffffff) /* FGA-002 Force Gate Array */
+ AM_RANGE (0xffe00000, 0xffefffff) AM_ROM AM_REGION("maincpu", 0xffe00000)
+
+ //AM_RANGE(0x100000, 0xfeffff) AM_READWRITE(vme_a24_r, vme_a24_w) /* VMEbus Rev B addresses (24 bits) - not verified */
+ //AM_RANGE(0xff0000, 0xffffff) AM_READWRITE(vme_a16_r, vme_a16_w) /* VMEbus Rev B addresses (16 bits) - not verified */
+ADDRESS_MAP_END
+
+/* Input ports */
+static INPUT_PORTS_START (fccpu30)
+INPUT_PORTS_END
+
+#define FGA_ICRMBOX0 0x0000
+#define FGA_ICRMBOX1 0x0004
+#define FGA_ICRMBOX2 0x0008
+#define FGA_ICRMBOX3 0x000c
+#define FGA_ICRMBOX4 0x0010
+#define FGA_ICRMBOX5 0x0014
+#define FGA_ICRMBOX6 0x0018
+#define FGA_ICRMBOX7 0x001C
+#define FGA_VMEPAGE 0x0200
+#define FGA_ICRVME1 0x0204
+#define FGA_ICRVME2 0x0208
+#define FGA_ICRVME3 0x020c
+#define FGA_ICRVME4 0x0210
+#define FGA_ICRVME5 0x0214
+#define FGA_ICRVME6 0x0218
+#define FGA_ICRVME7 0x021c
+#define FGA_ICRTIM0 0x0220
+#define FGA_ICRDMANORM 0x0230
+#define FGA_ICRDMAERR 0x0234
+#define FGA_CTL1 0x0238
+#define FGA_CTL2 0x023c
+#define FGA_ICRFMB0REF 0x0240
+#define FGA_ICRFMB1REF 0x0244
+#define FGA_ICRFMB0MES 0x0248
+#define FGA_ICRFMB1MES 0x024c
+#define FGA_CTL3 0x0250
+#define FGA_CTL4 0x0254
+#define FGA_ICRPARITY 0x0258
+#define FGA_AUXPINCTL 0x0260
+#define FGA_CTL5 0x0264
+#define FGA_AUXFIFWEX 0x0268
+#define FGA_AUXFIFREX 0x026c
+#define FGA_CTL6 0x0270
+#define FGA_CTL7 0x0274
+#define FGA_CTL8 0x0278
+#define FGA_CTL9 0x027c
+#define FGA_ICRABORT 0x0280
+#define FGA_ICRACFAIL 0x0284
+#define FGA_ICRSYSFAIL 0x0288
+#define FGA_ICRLOCAL0 0x028c
+#define FGA_ICRLOCAL1 0x0290
+#define FGA_ICRLOCAL2 0x0294
+#define FGA_ICRLOCAL3 0x0298
+#define FGA_ICRLOCAL4 0x029c
+#define FGA_ICRLOCAL5 0x02a0
+#define FGA_ICRLOCAL6 0x02a4
+#define FGA_ICRLOCAL7 0x02a8
+#define FGA_ENAMCODE 0x02b4
+#define FGA_CTL10 0x02c0
+#define FGA_CTL11 0x02c4
+#define FGA_MAINUM 0x02c8
+#define FGA_MAINUU 0x02cc
+#define FGA_BOTTOMPAGEU 0x02d0
+#define FGA_BOTTOMPAGEL 0x02d4
+#define FGA_TOPPAGEU 0x02d8
+#define FGA_TOPPAGEL 0x02dc
+#define FGA_MYVMEPAGE 0x02fc
+#define FGA_TIM0PRELOAD 0x0300
+#define FGA_TIM0CTL 0x0310
+#define FGA_DMASRCATT 0x0320
+#define FGA_DMADSTATT 0x0324
+#define FGA_DMA_GENERAL 0x0328
+#define FGA_CTL12 0x032c
+#define FGA_LIOTIMING 0x0330
+#define FGA_LOCALIACK 0x0334
+#define FGA_FMBCTL 0x0338
+#define FGA_FMBAREA 0x033c
+#define FGA_AUXSRCSTART 0x0340
+#define FGA_AUXDSTSTART 0x0344
+#define FGA_AUXSRCTERM 0x0348
+#define FGA_AUXDSTTERM 0x034c
+#define FGA_CTL13 0x0350
+#define FGA_CTL14 0x0354
+#define FGA_CTL15 0x0358
+#define FGA_CTL16 0x035c
+#define FGA_SPECIALENA 0x0424
+#define FGA_ISTIM0 0x04a0
+#define FGA_ISDMANORM 0x04b0
+#define FGA_ISDMAERR 0x04b4
+#define FGA_ISFMB0REF 0x04b8
+#define FGA_ISFMB1REF 0x04bc
+#define FGA_ISPARITY 0x04c0
+#define FGA_DMARUNCTL 0x04c4
+#define FGA_ISABORT 0x04c8
+#define FGA_ISACFAIL 0x04cc
+#define FGA_ISFMB0MES 0x04e0
+#define FGA_ISFMB1MES 0x04e4
+#define FGA_ISSYSFAIL 0x04d0
+#define FGA_ABORTPIN 0x04d4
+#define FGA_RSVMECALL 0x04f0
+#define FGA_RSKEYRES 0x04f4
+#define FGA_RSCPUCALL 0x04f8
+#define FGA_RSLOCSW 0x04fc
+
+/* Start it up */
+void fccpu30_state::machine_start ()
+{
+ LOG(("--->%s\n", FUNCNAME));
+
+ save_pointer (NAME (m_sysrom), sizeof(m_sysrom));
+ save_pointer (NAME (m_sysram), sizeof(m_sysram));
+ save_pointer (NAME (m_fga002), sizeof(m_fga002));
+
+ /* Setup pointer to bootvector in ROM for bootvector handler bootvect_r */
+ m_sysrom = (UINT32*)(memregion ("maincpu")->base () + 0xffe00000);
+}
+
+void fccpu30_state::machine_reset ()
+{
+ LOG(("--->%s\n", FUNCNAME));
+
+ /* Reset pointer to bootvector in ROM for bootvector handler bootvect_r */
+ if (m_sysrom == &m_sysram[0]) /* Condition needed because memory map is not setup first time */
+ m_sysrom = (UINT32*)(memregion ("maincpu")->base () + 0xffe00000);
+
+ /* Reset values for the FGA-002 */
+ memset(&m_fga002[0], 0, sizeof(m_fga002));
+ m_fga002[FGA_RSVMECALL] = 0x80;
+ m_fga002[FGA_RSKEYRES] = 0x80;
+ m_fga002[FGA_RSCPUCALL] = 0x80;
+ m_fga002[FGA_RSLOCSW] = 0x80;
+ m_fga002[FGA_ISTIM0] = 0x80;
+ m_fga002[FGA_ISDMANORM] = 0x80;
+ m_fga002[FGA_ISDMAERR] = 0x80;
+ m_fga002[FGA_ISFMB0REF] = 0x80;
+ m_fga002[FGA_ISFMB1REF] = 0x80;
+ m_fga002[FGA_ISPARITY] = 0x80;
+ m_fga002[FGA_ISABORT] = 0x80;
+ m_fga002[FGA_ISACFAIL] = 0x80;
+ m_fga002[FGA_ISSYSFAIL] = 0x80;
+ m_fga002[FGA_ISFMB0MES] = 0x80;
+ m_fga002[FGA_ISFMB1MES] = 0x80;
+}
+
+/* Boot vector handler, the PCB hardwires the first 8 bytes from 0xff800000 to 0x0 at reset*/
+READ32_MEMBER (fccpu30_state::bootvect_r){
+ return m_sysrom[offset];
+}
+
+WRITE32_MEMBER (fccpu30_state::bootvect_w){
+ m_sysram[offset % sizeof(m_sysram)] &= ~mem_mask;
+ m_sysram[offset % sizeof(m_sysram)] |= (data & mem_mask);
+ m_sysrom = &m_sysram[0]; // redirect all upcomming accesses to masking RAM until reset.
+}
+
+/*
+ * FGA-002 driver, might deserve its own driver but will rest here until another board wants it
+ *
+The FGA-002 gate array is a high speed CMOS device manufactured in 1.2 micron technology and
+containing 24,000 gates in a 281 pin PGA package. It provides interfaces to the 68020/30 microprocessor
+as well as a VMEbus compatible interface. The auxilary interface of the gate array is a high speed data
+channel used by the internal 32 bit DMA controller. The interface allows data transfer rates of up to
+6 MByte/second. The timing of the local I/O interface is programmable and provides easy interfacing of
+local I/O devices. All control, address and data lines of the CPU and the VMEbus are either directly
+connected or connected via buffers to the gate array allowing easy implementation and usage.
+The gate array registers are programmed by the local CPU.
+
+FEATURES:
+- Programmable decoding for CPU and VME access to the local main memory
+- Interrupt management for internal and external interrupt sources
+- 32 bit multi-port DMA Controller
+- FORCE Message Broadcast slave interface with 2 message channels
+- 8 interrupt capable MAILBOXES
+- 8 bit TIMER with 16 selectable internal source clocks
+*/
+WRITE8_MEMBER (fccpu30_state::fga8_w){
+ LOG(("%s[%04x] <- %02x - ", FUNCNAME, offset, data));
+ switch(offset)
+ {
+ case FGA_SPECIALENA : LOG(("FGA_SPECIALENA - not implemented\n")); m_fga002[FGA_SPECIALENA] = data; break;
+ case FGA_RSVMECALL : LOG(("FGA_RSVMECALL - not implemented\n")); m_fga002[FGA_RSVMECALL] = data; break;
+ case FGA_RSKEYRES : LOG(("FGA_RSKEYRES - not implemented\n")); m_fga002[FGA_RSKEYRES] = data; break;
+ case FGA_RSCPUCALL : LOG(("FGA_RSCPUCALL - not implemented\n")); m_fga002[FGA_RSCPUCALL] = data; break;
+ case FGA_RSLOCSW : LOG(("FGA_RSLOCSW - not implemented\n")); m_fga002[FGA_RSLOCSW] = data; break;
+ case FGA_ICRMBOX0 : LOG(("FGA_ICRMBOX0 - not implemented\n")); m_fga002[FGA_ICRMBOX0] = data; break;
+ case FGA_ICRMBOX1 : LOG(("FGA_ICRMBOX1 - not implemented\n")); m_fga002[FGA_ICRMBOX1] = data; break;
+ case FGA_ICRMBOX2 : LOG(("FGA_ICRMBOX2 - not implemented\n")); m_fga002[FGA_ICRMBOX2] = data; break;
+ case FGA_ICRMBOX3 : LOG(("FGA_ICRMBOX3 - not implemented\n")); m_fga002[FGA_ICRMBOX3] = data; break;
+ case FGA_ICRMBOX4 : LOG(("FGA_ICRMBOX4 - not implemented\n")); m_fga002[FGA_ICRMBOX4] = data; break;
+ case FGA_ICRMBOX5 : LOG(("FGA_ICRMBOX5 - not implemented\n")); m_fga002[FGA_ICRMBOX5] = data; break;
+ case FGA_ICRMBOX6 : LOG(("FGA_ICRMBOX6 - not implemented\n")); m_fga002[FGA_ICRMBOX6] = data; break;
+ case FGA_ICRMBOX7 : LOG(("FGA_ICRMBOX7 - not implemented\n")); m_fga002[FGA_ICRMBOX7] = data; break;
+ case FGA_VMEPAGE : LOG(("FGA_VMEPAGE - not implemented\n")); m_fga002[FGA_VMEPAGE ] = data; break;
+ case FGA_ICRVME1 : LOG(("FGA_ICRVME1 - not implemented\n")); m_fga002[FGA_ICRVME1] = data; break;
+ case FGA_ICRVME2 : LOG(("FGA_ICRVME2 - not implemented\n")); m_fga002[FGA_ICRVME2] = data; break;
+ case FGA_ICRVME3 : LOG(("FGA_ICRVME3 - not implemented\n")); m_fga002[FGA_ICRVME3] = data; break;
+ case FGA_ICRVME4 : LOG(("FGA_ICRVME4 - not implemented\n")); m_fga002[FGA_ICRVME4] = data; break;
+ case FGA_ICRVME5 : LOG(("FGA_ICRVME5 - not implemented\n")); m_fga002[FGA_ICRVME5] = data; break;
+ case FGA_ICRVME6 : LOG(("FGA_ICRVME6 - not implemented\n")); m_fga002[FGA_ICRVME6] = data; break;
+ case FGA_ICRVME7 : LOG(("FGA_ICRVME7 - not implemented\n")); m_fga002[FGA_ICRVME7] = data; break;
+ case FGA_ICRTIM0 : LOG(("FGA_ICRTIM0 - not implemented\n")); m_fga002[FGA_ICRTIM0] = data; break;
+ case FGA_ICRDMANORM : LOG(("FGA_ICRDMANORM - not implemented\n")); m_fga002[FGA_ICRDMANORM] = data; break;
+ case FGA_ICRDMAERR : LOG(("FGA_ICRDMAERR - not implemented\n")); m_fga002[FGA_ICRDMAERR] = data; break;
+ case FGA_CTL1 : LOG(("FGA_CTL1 - not implemented\n")); m_fga002[FGA_CTL1] = data; break;
+ case FGA_CTL2 : LOG(("FGA_CTL2 - not implemented\n")); m_fga002[FGA_CTL2] = data; break;
+ case FGA_ICRFMB0REF : LOG(("FGA_ICRFMB0REF - not implemented\n")); m_fga002[FGA_ICRFMB0REF] = data; break;
+ case FGA_ICRFMB1REF : LOG(("FGA_ICRFMB1REF - not implemented\n")); m_fga002[FGA_ICRFMB1REF] = data; break;
+ case FGA_ICRFMB0MES : LOG(("FGA_ICRFMB0MES - not implemented\n")); m_fga002[FGA_ICRFMB0MES] = data; break;
+ case FGA_ICRFMB1MES : LOG(("FGA_ICRFMB1MES - not implemented\n")); m_fga002[FGA_ICRFMB1MES] = data; break;
+ case FGA_CTL3 : LOG(("FGA_CTL3 - not implemented\n")); m_fga002[FGA_CTL3] = data; break;
+ case FGA_CTL4 : LOG(("FGA_CTL4 - not implemented\n")); m_fga002[FGA_CTL4] = data; break;
+ case FGA_ICRPARITY : LOG(("FGA_ICRPARITY - not implemented\n")); m_fga002[FGA_ICRPARITY] = data; break;
+ case FGA_AUXPINCTL : LOG(("FGA_AUXPINCTL - not implemented\n")); m_fga002[FGA_AUXPINCTL] = data; break;
+ case FGA_CTL5 : LOG(("FGA_CTL5 - not implemented\n")); m_fga002[FGA_CTL5] = data; break;
+ case FGA_AUXFIFWEX : LOG(("FGA_AUXFIFWEX - not implemented\n")); m_fga002[FGA_AUXFIFWEX] = data; break;
+ case FGA_AUXFIFREX : LOG(("FGA_AUXFIFREX - not implemented\n")); m_fga002[FGA_AUXFIFREX] = data; break;
+ case FGA_CTL6 : LOG(("FGA_CTL6 - not implemented\n")); m_fga002[FGA_CTL6] = data; break;
+ case FGA_CTL7 : LOG(("FGA_CTL7 - not implemented\n")); m_fga002[FGA_CTL7] = data; break;
+ case FGA_CTL8 : LOG(("FGA_CTL8 - not implemented\n")); m_fga002[FGA_CTL8] = data; break;
+ case FGA_CTL9 : LOG(("FGA_CTL9 - not implemented\n")); m_fga002[FGA_CTL9] = data; break;
+ case FGA_ICRABORT : LOG(("FGA_ICRABORT - not implemented\n")); m_fga002[FGA_ICRABORT] = data; break;
+ case FGA_ICRACFAIL : LOG(("FGA_ICRACFAIL - not implemented\n")); m_fga002[FGA_ICRACFAIL] = data; break;
+ case FGA_ICRSYSFAIL : LOG(("FGA_ICRSYSFAIL - not implemented\n")); m_fga002[FGA_ICRSYSFAIL] = data; break;
+ case FGA_ICRLOCAL0 : LOG(("FGA_ICRLOCAL0 - not implemented\n")); m_fga002[FGA_ICRLOCAL0] = data; break;
+ case FGA_ICRLOCAL1 : LOG(("FGA_ICRLOCAL1 - not implemented\n")); m_fga002[FGA_ICRLOCAL1] = data; break;
+ case FGA_ICRLOCAL2 : LOG(("FGA_ICRLOCAL2 - not implemented\n")); m_fga002[FGA_ICRLOCAL2] = data; break;
+ case FGA_ICRLOCAL3 : LOG(("FGA_ICRLOCAL3 - not implemented\n")); m_fga002[FGA_ICRLOCAL3] = data; break;
+ case FGA_ICRLOCAL4 : LOG(("FGA_ICRLOCAL4 - not implemented\n")); m_fga002[FGA_ICRLOCAL4] = data; break;
+ case FGA_ICRLOCAL5 : LOG(("FGA_ICRLOCAL5 - not implemented\n")); m_fga002[FGA_ICRLOCAL5] = data; break;
+ case FGA_ICRLOCAL6 : LOG(("FGA_ICRLOCAL6 - not implemented\n")); m_fga002[FGA_ICRLOCAL6] = data; break;
+ case FGA_ICRLOCAL7 : LOG(("FGA_ICRLOCAL7 - not implemented\n")); m_fga002[FGA_ICRLOCAL7] = data; break;
+ case FGA_ENAMCODE : LOG(("FGA_ENAMCODE - not implemented\n")); m_fga002[FGA_ENAMCODE] = data; break;
+ case FGA_CTL10 : LOG(("FGA_CTL10 - not implemented\n")); m_fga002[FGA_CTL10] = data; break;
+ case FGA_CTL11 : LOG(("FGA_CTL11 - not implemented\n")); m_fga002[FGA_CTL11] = data; break;
+ case FGA_MAINUM : LOG(("FGA_MAINUM - not implemented\n")); m_fga002[FGA_MAINUM] = data; break;
+ case FGA_MAINUU : LOG(("FGA_MAINUU - not implemented\n")); m_fga002[FGA_MAINUU] = data; break;
+ case FGA_BOTTOMPAGEU : LOG(("FGA_BOTTOMPAGEU - not implemented\n")); m_fga002[FGA_BOTTOMPAGEU] = data; break;
+ case FGA_BOTTOMPAGEL : LOG(("FGA_BOTTOMPAGEL - not implemented\n")); m_fga002[FGA_BOTTOMPAGEL] = data; break;
+ case FGA_TOPPAGEU : LOG(("FGA_TOPPAGEU - not implemented\n")); m_fga002[FGA_TOPPAGEU] = data; break;
+ case FGA_TOPPAGEL : LOG(("FGA_TOPPAGEL - not implemented\n")); m_fga002[FGA_TOPPAGEL] = data; break;
+ case FGA_MYVMEPAGE : LOG(("FGA_MYVMEPAGE - not implemented\n")); m_fga002[FGA_MYVMEPAGE] = data; break;
+ case FGA_TIM0PRELOAD : LOG(("FGA_TIM0PRELOAD - not implemented\n")); m_fga002[FGA_TIM0PRELOAD] = data; break;
+ case FGA_TIM0CTL : LOG(("FGA_TIM0CTL - not implemented\n")); m_fga002[FGA_TIM0CTL] = data; break;
+ case FGA_DMASRCATT : LOG(("FGA_DMASRCATT - not implemented\n")); m_fga002[FGA_DMASRCATT] = data; break;
+ case FGA_DMADSTATT : LOG(("FGA_DMADSTATT - not implemented\n")); m_fga002[FGA_DMADSTATT] = data; break;
+ case FGA_DMA_GENERAL : LOG(("FGA_DMA_GENERAL - not implemented\n")); m_fga002[FGA_DMA_GENERAL] = data; break;
+ case FGA_CTL12 : LOG(("FGA_CTL12 - not implemented\n")); m_fga002[FGA_CTL12] = data; break;
+ case FGA_LIOTIMING : LOG(("FGA_LIOTIMING - not implemented\n")); m_fga002[FGA_LIOTIMING] = data; break;
+ case FGA_LOCALIACK : LOG(("FGA_LOCALIACK - not implemented\n")); m_fga002[FGA_LOCALIACK] = data; break;
+ case FGA_FMBCTL : LOG(("FGA_FMBCTL - not implemented\n")); m_fga002[FGA_FMBCTL] = data; break;
+ case FGA_FMBAREA : LOG(("FGA_FMBAREA - not implemented\n")); m_fga002[FGA_FMBAREA] = data; break;
+ case FGA_AUXSRCSTART : LOG(("FGA_AUXSRCSTART - not implemented\n")); m_fga002[FGA_AUXSRCSTART] = data; break;
+ case FGA_AUXDSTSTART : LOG(("FGA_AUXDSTSTART - not implemented\n")); m_fga002[FGA_AUXDSTSTART] = data; break;
+ case FGA_AUXSRCTERM : LOG(("FGA_AUXSRCTERM - not implemented\n")); m_fga002[FGA_AUXSRCTERM] = data; break;
+ case FGA_AUXDSTTERM : LOG(("FGA_AUXDSTTERM - not implemented\n")); m_fga002[FGA_AUXDSTTERM] = data; break;
+ case FGA_CTL13 : LOG(("FGA_CTL13 - not implemented\n")); m_fga002[FGA_CTL13] = data; break;
+ case FGA_CTL14 : LOG(("FGA_CTL14 - not implemented\n")); m_fga002[FGA_CTL14] = data; break;
+ case FGA_CTL15 : LOG(("FGA_CTL15 - not implemented\n")); m_fga002[FGA_CTL15] = data; break;
+ case FGA_CTL16 : LOG(("FGA_CTL16 - not implemented\n")); m_fga002[FGA_CTL16] = data; break;
+ case FGA_ISTIM0 : LOG(("FGA_ISTIM0 - not implemented\n")); m_fga002[FGA_ISTIM0] = data; break;
+ case FGA_ISDMANORM : LOG(("FGA_ISDMANORM - not implemented\n")); m_fga002[FGA_ISDMANORM] = data; break;
+ case FGA_ISDMAERR : LOG(("FGA_ISDMAERR - not implemented\n")); m_fga002[FGA_ISDMAERR] = data; break;
+ case FGA_ISFMB0REF : LOG(("FGA_ISFMB0REF - not implemented\n")); m_fga002[FGA_ISFMB0REF] = data; break;
+ case FGA_ISFMB1REF : LOG(("FGA_ISFMB1REF - not implemented\n")); m_fga002[FGA_ISFMB1REF] = data; break;
+ case FGA_ISPARITY : LOG(("FGA_ISPARITY - not implemented\n")); m_fga002[FGA_ISPARITY] = data; break;
+ case FGA_DMARUNCTL : LOG(("FGA_DMARUNCTL - not implemented\n")); m_fga002[FGA_DMARUNCTL] = data; break;
+ case FGA_ISABORT : LOG(("FGA_ISABORT - not implemented\n")); m_fga002[FGA_ISABORT] = data; break;
+ case FGA_ISFMB0MES : LOG(("FGA_ISFMB0MES - not implemented\n")); m_fga002[FGA_ISFMB0MES] = data; break;
+ case FGA_ISFMB1MES : LOG(("FGA_ISFMB1MES - not implemented\n")); m_fga002[FGA_ISFMB1MES] = data; break;
+ case FGA_ABORTPIN : LOG(("FGA_ABORTPIN - not implemented\n")); m_fga002[FGA_ABORTPIN] = data; break;
+ default:
+ LOG(("Unsupported register %04x\n", offset));
+ }
+}
+
+READ8_MEMBER (fccpu30_state::fga8_r){
+
+ UINT8 ret = 0;
+
+ LOG(("%s[%04x] ", FUNCNAME, offset));
+ switch(offset)
+ {
+ case FGA_SPECIALENA : ret = m_fga002[FGA_SPECIALENA]; LOG(("FGA_SPECIALENA returns %02x - not implemented\n", ret)); break;
+ case FGA_RSVMECALL : ret = m_fga002[FGA_RSVMECALL]; LOG(("FGA_RSVMECALL returns %02x - not implemented\n", ret)); break;
+ case FGA_RSKEYRES : ret = m_fga002[FGA_RSKEYRES]; LOG(("FGA_RSKEYRES returns %02x - not implemented\n", ret)); break;
+ case FGA_RSCPUCALL : ret = m_fga002[FGA_RSCPUCALL]; LOG(("FGA_RSCPUCALL returns %02x - not implemented\n", ret)); break;
+ case FGA_RSLOCSW : ret = m_fga002[FGA_RSLOCSW]; LOG(("FGA_RSLOCSW returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRMBOX0 : ret = m_fga002[FGA_ICRMBOX0]; LOG(("FGA_ICRMBOX0 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRMBOX1 : ret = m_fga002[FGA_ICRMBOX1]; LOG(("FGA_ICRMBOX1 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRMBOX2 : ret = m_fga002[FGA_ICRMBOX2]; LOG(("FGA_ICRMBOX2 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRMBOX3 : ret = m_fga002[FGA_ICRMBOX3]; LOG(("FGA_ICRMBOX3 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRMBOX4 : ret = m_fga002[FGA_ICRMBOX4]; LOG(("FGA_ICRMBOX4 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRMBOX5 : ret = m_fga002[FGA_ICRMBOX5]; LOG(("FGA_ICRMBOX5 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRMBOX6 : ret = m_fga002[FGA_ICRMBOX6]; LOG(("FGA_ICRMBOX6 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRMBOX7 : ret = m_fga002[FGA_ICRMBOX7]; LOG(("FGA_ICRMBOX7 returns %02x - not implemented\n", ret)); break;
+ case FGA_VMEPAGE : ret = m_fga002[FGA_VMEPAGE]; LOG(("FGA_VMEPAGE returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRVME1 : ret = m_fga002[FGA_ICRVME1]; LOG(("FGA_ICRVME1 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRVME2 : ret = m_fga002[FGA_ICRVME2]; LOG(("FGA_ICRVME2 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRVME3 : ret = m_fga002[FGA_ICRVME3]; LOG(("FGA_ICRVME3 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRVME4 : ret = m_fga002[FGA_ICRVME4]; LOG(("FGA_ICRVME4 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRVME5 : ret = m_fga002[FGA_ICRVME5]; LOG(("FGA_ICRVME5 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRVME6 : ret = m_fga002[FGA_ICRVME6]; LOG(("FGA_ICRVME6 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRVME7 : ret = m_fga002[FGA_ICRVME7]; LOG(("FGA_ICRVME7 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRTIM0 : ret = m_fga002[FGA_ICRTIM0]; LOG(("FGA_ICRTIM0 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRDMANORM : ret = m_fga002[FGA_ICRDMANORM]; LOG(("FGA_ICRDMANORM returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRDMAERR : ret = m_fga002[FGA_ICRDMAERR]; LOG(("FGA_ICRDMAERR returns %02x - not implemented\n", ret)); break;
+ case FGA_CTL1 : ret = m_fga002[FGA_CTL1]; LOG(("FGA_CTL1 returns %02x - not implemented\n", ret)); break;
+ case FGA_CTL2 : ret = m_fga002[FGA_CTL2]; LOG(("FGA_CTL2 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRFMB0REF : ret = m_fga002[FGA_ICRFMB0REF]; LOG(("FGA_ICRFMB0REF returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRFMB1REF : ret = m_fga002[FGA_ICRFMB1REF]; LOG(("FGA_ICRFMB1REF returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRFMB0MES : ret = m_fga002[FGA_ICRFMB0MES]; LOG(("FGA_ICRFMB0MES returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRFMB1MES : ret = m_fga002[FGA_ICRFMB1MES]; LOG(("FGA_ICRFMB1MES returns %02x - not implemented\n", ret)); break;
+ case FGA_CTL3 : ret = m_fga002[FGA_CTL3]; LOG(("FGA_CTL3 returns %02x - not implemented\n", ret)); break;
+ case FGA_CTL4 : ret = m_fga002[FGA_CTL4]; LOG(("FGA_CTL4 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRPARITY : ret = m_fga002[FGA_ICRPARITY]; LOG(("FGA_ICRPARITY returns %02x - not implemented\n", ret)); break;
+ case FGA_AUXPINCTL : ret = m_fga002[FGA_AUXPINCTL]; LOG(("FGA_AUXPINCTL returns %02x - not implemented\n", ret)); break;
+ case FGA_CTL5 : ret = m_fga002[FGA_CTL5]; LOG(("FGA_CTL5 returns %02x - not implemented\n", ret)); break;
+ case FGA_AUXFIFWEX : ret = m_fga002[FGA_AUXFIFWEX]; LOG(("FGA_AUXFIFWEX returns %02x - not implemented\n", ret)); break;
+ case FGA_AUXFIFREX : ret = m_fga002[FGA_AUXFIFREX]; LOG(("FGA_AUXFIFREX returns %02x - not implemented\n", ret)); break;
+ case FGA_CTL6 : ret = m_fga002[FGA_CTL6]; LOG(("FGA_CTL6 returns %02x - not implemented\n", ret)); break;
+ case FGA_CTL7 : ret = m_fga002[FGA_CTL7]; LOG(("FGA_CTL7 returns %02x - not implemented\n", ret)); break;
+ case FGA_CTL8 : ret = m_fga002[FGA_CTL8]; LOG(("FGA_CTL8 returns %02x - not implemented\n", ret)); break;
+ case FGA_CTL9 : ret = m_fga002[FGA_CTL9]; LOG(("FGA_CTL9 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRABORT : ret = m_fga002[FGA_ICRABORT]; LOG(("FGA_ICRABORT returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRACFAIL : ret = m_fga002[FGA_ICRACFAIL]; LOG(("FGA_ICRACFAIL returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRSYSFAIL : ret = m_fga002[FGA_ICRSYSFAIL]; LOG(("FGA_ICRSYSFAIL returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRLOCAL0 : ret = m_fga002[FGA_ICRLOCAL0]; LOG(("FGA_ICRLOCAL0 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRLOCAL1 : ret = m_fga002[FGA_ICRLOCAL1]; LOG(("FGA_ICRLOCAL1 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRLOCAL2 : ret = m_fga002[FGA_ICRLOCAL2]; LOG(("FGA_ICRLOCAL2 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRLOCAL3 : ret = m_fga002[FGA_ICRLOCAL3]; LOG(("FGA_ICRLOCAL3 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRLOCAL4 : ret = m_fga002[FGA_ICRLOCAL4]; LOG(("FGA_ICRLOCAL4 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRLOCAL5 : ret = m_fga002[FGA_ICRLOCAL5]; LOG(("FGA_ICRLOCAL5 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRLOCAL6 : ret = m_fga002[FGA_ICRLOCAL6]; LOG(("FGA_ICRLOCAL6 returns %02x - not implemented\n", ret)); break;
+ case FGA_ICRLOCAL7 : ret = m_fga002[FGA_ICRLOCAL7]; LOG(("FGA_ICRLOCAL7 returns %02x - not implemented\n", ret)); break;
+ case FGA_ENAMCODE : ret = m_fga002[FGA_ENAMCODE]; LOG(("FGA_ENAMCODE returns %02x - not implemented\n", ret)); break;
+ case FGA_CTL10 : ret = m_fga002[FGA_CTL10]; LOG(("FGA_CTL10 returns %02x - not implemented\n", ret)); break;
+ case FGA_CTL11 : ret = m_fga002[FGA_CTL11]; LOG(("FGA_CTL11 returns %02x - not implemented\n", ret)); break;
+ case FGA_MAINUM : ret = m_fga002[FGA_MAINUM]; LOG(("FGA_MAINUM returns %02x - not implemented\n", ret)); break;
+ case FGA_MAINUU : ret = m_fga002[FGA_MAINUU]; LOG(("FGA_MAINUU returns %02x - not implemented\n", ret)); break;
+ case FGA_BOTTOMPAGEU : ret = m_fga002[FGA_BOTTOMPAGEU]; LOG(("FGA_BOTTOMPAGEU returns %02x - not implemented\n", ret)); break;
+ case FGA_BOTTOMPAGEL : ret = m_fga002[FGA_BOTTOMPAGEL]; LOG(("FGA_BOTTOMPAGEL returns %02x - not implemented\n", ret)); break;
+ case FGA_TOPPAGEU : ret = m_fga002[FGA_TOPPAGEU]; LOG(("FGA_TOPPAGEU returns %02x - not implemented\n", ret)); break;
+ case FGA_TOPPAGEL : ret = m_fga002[FGA_TOPPAGEL]; LOG(("FGA_TOPPAGEL returns %02x - not implemented\n", ret)); break;
+ case FGA_MYVMEPAGE : ret = m_fga002[FGA_MYVMEPAGE]; LOG(("FGA_MYVMEPAGE returns %02x - not implemented\n", ret)); break;
+ case FGA_TIM0PRELOAD : ret = m_fga002[FGA_TIM0PRELOAD]; LOG(("FGA_TIM0PRELOAD returns %02x - not implemented\n", ret)); break;
+ case FGA_TIM0CTL : ret = m_fga002[FGA_TIM0CTL]; LOG(("FGA_TIM0CTL returns %02x - not implemented\n", ret)); break;
+ case FGA_DMASRCATT : ret = m_fga002[FGA_DMASRCATT]; LOG(("FGA_DMASRCATT returns %02x - not implemented\n", ret)); break;
+ case FGA_DMADSTATT : ret = m_fga002[FGA_DMADSTATT]; LOG(("FGA_DMADSTATT returns %02x - not implemented\n", ret)); break;
+ case FGA_DMA_GENERAL : ret = m_fga002[FGA_DMA_GENERAL]; LOG(("FGA_DMA_GENERAL returns %02x - not implemented\n", ret)); break;
+ case FGA_CTL12 : ret = m_fga002[FGA_CTL12]; LOG(("FGA_CTL12 returns %02x - not implemented\n", ret)); break;
+ case FGA_LIOTIMING : ret = m_fga002[FGA_LIOTIMING]; LOG(("FGA_LIOTIMING returns %02x - not implemented\n", ret)); break;
+ case FGA_LOCALIACK : ret = m_fga002[FGA_LOCALIACK]; LOG(("FGA_LOCALIACK returns %02x - not implemented\n", ret)); break;
+ case FGA_FMBCTL : ret = m_fga002[FGA_FMBCTL]; LOG(("FGA_FMBCTL returns %02x - not implemented\n", ret)); break;
+ case FGA_FMBAREA : ret = m_fga002[FGA_FMBAREA]; LOG(("FGA_FMBAREA returns %02x - not implemented\n", ret)); break;
+ case FGA_AUXSRCSTART : ret = m_fga002[FGA_AUXSRCSTART]; LOG(("FGA_AUXSRCSTART returns %02x - not implemented\n", ret)); break;
+ case FGA_AUXDSTSTART : ret = m_fga002[FGA_AUXDSTSTART]; LOG(("FGA_AUXDSTSTART returns %02x - not implemented\n", ret)); break;
+ case FGA_AUXSRCTERM : ret = m_fga002[FGA_AUXSRCTERM]; LOG(("FGA_AUXSRCTERM returns %02x - not implemented\n", ret)); break;
+ case FGA_AUXDSTTERM : ret = m_fga002[FGA_AUXDSTTERM]; LOG(("FGA_AUXDSTTERM returns %02x - not implemented\n", ret)); break;
+ case FGA_CTL13 : ret = m_fga002[FGA_CTL13]; LOG(("FGA_CTL13 returns %02x - not implemented\n", ret)); break;
+ case FGA_CTL14 : ret = m_fga002[FGA_CTL14]; LOG(("FGA_CTL14 returns %02x - not implemented\n", ret)); break;
+ case FGA_CTL15 : ret = m_fga002[FGA_CTL15]; LOG(("FGA_CTL15 returns %02x - not implemented\n", ret)); break;
+ case FGA_CTL16 : ret = m_fga002[FGA_CTL16]; LOG(("FGA_CTL16 returns %02x - not implemented\n", ret)); break;
+ case FGA_ISTIM0 : ret = m_fga002[FGA_ISTIM0]; LOG(("FGA_ISTIM0 returns %02x - not implemented\n", ret)); break;
+ case FGA_ISDMANORM : ret = m_fga002[FGA_ISDMANORM]; LOG(("FGA_ISDMANORM returns %02x - not implemented\n", ret)); break;
+ case FGA_ISDMAERR : ret = m_fga002[FGA_ISDMAERR]; LOG(("FGA_ISDMAERR returns %02x - not implemented\n", ret)); break;
+ case FGA_ISFMB0REF : ret = m_fga002[FGA_ISFMB0REF]; LOG(("FGA_ISFMB0REF returns %02x - not implemented\n", ret)); break;
+ case FGA_ISFMB1REF : ret = m_fga002[FGA_ISFMB1REF]; LOG(("FGA_ISFMB1REF returns %02x - not implemented\n", ret)); break;
+ case FGA_ISPARITY : ret = m_fga002[FGA_ISPARITY]; LOG(("FGA_ISPARITY returns %02x - not implemented\n", ret)); break;
+ case FGA_DMARUNCTL : ret = m_fga002[FGA_DMARUNCTL]; LOG(("FGA_DMARUNCTL returns %02x - not implemented\n", ret)); break;
+ case FGA_ISABORT : ret = m_fga002[FGA_ISABORT]; LOG(("FGA_ISABORT returns %02x - not implemented\n", ret)); break;
+ case FGA_ISFMB0MES : ret = m_fga002[FGA_ISFMB0MES]; LOG(("FGA_ISFMB0MES returns %02x - not implemented\n", ret)); break;
+ case FGA_ISFMB1MES : ret = m_fga002[FGA_ISFMB1MES]; LOG(("FGA_ISFMB1MES returns %02x - not implemented\n", ret)); break;
+ case FGA_ABORTPIN : ret = m_fga002[FGA_ABORTPIN]; LOG(("FGA_ABORTPIN returns %02x - not implemented\n", ret)); break;
+ default:
+ LOG(("Unsupported register %04x\n", offset));
+ }
+ return ret;
+}
+
+/*
+ * Rotary Switches - to configure the board
+ *
+ * Table 25: PI/T #1 Interface Signals
+ * Pin Function In/Out
+ * PA0-PA3 SW1 In
+ * PA4 PA7 SW2 In
+ *
+ * Table 38: Upper Rotary Switch (SW2)
+ * Bit 3: This bit indicates whether the RAM disk should be initialized after reset. If this bit is set to "0" (settings 0-7),
+ * the RAM disk is initialized as defined by bit 0 and 1. When the disk is initialized, all data on the disk is lost.
+ * Bit 2: This bit defines the default data size on the VMEbus. If the bit is set to "0", 16 bits are selected, if it is set
+ * to "1", 32 bits are selected.
+ * Bit 1 and Bit 0: These two bits define the default RAM disk. See Table 40, "RAM Disk Usage," a detailed description.
+ * If AUTOBOOT is set by bit 2 and 3 of SW1, bit 1 and 0 of SW2 define which operating system will be booted. See Table 42,
+ * "Boot an Operating System (if AUTOBOOT is selected)," on page 129 for detailed description.
+ *
+ * Table 39: Lower Rotary Switch (SW1)
+ * Bit 3 and Bit 2: These two bits define which program is to be invoked after reset. Please refer
+ * to Table 41, "Program After Reset," on page 129 for a detailed description.
+ * Bit 1: If this switch is "0" (settings 0,1,4,5,8,9,C,D), VMEPROM tries to execute a start-up file after reset. The default
+ * filename is SY$STRT. If the bit is "1", VMEPROM comes up with the default banner.
+ * Bit 0: If this switch is set to "0" (settings 0,2,4,6,8,A,C,E), VMEPROM checks the VMEbus for available hardware after reset.
+ * In addition VMEPROM waits for SYSFAIL to disappear from the VMEbus. The following hardware can be detected:
+ * - Contiguous memory
+ * - ASCU-1/2
+ * - ISIO-1/2
+ * - SIO-1/2
+ * - ISCSI-1
+ * - WFC-1
+ *
+ * Table 40: RAM Disk Usage
+ * Bit 1 Bit 0 Upper Switch (SW 2) selected on
+ * 1 1 RAM DISK AT TOP OF MEMORY (32 Kbytes) 3,7,B,F
+ * 1 0 RAM DISK AT 0xFC80 0000 (512 Kbytes) 2,6,A,E
+ * 0 1 RAM DISK AT 0x4070 0000 (512 Kbytes) 1,5,9,D
+ * 0 0 RAM DISK AT 0x4080 0000 (512 Kbytes) 0,4,8,C
+ *
+ * Table 41: Program After Reset
+ * Bit 3 Bit 2 Lower Switch (SW 1) selected on
+ * 1 1 VMEPROM C,D,E,F
+ * 1 0 USER PROGRAM AT 0x4070 0000 8,9,A,B
+ * 0 1 AUTOBOOT SYSTEM 4,5,6,7
+ * 0 0 USER PROGRAM AT 4080.000016 0,1,2,3
+ *
+ * Table 42: Boot an Operating System (if AUTOBOOT is selected)
+ * Bit 1 Bit 0 Upper Switch (SW 2) selected on
+ * 1 1 reserved 3,7,B,F
+ * 1 0 Boot UNIX/PDOS 4.x 2,6,A,E
+ * 0 1 Boot another operating system 1,5,9,D
+ * 0 0 Setup for UNIX mailbox driver 0,4,8,C
+ *
+ * "To start VMEPROM, the rotary switches must both be set to 'F':" Hmm...
+ */
+READ8_MEMBER (fccpu30_state::rotary_rd){
+ LOG(("%s\n", FUNCNAME));
+ return 0xff; // TODO: make this configurable from commandline or artwork
+}
+
+/*
+ * PI/T #2 Factory settings
+ * B0-B2 Shared Memory Size - From these lines, the on-board Shared RAM capacity can be read in by software.
+ * 0 0 0 32 Mb
+ * 0 0 1 16 Mb
+ * 0 1 0 8 Mb
+ * 0 1 1 4 Mb
+ * 1 x x Reserved
+ * B3-B7 Board ID(s) - From these lines, the CPU board identification number can be read in by
+ * 0 1 0 1 0 CPU-30 R4 software. Every CPU board has a unique number. Different versions of
+ * (fill in more) one CPU board (i.e. different speeds, capacity of memory, or modules)
+ * contain the same identification number. In the case of the CPU-30 R4, the
+ * number is ten ("10" decimal or 0A16 hexadecimal "01010" binary).
+ */
+READ8_MEMBER (fccpu30_state::board_mem_id_rd){
+ LOG(("%s\n", FUNCNAME));
+ return 0x6A; // CPU-30 R4 with 4Mb of shared RAM. TODO: make this configurable from commandline or artwork
+}
+
+#if 0
+/* Dummy VME access methods until the VME bus device is ready for use */
+READ16_MEMBER (fccpu30_state::vme_a24_r){
+ LOG (logerror ("vme_a24_r\n"));
+ return (UINT16) 0;
+}
+
+WRITE16_MEMBER (fccpu30_state::vme_a24_w){
+ LOG (logerror ("vme_a24_w\n"));
+}
+
+READ16_MEMBER (fccpu30_state::vme_a16_r){
+ LOG (logerror ("vme_16_r\n"));
+ return (UINT16) 0;
+}
+
+WRITE16_MEMBER (fccpu30_state::vme_a16_w){
+ LOG (logerror ("vme_a16_w\n"));
+}
+#endif
+
+/*
+ * Machine configuration
+ */
+static MACHINE_CONFIG_START (fccpu30, fccpu30_state)
+ /* basic machine hardware */
+ MCFG_CPU_ADD ("maincpu", M68030, XTAL_16MHz)
+ MCFG_CPU_PROGRAM_MAP (fccpu30_mem)
+ MCFG_NVRAM_ADD_0FILL("nvram")
+
+ /* Terminal Port config */
+ MCFG_DUSCC68562_ADD("duscc", 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 ("duscc", duscc68562_device, rxa_w))
+ MCFG_RS232_CTS_HANDLER (DEVWRITELINE ("duscc", duscc68562_device, ctsa_w))
+
+// MCFG_DUSCC68562_ADD("duscc2", DUSCC_CLOCK, 0, 0, 0, 0 )
+
+ /* PIT Parallel Interface and Timer device, assuming strapped for on board clock */
+ MCFG_DEVICE_ADD ("pit1", PIT68230, XTAL_16MHz / 2)
+ MCFG_PIT68230_PA_INPUT_CB(READ8(fccpu30_state, rotary_rd))
+ MCFG_DEVICE_ADD ("pit2", PIT68230, XTAL_16MHz / 2)
+ MCFG_PIT68230_PB_INPUT_CB(READ8(fccpu30_state, board_mem_id_rd))
+MACHINE_CONFIG_END
+
+/* ROM definitions */
+ROM_START (fccpu30)
+ROM_REGION32_BE(0xfff00000, "maincpu", 0)
+
+ROM_LOAD16_BYTE("CPU30LO.BIN", 0xff000000, 0x20000, CRC (fefa88ed) SHA1 (71a9ad807c0c2da5c6f6a6dc68c73ad8b52f3ea9))
+ROM_LOAD16_BYTE("CPU30UP.BIN", 0xff000001, 0x20000, CRC (dfed1f68) SHA1 (71478a77d5ab5da0fabcd78e69537919b560e3b8))
+ROM_LOAD("PGA-002.BIN", 0xffe00000, 0x10000, CRC (faa38972) SHA1 (651dfc2f9a865fc6adf49dad90f9e705f2889919))
+
+/*
+ * System ROM information
+ *
+ * FGA-002 Bootprom version 3.1 is released May 28, 1990, coprighted by FORCE Computers Gmbh
+ *
+ * Bootprom PIT setup sequence
+ * 0a 00 <- read port A without side effects
+ * 0b 00 <- read port B without side effects
+ * 10 00 -> TCR - Timer Control register: Disable timer
+ * 13 ff -> CPRH - Counter Preload Regsiter High
+ * 14 ff -> CPRM - Counter Preload Regsiter Mid
+ * 15 ff -> CPRL - Counter Preload Regsiter Low
+ * 10 01 -> TCR - Timer Control register: Enable timer
+ * ------ init ends -------- clock: 4217
+ *
+ * To start VMEPROM, the rotary switches must both be set to 'F' (PI/T #1 port A)
+ *
+ * ------ next config -------- clock: 1964222
+ * 10 00 -> TCR - Timer Control register: Disable timer
+ * 17 00 -> CRH - Counter Register High
+ * 18 00 -> CRM - Counter Register Medium
+ * 19 00 -> CRL - Counter Register Low
+ *
+ * DUSCC #1 channel A setup sequence
+ * 0f 00 -> REG_CCR - reset Tx Command
+ * 0f 40 -> REG_CCR - reset Rx Command
+ * 00 07 -> REG_CMR1 - Async mode
+ * 01 38 -> REG_CMR2 - Normal polled or interrupt mode, no DMA
+ * 04 7f -> REG_TPR - Tx 8 bits, CTS and RTS, 1 STOP bit
+ * 06 1b -> REG_RPR - Rx RTS, 8 bits, no DCD, no parity
+ * 05 3d -> REG_TTR - Tx BRG 9600 (assuming a 14.7456 crystal)
+ * 07 2d -> REG_RTR - Rx BRG 9600 (assuming a 14.7456 crystal)
+ * 0e 27 -> REG_PCR - TRxC = RxCLK 1x, RTxC is input, RTS, GPO2, crystal oscillator connected to X2
+ * 0b f1 -> REG_OMR - RTS low, OUT1 = OUT2 = high, RxRdy asserted for each character,
+ * TxRdy asserted on threshold, Same Tx Residual Character Length as for REG_TPR
+ * 0f 00 -> REG_CCR - reset Tx Command
+ * 0f 40 -> REG_CCR - reset Rx Command
+ * 0f 02 -> REG_CCR - enable Tx Command
+ * 0f 42 -> REG_CCR - enable Rx Command
+ *--- end of setup sequence ---
+ * loop:
+ * read <- REG_GSR
+ * until something needs attention
+ */
+ROM_END
+
+/* Driver */
+/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
+COMP (1990, fccpu30, 0, 0, fccpu30, fccpu30, driver_device, 0, "Force Computers Gmbh", "SYS68K/CPU-30", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW | MACHINE_TYPE_COMPUTER )
diff --git a/src/mame/drivers/force68k.cpp b/src/mame/drivers/force68k.cpp
index a4ba796836e..6a7cc1a172a 100644
--- a/src/mame/drivers/force68k.cpp
+++ b/src/mame/drivers/force68k.cpp
@@ -470,8 +470,8 @@ MCFG_DEVICE_ADD ("rtc", MM58167, XTAL_32_768kHz)
/* PIT Parallel Interface and Timer device, assuming strapped for on board clock */
MCFG_DEVICE_ADD ("pit", PIT68230, XTAL_16MHz / 2)
-MCFG_PIT68230_PA_OUTPUT_CALLBACK (DEVWRITE8 ("cent_data_out", output_latch_device, write))
-MCFG_PIT68230_H2_CALLBACK (DEVWRITELINE ("centronics", centronics_device, write_strobe))
+MCFG_PIT68230_PA_OUTPUT_CB (DEVWRITE8 ("cent_data_out", output_latch_device, write))
+MCFG_PIT68230_H2_CB (DEVWRITELINE ("centronics", centronics_device, write_strobe))
// centronics
MCFG_CENTRONICS_ADD ("centronics", centronics_devices, "printer")
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index ab30da025a6..f6c35358e1d 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -12069,6 +12069,9 @@ fb01 // 1986 FB-01
@source:fc100.cpp
fc100 //
+@source:fccpu30.cpp
+fccpu30 //
+
@source:fcscsi.cpp
fcscsi1 //