summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine')
-rw-r--r--src/devices/machine/8042kbdc.cpp72
-rw-r--r--src/devices/machine/8042kbdc.h1
-rw-r--r--src/devices/machine/8530scc.cpp2
-rw-r--r--src/devices/machine/at28c16.cpp4
-rw-r--r--src/devices/machine/at45dbxx.h6
-rw-r--r--src/devices/machine/atahle.h2
-rw-r--r--src/devices/machine/dp8390.cpp2
-rw-r--r--src/devices/machine/ds1302.h1
-rw-r--r--src/devices/machine/ds1386.cpp594
-rw-r--r--src/devices/machine/ds1386.h210
-rw-r--r--src/devices/machine/hd64610.h1
-rw-r--r--src/devices/machine/i2cmem.h2
-rw-r--r--src/devices/machine/laserdsc.h2
-rw-r--r--src/devices/machine/matsucd.cpp757
-rw-r--r--src/devices/machine/matsucd.h31
-rw-r--r--src/devices/machine/mc146818.h2
-rw-r--r--src/devices/machine/mc6846.cpp4
-rw-r--r--src/devices/machine/mc6846.h6
-rw-r--r--src/devices/machine/mccs1850.h1
-rw-r--r--src/devices/machine/mm58167.cpp22
-rw-r--r--src/devices/machine/mm58167.h1
-rw-r--r--src/devices/machine/msm5832.cpp20
-rw-r--r--src/devices/machine/msm5832.h1
-rw-r--r--src/devices/machine/msm58321.h1
-rw-r--r--src/devices/machine/msm6242.h1
-rw-r--r--src/devices/machine/nscsi_s1410.cpp2
-rw-r--r--src/devices/machine/pcf8593.h1
-rw-r--r--src/devices/machine/pckeybrd.cpp6
-rw-r--r--src/devices/machine/pckeybrd.h6
-rw-r--r--src/devices/machine/pit8253.cpp28
-rw-r--r--src/devices/machine/ram.h2
-rw-r--r--src/devices/machine/roc10937.cpp28
-rw-r--r--src/devices/machine/roc10937.h16
-rw-r--r--src/devices/machine/rp5c01.cpp20
-rw-r--r--src/devices/machine/rp5c01.h2
-rw-r--r--src/devices/machine/rp5c15.h1
-rw-r--r--src/devices/machine/rtc4543.h1
-rw-r--r--src/devices/machine/s3c2400.cpp1
-rw-r--r--src/devices/machine/s3c2410.cpp1
-rw-r--r--src/devices/machine/s3c2440.cpp1
-rw-r--r--src/devices/machine/s3c44b0.cpp1
-rw-r--r--src/devices/machine/serflash.h2
-rw-r--r--src/devices/machine/stvcd.cpp4
-rw-r--r--src/devices/machine/timehelp.h51
-rw-r--r--src/devices/machine/timekpr.cpp71
-rw-r--r--src/devices/machine/timekpr.h2
-rw-r--r--src/devices/machine/upd1990a.h1
-rw-r--r--src/devices/machine/z80scc.cpp706
-rw-r--r--src/devices/machine/z80scc.h45
49 files changed, 1504 insertions, 1241 deletions
diff --git a/src/devices/machine/8042kbdc.cpp b/src/devices/machine/8042kbdc.cpp
index 509a5952890..72b3718c821 100644
--- a/src/devices/machine/8042kbdc.cpp
+++ b/src/devices/machine/8042kbdc.cpp
@@ -267,28 +267,18 @@ WRITE_LINE_MEMBER( kbdc8042_device::keyboard_w )
at_8042_check_keyboard();
}
-TIMER_CALLBACK_MEMBER( kbdc8042_device::kbdc8042_clr_int )
-{
- /* Lets 8952's timers do their job before clear the interrupt line, */
- /* else Keyboard interrupt never happens. */
- m_input_buffer_full_cb(0);
-}
-
void kbdc8042_device::at_8042_receive(UINT8 data)
{
if (LOG_KEYBOARD)
logerror("at_8042_receive Received 0x%02x\n", data);
m_data = data;
- m_keyboard.received = 1;
-
- if (!m_input_buffer_full_cb.isnull())
+ if(!(m_speaker & 0x80))
{
- m_input_buffer_full_cb(1);
- /* Lets 8952's timers do their job before clear the interrupt line, */
- /* else Keyboard interrupt never happens. */
- /* Why was this done? It dies when an extended scan code is received */
- //machine().scheduler().timer_set(attotime::from_usec(2), timer_expired_delegate(FUNC(kbdc8042_device::kbdc8042_clr_int),this));
+ m_keyboard.received = 1;
+
+ if (!m_input_buffer_full_cb.isnull())
+ m_input_buffer_full_cb(1);
}
}
@@ -312,6 +302,7 @@ void kbdc8042_device::at_8042_clear_keyboard_received()
logerror("kbdc8042_8_r(): Clearing m_keyboard.received\n");
}
+ m_input_buffer_full_cb(0);
m_keyboard.received = 0;
m_mouse.received = 0;
}
@@ -348,29 +339,14 @@ READ8_MEMBER(kbdc8042_device::data_r)
switch (offset) {
case 0:
data = m_data;
- m_input_buffer_full_cb(0);
- if ((m_status_read_mode != 3) || (data != 0xfa))
- {
- if (m_keybtype != KBDC8042_AT386 || (data != 0x55))
- {
- /* at386 self test doesn't like this */
- at_8042_clear_keyboard_received();
- }
- at_8042_check_keyboard();
- }
- else
- {
- m_status_read_mode = 4;
- }
+ at_8042_clear_keyboard_received();
+ at_8042_check_keyboard();
break;
case 1:
data = m_speaker;
data &= ~0xc0; /* AT BIOS don't likes this being set */
- /* needed for AMI BIOS, maybe only some keyboard controller revisions! */
- at_8042_clear_keyboard_received();
-
/* polled for changes in ibmat bios */
if (--m_poll_delay < 0)
{
@@ -420,10 +396,6 @@ READ8_MEMBER(kbdc8042_device::data_r)
case 2:
data |= m_inport<<4;
break;
- case 4:
- at_8042_receive(0xaa);
- m_status_read_mode = 0;
- break;
}
break;
}
@@ -443,19 +415,6 @@ WRITE8_MEMBER(kbdc8042_device::data_w)
m_status_read_mode = 0;
switch (m_operation_write_state) {
case 0:
- if ((data == 0xf4) || (data == 0xff)) /* keyboard enable or keyboard reset */
- {
- at_8042_receive(0xfa); /* ACK, delivered a bit differently */
-
- if (data == 0xff)
- {
- m_status_read_mode = 3; /* keyboard buffer to be written again after next read */
- }
-
- break;
- }
-
- /* normal case */
m_data = data;
m_sending=1;
m_keyboard_dev->write(space, 0, data);
@@ -477,9 +436,7 @@ WRITE8_MEMBER(kbdc8042_device::data_w)
case 2:
/* preceded by writing 0xD2 to port 60h */
- m_data = data;
- m_sending=1;
- m_keyboard_dev->write(space, 0, data);
+ at_8042_receive(data);
break;
case 3:
@@ -502,13 +459,19 @@ WRITE8_MEMBER(kbdc8042_device::data_w)
case 1:
m_speaker = data;
+ if (data & 0x80)
+ {
+ at_8042_check_keyboard();
+ at_8042_clear_keyboard_received();
+ }
+ m_speaker &= ~0x80;
if (!m_speaker_cb.isnull())
m_speaker_cb((offs_t)0, m_speaker);
break;
case 4:
- m_last_write_to_control=0;
+ m_last_write_to_control=1;
/* switch based on the command */
switch(data) {
@@ -558,6 +521,9 @@ WRITE8_MEMBER(kbdc8042_device::data_w)
case 0xc2: /* read input port 7..4 until write to 0x60 */
m_status_read_mode = 2;
break;
+ case 0xca: /* unknown used by savquest (read controller mode AT=0/PS2=1 ?) */
+ at_8042_receive(1);
+ break;
case 0xd0: /* read output port */
at_8042_receive(m_outport);
break;
diff --git a/src/devices/machine/8042kbdc.h b/src/devices/machine/8042kbdc.h
index 169c2f9cb12..75ea3d4f2d8 100644
--- a/src/devices/machine/8042kbdc.h
+++ b/src/devices/machine/8042kbdc.h
@@ -72,7 +72,6 @@ public:
DECLARE_WRITE_LINE_MEMBER( keyboard_w );
void at_8042_set_outport(UINT8 data, int initial);
- TIMER_CALLBACK_MEMBER( kbdc8042_clr_int );
void at_8042_receive(UINT8 data);
void at_8042_check_keyboard();
void at_8042_clear_keyboard_received();
diff --git a/src/devices/machine/8530scc.cpp b/src/devices/machine/8530scc.cpp
index bf1c5e09203..88cd30a3388 100644
--- a/src/devices/machine/8530scc.cpp
+++ b/src/devices/machine/8530scc.cpp
@@ -530,7 +530,7 @@ void scc8530_t::write_reg(int offset, UINT8 data)
case 0: /* Channel B (Printer Port) Control */
case 1: /* Channel A (Modem Port) Control */
{
- int chan = ((offset == 2) ? 1 : 0);
+ int chan = ((offset == 0) ? 1 : 0);
if (mode == 0)
{
if((data & 0xf0) == 0) // not a reset command
diff --git a/src/devices/machine/at28c16.cpp b/src/devices/machine/at28c16.cpp
index f54e28f8bda..bc6900924eb 100644
--- a/src/devices/machine/at28c16.cpp
+++ b/src/devices/machine/at28c16.cpp
@@ -136,7 +136,7 @@ void at28c16_device::nvram_default()
void at28c16_device::nvram_read( emu_file &file )
{
- dynamic_buffer buffer( AT28C16_TOTAL_BYTES );
+ std::vector<UINT8> buffer( AT28C16_TOTAL_BYTES );
file.read( &buffer[0], AT28C16_TOTAL_BYTES );
@@ -153,7 +153,7 @@ void at28c16_device::nvram_read( emu_file &file )
void at28c16_device::nvram_write( emu_file &file )
{
- dynamic_buffer buffer ( AT28C16_TOTAL_BYTES );
+ std::vector<UINT8> buffer ( AT28C16_TOTAL_BYTES );
for( offs_t offs = 0; offs < AT28C16_TOTAL_BYTES; offs++ )
{
diff --git a/src/devices/machine/at45dbxx.h b/src/devices/machine/at45dbxx.h
index 40688fd786e..449d95f9651 100644
--- a/src/devices/machine/at45dbxx.h
+++ b/src/devices/machine/at45dbxx.h
@@ -76,12 +76,12 @@ protected:
void write_byte(UINT8 data);
// internal state
- dynamic_buffer m_data;
+ std::vector<UINT8> m_data;
UINT32 m_size;
UINT8 m_mode;
UINT8 m_status;
- dynamic_buffer m_buffer1;
- //dynamic_buffer m_buffer2;
+ std::vector<UINT8> m_buffer1;
+ //std::vector<UINT8> m_buffer2;
UINT8 m_si_byte;
UINT8 m_si_bits;
UINT8 m_so_byte;
diff --git a/src/devices/machine/atahle.h b/src/devices/machine/atahle.h
index e26ad86b92c..29bc23bf9cd 100644
--- a/src/devices/machine/atahle.h
+++ b/src/devices/machine/atahle.h
@@ -175,7 +175,7 @@ protected:
attotime MINIMUM_COMMAND_TIME;
- dynamic_buffer m_buffer;
+ std::vector<UINT8> m_buffer;
UINT16 m_buffer_offset;
UINT16 m_buffer_size;
UINT8 m_error;
diff --git a/src/devices/machine/dp8390.cpp b/src/devices/machine/dp8390.cpp
index 52e66168322..32d41d73896 100644
--- a/src/devices/machine/dp8390.cpp
+++ b/src/devices/machine/dp8390.cpp
@@ -64,7 +64,7 @@ void dp8390_device::check_dma_complete() {
}
void dp8390_device::do_tx() {
- dynamic_buffer buf;
+ std::vector<UINT8> buf;
int i;
UINT32 high16 = (m_regs.dcr & 4)?m_regs.rsar<<16:0;
if(m_reset) return;
diff --git a/src/devices/machine/ds1302.h b/src/devices/machine/ds1302.h
index 6afbc9ea9a4..273bd6bbc9e 100644
--- a/src/devices/machine/ds1302.h
+++ b/src/devices/machine/ds1302.h
@@ -18,6 +18,7 @@
#ifndef __DS1302_H__
#define __DS1302_H__
+#include "emu.h"
#include "dirtc.h"
diff --git a/src/devices/machine/ds1386.cpp b/src/devices/machine/ds1386.cpp
new file mode 100644
index 00000000000..91a6e2f9c06
--- /dev/null
+++ b/src/devices/machine/ds1386.cpp
@@ -0,0 +1,594 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/**********************************************************************
+
+ Dallas DS1386/DS1386P RAMified Watchdog Timekeeper
+
+ Note: Largely untested.
+
+**********************************************************************/
+
+#include "ds1386.h"
+#include "machine/timehelp.h"
+
+#define DISABLE_OSC (0x80)
+#define DISABLE_SQW (0x40)
+
+#define COMMAND_TE (0x80)
+#define COMMAND_IPSW (0x40)
+#define COMMAND_IBH_LO (0x20)
+#define COMMAND_PU_LVL (0x10)
+#define COMMAND_WAM (0x08)
+#define COMMAND_TDM (0x04)
+#define COMMAND_WAF (0x02)
+#define COMMAND_TDF (0x01)
+
+#define HOURS_12_24 (0x40)
+#define HOURS_AM_PM (0x20)
+
+const device_type DS1386_8K = &device_creator<ds1386_8k_device>;
+const device_type DS1386_32K = &device_creator<ds1386_32k_device>;
+
+ds1386_device::ds1386_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, size_t size)
+ : device_t(mconfig, type, name, tag, owner, clock, shortname, __FILE__)
+ , device_nvram_interface(mconfig, *this)
+ , m_tod_alarm(0)
+ , m_watchdog_alarm(0)
+ , m_square(1)
+ , m_inta_cb(*this)
+ , m_intb_cb(*this)
+ , m_sqw_cb(*this)
+ , m_clock_timer(nullptr)
+ , m_square_timer(nullptr)
+ , m_watchdog_timer(nullptr)
+ , m_inta_timer(nullptr)
+ , m_intb_timer(nullptr)
+ , m_default_data(*this, DEVICE_SELF, size)
+ , m_hundredths(0)
+ , m_seconds(0)
+ , m_minutes(0)
+ , m_minutes_alarm(0)
+ , m_hours(0)
+ , m_hours_alarm(0)
+ , m_days(0)
+ , m_days_alarm(0)
+ , m_date(0)
+ , m_months_enables(0)
+ , m_years(0)
+ , m_ram_size(size)
+{
+}
+
+ds1386_8k_device::ds1386_8k_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : ds1386_device(mconfig, DS1386_8K, "DS1386-8K", tag, owner, clock, "ds1386_8k", 8192)
+{
+}
+
+ds1386_32k_device::ds1386_32k_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : ds1386_device(mconfig, DS1386_32K, "DS1386-32K", tag, owner, clock, "ds1386_32k", 32768)
+{
+}
+
+void ds1386_device::safe_inta_cb(int state)
+{
+ if (!m_inta_cb.isnull())
+ m_inta_cb(state);
+}
+
+void ds1386_device::safe_intb_cb(int state)
+{
+ if (!m_intb_cb.isnull())
+ m_intb_cb(state);
+}
+
+void ds1386_device::safe_sqw_cb(int state)
+{
+ if (!m_sqw_cb.isnull())
+ m_sqw_cb(state);
+}
+
+void ds1386_device::device_start()
+{
+ m_inta_cb.resolve();
+ m_intb_cb.resolve();
+ m_sqw_cb.resolve();
+
+ m_tod_alarm = 0;
+ m_watchdog_alarm = 0;
+ m_square = 1;
+
+ safe_inta_cb(0);
+ safe_intb_cb(0);
+ safe_sqw_cb(1);
+
+ // allocate timers
+ m_clock_timer = timer_alloc(CLOCK_TIMER);
+ m_clock_timer->adjust(attotime::from_hz(100), 0, attotime::from_hz(100));
+ m_square_timer = timer_alloc(SQUAREWAVE_TIMER);
+ m_square_timer->adjust(attotime::never);
+ m_watchdog_timer = timer_alloc(WATCHDOG_TIMER);
+ m_watchdog_timer->adjust(attotime::never);
+ m_inta_timer= timer_alloc(INTA_TIMER);
+ m_inta_timer->adjust(attotime::never);
+ m_intb_timer= timer_alloc(INTB_TIMER);
+ m_intb_timer->adjust(attotime::never);
+
+ set_current_time();
+
+ // state saving
+ save_item(NAME(m_tod_alarm));
+ save_item(NAME(m_watchdog_alarm));
+ save_item(NAME(m_square));
+
+ m_ram = std::make_unique<UINT8[]>(m_ram_size);
+ memset(&m_ram[0], 0, m_ram_size);
+}
+
+void ds1386_device::device_reset()
+{
+ m_tod_alarm = 0;
+ m_watchdog_alarm = 0;
+ m_square = 1;
+
+ safe_inta_cb(0);
+ safe_intb_cb(0);
+ safe_sqw_cb(1);
+
+ m_clock_timer->adjust(attotime::from_hz(100), 0, attotime::from_hz(100));
+ m_square_timer->adjust(attotime::never);
+ m_watchdog_timer->adjust(attotime::never);
+
+ set_current_time();
+}
+
+
+void ds1386_device::set_current_time()
+{
+ system_time systime;
+ machine().base_datetime(systime);
+
+ m_hundredths = 0;
+ m_seconds = time_helper::make_bcd(systime.local_time.second);
+ m_minutes = time_helper::make_bcd(systime.local_time.minute);
+ m_hours = time_helper::make_bcd(systime.local_time.hour);
+ m_days = time_helper::make_bcd(systime.local_time.weekday + 1);
+ m_date = time_helper::make_bcd(systime.local_time.mday);
+ m_months_enables = time_helper::make_bcd(systime.local_time.month + 1);
+ m_years = time_helper::make_bcd(systime.local_time.year % 100);
+}
+
+void ds1386_device::time_of_day_alarm()
+{
+ m_ram[REGISTER_COMMAND] |= COMMAND_TDF;
+ m_tod_alarm = 1;
+
+ if (m_ram[REGISTER_COMMAND] & COMMAND_IPSW)
+ {
+ safe_inta_cb(m_tod_alarm);
+ if (m_ram[REGISTER_COMMAND] & COMMAND_PU_LVL)
+ {
+ m_inta_timer->adjust(attotime::from_msec(3));
+ }
+ }
+ else
+ {
+ safe_intb_cb(m_tod_alarm);
+ if (m_ram[REGISTER_COMMAND] & COMMAND_PU_LVL)
+ {
+ m_intb_timer->adjust(attotime::from_msec(3));
+ }
+ }
+}
+
+void ds1386_device::watchdog_alarm()
+{
+ m_ram[REGISTER_COMMAND] |= COMMAND_WAF;
+ m_watchdog_alarm = 1;
+
+ if (m_ram[REGISTER_COMMAND] & COMMAND_IPSW)
+ {
+ safe_intb_cb(m_watchdog_alarm);
+ if (m_ram[REGISTER_COMMAND] & COMMAND_PU_LVL)
+ {
+ m_intb_timer->adjust(attotime::from_msec(3));
+ }
+ }
+ else
+ {
+ safe_inta_cb(m_watchdog_alarm);
+ if (m_ram[REGISTER_COMMAND] & COMMAND_PU_LVL)
+ {
+ m_inta_timer->adjust(attotime::from_msec(3));
+ }
+ }
+}
+
+void ds1386_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case CLOCK_TIMER:
+ advance_hundredths();
+ break;
+
+ case SQUAREWAVE_TIMER:
+ m_square = ((m_square == 0) ? 1 : 0);
+ safe_sqw_cb(m_square);
+ break;
+
+ case WATCHDOG_TIMER:
+ if ((m_ram[REGISTER_COMMAND] & COMMAND_WAF) == 0)
+ watchdog_alarm();
+ break;
+
+ case INTA_TIMER:
+ if (m_ram[REGISTER_COMMAND] & COMMAND_IPSW)
+ {
+ m_tod_alarm = 0;
+ }
+ else
+ {
+ m_watchdog_alarm = 0;
+ }
+ safe_inta_cb(0);
+ break;
+
+ case INTB_TIMER:
+ if (m_ram[REGISTER_COMMAND] & COMMAND_IPSW)
+ {
+ m_watchdog_alarm = 0;
+ }
+ else
+ {
+ m_tod_alarm = 0;
+ }
+ safe_intb_cb(0);
+ break;
+ }
+}
+
+void ds1386_device::advance_hundredths()
+{
+ if ((m_ram[REGISTER_COMMAND] & COMMAND_TE) != 0)
+ {
+ copy_ram_to_registers();
+ }
+
+ int carry = time_helper::inc_bcd(&m_hundredths, 0xff, 0x00, 0x99);
+ if (carry)
+ {
+ carry = time_helper::inc_bcd(&m_seconds, 0x7f, 0x00, 0x59);
+ }
+ if (carry)
+ {
+ carry = time_helper::inc_bcd(&m_minutes, 0x7f, 0x00, 0x59);
+ }
+ if (carry)
+ {
+ UINT8 value = 0;
+ UINT8 min_value = 0;
+ UINT8 max_value = 0;
+ if (m_hours & HOURS_12_24)
+ {
+ value = m_hours & 0x1f;
+ min_value = 0x01;
+ max_value = 0x12;
+ }
+ else
+ {
+ value = m_hours & 0x3f;
+ min_value = 0x00;
+ max_value = 0x23;
+ }
+ carry = time_helper::inc_bcd(&value, 0x1f, min_value, max_value);
+
+ m_hours &= ~0x1f;
+ if (carry)
+ {
+ if (m_hours & HOURS_12_24)
+ {
+ if (m_hours & HOURS_AM_PM)
+ carry = 1;
+ else
+ carry = 0;
+
+ m_hours = m_hours ^ HOURS_AM_PM;
+ }
+ else
+ {
+ m_hours &= ~0x3f;
+ }
+ }
+ else
+ {
+ if ((m_hours & HOURS_12_24) == 0)
+ m_hours &= ~0x3f;
+ }
+ m_hours |= value;
+ }
+
+ if (carry)
+ {
+ UINT8 maxdays;
+ static const UINT8 daysinmonth[] = { 0x31, 0x28, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0x31, 0x30, 0x31 };
+
+ time_helper::inc_bcd(&m_days, 0x07, 0x01, 0x07);
+
+ UINT8 month = time_helper::from_bcd(m_months_enables);
+ UINT8 year = time_helper::from_bcd(m_years);
+
+ if (month == 2 && (year % 4) == 0)
+ {
+ maxdays = 0x29;
+ }
+ else if (month >= 1 && month <= 12)
+ {
+ maxdays = daysinmonth[month - 1];
+ }
+ else
+ {
+ maxdays = 0x31;
+ }
+
+ carry = time_helper::inc_bcd(&m_date, 0x3f, 0x01, maxdays);
+ }
+ if (carry)
+ {
+ UINT8 enables = m_months_enables & 0xc0;
+ carry = time_helper::inc_bcd(&m_months_enables, 0x1f, 0x01, 0x12);
+ m_months_enables &= 0x3f;
+ m_months_enables |= enables;
+ }
+ if (carry)
+ {
+ carry = time_helper::inc_bcd(&m_years, 0xff, 0x00, 0x99);
+ }
+
+ if ((m_ram[REGISTER_COMMAND] & COMMAND_TE) != 0)
+ {
+ copy_registers_to_ram();
+ }
+
+ check_tod_alarm();
+}
+
+void ds1386_device::copy_ram_to_registers()
+{
+ m_hundredths = m_ram[REGISTER_HUNDREDTHS];
+ m_seconds = m_ram[REGISTER_SECONDS];
+ m_minutes = m_ram[REGISTER_MINUTES];
+ m_hours = m_ram[REGISTER_HOURS];
+ m_days = m_ram[REGISTER_DAYS];
+ m_date = m_ram[REGISTER_DATE];
+ m_months_enables = m_ram[REGISTER_MONTHS];
+ m_years = m_ram[REGISTER_YEARS];
+}
+
+void ds1386_device::copy_registers_to_ram()
+{
+ m_ram[REGISTER_HUNDREDTHS] = m_hundredths;
+ m_ram[REGISTER_SECONDS] = m_seconds;
+ m_ram[REGISTER_MINUTES] = m_minutes;
+ m_ram[REGISTER_HOURS] = m_hours;
+ m_ram[REGISTER_DAYS] = m_days;
+ m_ram[REGISTER_DATE] = m_date;
+ m_ram[REGISTER_MONTHS] = m_months_enables;
+ m_ram[REGISTER_YEARS] = m_years;
+}
+
+void ds1386_device::check_tod_alarm()
+{
+ UINT8 mode = BIT(m_days_alarm, 7) | (BIT(m_hours_alarm, 5) << 1) | (BIT(m_minutes_alarm, 3) << 2);
+ bool zeroes = (m_hundredths == 0 && m_seconds == 0);
+ if (zeroes && (m_ram[REGISTER_COMMAND] & COMMAND_TDF) == 0)
+ {
+ bool minutes_match = (m_minutes & 0x7f) == (m_minutes_alarm & 0x7f);
+ bool hours_match = (m_hours & 0x7f) == (m_hours_alarm & 0x7f);
+ bool days_match = (m_days & 0x7) == (m_days_alarm & 0x07);
+ bool alarm_match = false;
+ switch (mode)
+ {
+ case ALARM_PER_MINUTE:
+ alarm_match = true;
+ break;
+ case ALARM_MINUTES_MATCH:
+ alarm_match = minutes_match;
+ break;
+ case ALARM_HOURS_MATCH:
+ alarm_match = hours_match;
+ break;
+ case ALARM_DAYS_MATCH:
+ alarm_match = days_match;
+ break;
+ default:
+ break;
+ }
+ if (alarm_match)
+ {
+ time_of_day_alarm();
+ }
+ }
+}
+
+void ds1386_device::nvram_default()
+{
+ memset(&m_ram[0], 0, m_ram_size);
+}
+
+void ds1386_device::nvram_read(emu_file &file)
+{
+ file.read(&m_ram[0], m_ram_size);
+}
+
+void ds1386_device::nvram_write(emu_file &file)
+{
+ file.write(&m_ram[0], m_ram_size);
+}
+
+WRITE8_MEMBER( ds1386_device::data_w )
+{
+ if (offset >= m_ram_size)
+ return;
+
+ if (offset >= 0xe)
+ {
+ m_ram[offset] = data;
+ }
+ else
+ {
+ switch (offset)
+ {
+ case 0x00: // hundredths
+ case 0x03: // minutes alarm
+ case 0x05: // horus alarm
+ case 0x0a: // years
+ m_ram[offset] = data;
+ break;
+
+ case 0x01: // seconds
+ case 0x02: // minutes
+ case 0x04: // hours
+ m_ram[offset] = data & 0x7f;
+ break;
+
+ case 0x06: // days
+ m_ram[offset] = data & 0x07;
+ break;
+
+ case 0x07: // days alarm
+ m_ram[offset] = data & 0x87;
+ break;
+
+ case 0x08: // date
+ m_ram[offset] = data & 0x3f;
+ break;
+
+ case 0x09: // months
+ {
+ UINT8 old_value = m_ram[offset];
+ m_ram[offset] = data & 0xdf;
+ UINT8 changed = old_value ^ data;
+ if (changed & DISABLE_SQW)
+ {
+ if (m_ram[offset] & DISABLE_SQW)
+ {
+ m_square_timer->adjust(attotime::never);
+ }
+ else
+ {
+ m_square_timer->adjust(attotime::from_hz(2048));
+ }
+ }
+ if (changed & DISABLE_OSC)
+ {
+ if (m_ram[offset] & DISABLE_OSC)
+ {
+ m_clock_timer->adjust(attotime::never);
+ }
+ else
+ {
+ m_clock_timer->adjust(attotime::from_hz(100));
+ }
+ }
+ break;
+ }
+
+ case 0x0c: // watchdog hundredths
+ case 0x0d: // watchdog seconds
+ {
+ if ((m_ram[REGISTER_COMMAND] & COMMAND_WAF) != 0 && (m_ram[REGISTER_COMMAND] & COMMAND_WAM) == 0)
+ {
+ m_ram[REGISTER_COMMAND] &= ~COMMAND_WAF;
+ m_watchdog_alarm = 0;
+ if (m_ram[REGISTER_COMMAND] & COMMAND_IPSW)
+ safe_intb_cb(0);
+ else
+ safe_inta_cb(0);
+ }
+ m_ram[offset] = data;
+ UINT8 wd_hundredths = m_ram[REGISTER_WATCHDOG_HUNDREDTHS];
+ UINT8 wd_seconds = m_ram[REGISTER_WATCHDOG_SECONDS];
+ int total_hundredths = (wd_hundredths & 0xf) + ((wd_hundredths >> 4) & 0xf) * 10 + (wd_seconds & 0xf) * 100 + ((wd_seconds >> 4) & 0xf) * 1000;
+ m_watchdog_timer->adjust(attotime::from_msec(total_hundredths * 10));
+ break;
+ }
+
+ case 0x0b: // command
+ {
+ UINT8 old = m_ram[offset];
+ m_ram[offset] = data & 0xfc;
+ UINT8 changed = old ^ m_ram[offset];
+ if (changed & COMMAND_IPSW)
+ {
+ int old_a = (old & COMMAND_IPSW) ? m_tod_alarm : m_watchdog_alarm;
+ int old_b = (old & COMMAND_IPSW) ? m_watchdog_alarm : m_tod_alarm;
+ int new_a = old_b;
+ int new_b = old_a;
+
+ bool a_changed = old_a != new_a;
+ bool b_changed = old_b != new_b;
+
+ std::swap(m_tod_alarm, m_watchdog_alarm);
+
+ if (a_changed)
+ {
+ if (m_ram[offset] & COMMAND_IPSW)
+ safe_inta_cb(m_tod_alarm);
+ else
+ safe_inta_cb(m_watchdog_alarm);
+ }
+ if (b_changed)
+ {
+ if (m_ram[offset] & COMMAND_IPSW)
+ safe_intb_cb(m_watchdog_alarm);
+ else
+ safe_intb_cb(m_tod_alarm);
+ }
+ }
+ if (changed & COMMAND_WAM)
+ {
+ if (m_ram[offset] & COMMAND_WAF)
+ {
+ if (m_ram[offset] & COMMAND_IPSW)
+ safe_intb_cb(0);
+ else
+ safe_inta_cb(0);
+ }
+ else if (m_watchdog_alarm)
+ {
+ if (m_ram[offset] & COMMAND_IPSW)
+ safe_intb_cb(m_watchdog_alarm);
+ else
+ safe_inta_cb(m_watchdog_alarm);
+ }
+ }
+ if (changed & COMMAND_TDM)
+ {
+ if (m_ram[offset] & COMMAND_TDF)
+ {
+ if (m_ram[offset] & COMMAND_IPSW)
+ safe_inta_cb(0);
+ else
+ safe_intb_cb(0);
+ }
+ else if (m_tod_alarm)
+ {
+ if (m_ram[offset] & COMMAND_IPSW)
+ safe_inta_cb(m_tod_alarm);
+ else
+ safe_intb_cb(m_tod_alarm);
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
+READ8_MEMBER( ds1386_device::data_r )
+{
+ if (offset >= m_ram_size)
+ return 0;
+
+ return m_ram[offset];
+}
diff --git a/src/devices/machine/ds1386.h b/src/devices/machine/ds1386.h
new file mode 100644
index 00000000000..1146416b923
--- /dev/null
+++ b/src/devices/machine/ds1386.h
@@ -0,0 +1,210 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/**********************************************************************
+
+ Dallas DS1386/DS1386P RAMified Watchdog Timekeeper
+
+***********************************************************************
+ _____________
+ /INTA 1 | | 32 Vcc
+ /INTB 2 | | 31 SQW
+ NC/A14 3 | | 30 Vcc
+ A12 4 | | 29 /WE
+ A7 5 | | 28 NC/A13
+ A6 6 | | 27 A8
+ A5 7 | | 26 A9
+ A4 8 | | 25 A11
+ A3 9 | | 24 /OE
+ A2 10 | | 23 A10
+ A1 11 | | 22 /CE
+ A0 12 | | 21 DQ7
+ DQ0 13 | | 20 DQ6
+ DQ1 14 | | 19 DQ5
+ DQ2 15 | | 18 DQ4
+ GND 16 |_____________| 17 DQ3
+
+ DS1386 8k/32k x 8
+
+ __________________________________
+ / |
+ / |
+ /INTB | 1 34 | /INTA
+ NC | 2 33 | SQW
+ NC | 3 32 | NC/A13
+ /PFO | 4 31 | NC/A14
+ Vcc | 5 30 | A12
+ /WE | 6 29 | A11
+ /OE | 7 28 | A10
+ /CE | 8 27 | A9
+ DQ7 | 9 26 | A8
+ DQ6 | 10 25 | A7
+ DQ5 | 11 24 | A6
+ DQ4 | 12 23 | A5
+ DQ3 | 13 22 | A4
+ DQ2 | 14 X1 GND Vbat X2 21 | A3
+ DQ1 | 15 ____ ____ ____ ____ 20 | A2
+ DQ0 | 16 | | | | | | | | 19 | A1
+ GND | 17 |____| |____| |____| |____| 18 | A0
+ |____________________________________|
+
+ DS1386 8k/32k x 8, 34-Pin PowerCap Module Board
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef DS1386_H
+#define DS1386_H
+
+#include "emu.h"
+
+// handlers
+
+#define MCFG_DS1386_INTA_HANDLER(_devcb) \
+ devcb = &ds1386_device::set_inta_cb(*device, DEVCB_##_devcb);
+
+#define MCFG_DS1386_INTB_HANDLER(_devcb) \
+ devcb = &ds1386_device::set_inta_cb(*device, DEVCB_##_devcb);
+
+#define MCFG_DS1386_SQW_HANDLER(_devcb) \
+ devcb = &ds1386_device::set_sqw_cb(*device, DEVCB_##_devcb);
+
+// devices
+
+#define MCFG_DS1386_8K_ADD(_tag, _clock) \
+ MCFG_DEVICE_ADD(_tag, DS1386_8K, _clock)
+
+#define MCFG_DS1386_32K_ADD(_tag, _clock) \
+ MCFG_DEVICE_ADD(_tag, DS1386_32K, _clock)
+
+class ds1386_device : public device_t,
+ public device_nvram_interface
+{
+public:
+ ds1386_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, size_t size);
+
+ DECLARE_WRITE8_MEMBER( data_w );
+ DECLARE_READ8_MEMBER( data_r );
+
+ DECLARE_WRITE_LINE_MEMBER( ce_w );
+ DECLARE_WRITE_LINE_MEMBER( oe_w );
+ DECLARE_WRITE_LINE_MEMBER( we_w );
+
+ template<class _Object> static devcb_base &set_inta_cb(device_t &device, _Object object) { return downcast<ds1386_device &>(device).m_inta_cb.set_callback(object); }
+ template<class _Object> static devcb_base &set_intb_cb(device_t &device, _Object object) { return downcast<ds1386_device &>(device).m_intb_cb.set_callback(object); }
+ template<class _Object> static devcb_base &set_sqw_cb(device_t &device, _Object object) { return downcast<ds1386_device &>(device).m_sqw_cb.set_callback(object); }
+
+protected:
+ enum
+ {
+ REGISTER_HUNDREDTHS = 0,
+ REGISTER_SECONDS,
+ REGISTER_MINUTES,
+ REGISTER_MINUTE_ALARM,
+ REGISTER_HOURS,
+ REGISTER_HOUR_ALARM,
+ REGISTER_DAYS,
+ REGISTER_DAY_ALARM,
+ REGISTER_DATE,
+ REGISTER_MONTHS,
+ REGISTER_EN_OUTS = REGISTER_MONTHS,
+ REGISTER_YEARS,
+ REGISTER_COMMAND,
+ REGISTER_WATCHDOG_HUNDREDTHS,
+ REGISTER_WATCHDOG_SECONDS,
+ REGISTER_USER = 0xE,
+ };
+
+ enum
+ {
+ ALARM_DAYS_MATCH = 0x0,
+ ALARM_HOURS_MATCH = 0x1,
+ ALARM_MINUTES_MATCH = 0x3,
+ ALARM_PER_MINUTE = 0x7
+ };
+
+ // 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_nvram_interface overrides
+ virtual void nvram_default() override;
+ virtual void nvram_read(emu_file &file) override;
+ virtual void nvram_write(emu_file &file) override;
+
+ static const device_timer_id CLOCK_TIMER = 0;
+ static const device_timer_id SQUAREWAVE_TIMER = 1;
+ static const device_timer_id WATCHDOG_TIMER = 2;
+ static const device_timer_id INTA_TIMER = 3;
+ static const device_timer_id INTB_TIMER = 4;
+
+protected:
+ void safe_inta_cb(int state);
+ void safe_intb_cb(int state);
+ void safe_sqw_cb(int state);
+
+ void set_current_time();
+
+ void check_tod_alarm();
+ void time_of_day_alarm();
+ void watchdog_alarm();
+
+ void advance_hundredths();
+
+ void copy_ram_to_registers();
+ void copy_registers_to_ram();
+
+ int m_tod_alarm;
+ int m_watchdog_alarm;
+ int m_square;
+
+ // interfacing with other devices
+ devcb_write_line m_inta_cb;
+ devcb_write_line m_intb_cb;
+ devcb_write_line m_sqw_cb;
+
+ // timers
+ emu_timer *m_clock_timer;
+ emu_timer *m_square_timer;
+ emu_timer *m_watchdog_timer;
+ emu_timer *m_inta_timer;
+ emu_timer *m_intb_timer;
+
+ std::unique_ptr<UINT8[]> m_ram;
+ optional_region_ptr<UINT8> m_default_data;
+
+ UINT8 m_hundredths;
+ UINT8 m_seconds;
+ UINT8 m_minutes;
+ UINT8 m_minutes_alarm;
+ UINT8 m_hours;
+ UINT8 m_hours_alarm;
+ UINT8 m_days;
+ UINT8 m_days_alarm;
+ UINT8 m_date;
+ UINT8 m_months_enables;
+ UINT8 m_years;
+
+ const size_t m_ram_size;
+};
+
+class ds1386_8k_device : public ds1386_device
+{
+public:
+ // construction/destruction
+ ds1386_8k_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class ds1386_32k_device : public ds1386_device
+{
+public:
+ // construction/destruction
+ ds1386_32k_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+// device type definition
+extern const device_type DS1386_8K;
+extern const device_type DS1386_32K;
+
+#endif
diff --git a/src/devices/machine/hd64610.h b/src/devices/machine/hd64610.h
index 81147baede3..2dc5726ddea 100644
--- a/src/devices/machine/hd64610.h
+++ b/src/devices/machine/hd64610.h
@@ -26,6 +26,7 @@
#ifndef __HD64610__
#define __HD64610__
+#include "emu.h"
#include "dirtc.h"
diff --git a/src/devices/machine/i2cmem.h b/src/devices/machine/i2cmem.h
index 801aa6de3bd..797df97d70a 100644
--- a/src/devices/machine/i2cmem.h
+++ b/src/devices/machine/i2cmem.h
@@ -142,7 +142,7 @@ protected:
int m_shift;
int m_devsel;
int m_byteaddr;
- dynamic_buffer m_page;
+ std::vector<UINT8> m_page;
int m_page_offset;
};
diff --git a/src/devices/machine/laserdsc.h b/src/devices/machine/laserdsc.h
index 1bb19bea0a0..7816bfa2d21 100644
--- a/src/devices/machine/laserdsc.h
+++ b/src/devices/machine/laserdsc.h
@@ -301,7 +301,7 @@ private:
// disc parameters
chd_file * m_disc; // handle to the disc itself
- dynamic_buffer m_vbidata; // pointer to precomputed VBI data
+ std::vector<UINT8> m_vbidata; // pointer to precomputed VBI data
int m_width; // width of video
int m_height; // height of video
UINT32 m_fps_times_1million; // frame rate of video
diff --git a/src/devices/machine/matsucd.cpp b/src/devices/machine/matsucd.cpp
deleted file mode 100644
index d9d8ec47b27..00000000000
--- a/src/devices/machine/matsucd.cpp
+++ /dev/null
@@ -1,757 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:smf, Mariusz Wojcieszek
-/***************************************************************************
-
- Matsushita/Panasonic CDR521/522 type CDROM drive emulation
-
-Notes:
-This version implements the drive found in Amiga CDTV. There are
-different drives supporting this command-set (look in the sbpcd driver
-in Linux for examples). Most drives support the exact same command
-structure, but the command numbers differ. Eventually this driver
-can be expanded with support for the other drives as needed.
-
-***************************************************************************/
-
-
-#include "emu.h"
-#include "imagedev/chd_cd.h"
-#include "sound/cdda.h"
-#include "machine/matsucd.h"
-
-
-#define MATSU_STATUS_READY ( 1 << 0 ) /* driver ready */
-#define MATSU_STATUS_DOORLOCKED ( 1 << 1 ) /* door locked */
-#define MATSU_STATUS_PLAYING ( 1 << 2 ) /* drive playing */
-#define MATSU_STATUS_SUCCESS ( 1 << 3 ) /* last command was successful */
-#define MATSU_STATUS_ERROR ( 1 << 4 ) /* last command failed */
-#define MATSU_STATUS_MOTOR ( 1 << 5 ) /* spinning */
-#define MATSU_STATUS_MEDIA ( 1 << 6 ) /* media present (in caddy or tray) */
-#define MATSU_STATUS_DOORCLOSED ( 1 << 7 ) /* tray status */
-
-struct matsucd
-{
- UINT8 enabled; /* /ENABLE - Unit enabled */
- UINT8 cmd_signal; /* /CMD - Command mode */
- UINT8 stch_signal; /* /STCH - Status Changed */
- UINT8 sten_signal; /* /STEN - Status Enabled */
- UINT8 scor_signal; /* /STEN - Subcode Ready */
- UINT8 input[16];
- UINT8 input_pos;
- UINT8 output[16];
- UINT8 output_pos;
- UINT8 output_len;
- UINT8 status;
- UINT8 motor;
- UINT16 sector_size;
- UINT32 lba;
- UINT16 num_blocks;
- UINT16 xfer_offset;
- UINT8 sector_buffer[CD_MAX_SECTOR_DATA];
- UINT8 cdda_set;
- void (*sten_cb)( running_machine &machine, int level ); /* Status enabled callback */
- void (*stch_cb)( running_machine &machine, int level ); /* Status changed callback */
- void (*scor_cb)( running_machine &machine, int level ); /* Subcode ready callback */
- cdrom_file *cdrom;
- cdda_device *cdda;
- emu_timer *frame_timer;
-};
-
-static matsucd cd;
-
-#define MSF2LBA(msf) (((msf >> 16) & 0xff) * 60 * 75 + ((msf >> 8) & 0xff) * 75 + ((msf >> 0) & 0xff))
-#define LBA2MSF(lba) (((lba / (75 * 60)) << 16) | (((lba / 75) % 60) << 8) | (lba % 75))
-
-static TIMER_CALLBACK(matsu_subcode_proc);
-
-void matsucd_init( cdrom_image_device *cdrom_device, const char *cdda_tag )
-{
- memset(&cd, 0, sizeof( matsucd ) );
-
- cd.cdrom = cdrom_device->get_cdrom_file();
- cd.cdda = cdrom_device->machine().device<cdda_device>(cdda_tag);
-
- cd.frame_timer = cdrom_device->machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(matsu_subcode_proc),&cdrom_device->machine()));
-
- cd.stch_signal = 1;
-}
-
-void matsucd_set_status_enabled_callback( void (*sten_cb)( running_machine &machine, int level ) )
-{
- /* add the callback for status enabled signal */
- cd.sten_cb = sten_cb;
-}
-
-void matsucd_set_status_changed_callback( void (*stch_cb)( running_machine &machine, int level ) )
-{
- /* add the callback for status changed signal */
- cd.stch_cb = stch_cb;
-}
-
-void matsucd_set_subcode_ready_callback( void (*scor_cb)( running_machine &machine, int level ) )
-{
- /* add the callback for subcode ready signal */
- cd.scor_cb = scor_cb;
-}
-
-static int matsucd_getsector_type( running_machine &machine )
-{
- switch( cd.sector_size )
- {
- case 2048: return CD_TRACK_MODE1;
- case 2324: return CD_TRACK_MODE2_FORM2;
- case 2336: return CD_TRACK_MODE2;
- case 2352: return CD_TRACK_MODE2_RAW;
-
- default: machine.logerror( "MATSUCD: Sector size %d unsupported!\n", cd.sector_size ); break;
- }
-
- return CD_TRACK_RAW_DONTCARE;
-}
-
-void matsucd_read_next_block( running_machine &machine )
-{
- cd.xfer_offset = 0;
-
- if ( cd.num_blocks )
- {
- cd.lba++;
- cd.num_blocks--;
-
- if (!cdrom_read_data(cd.cdrom, cd.lba, cd.sector_buffer, matsucd_getsector_type(machine)))
- {
- machine.logerror( "MATSUCD - Warning: Read error on CD!\n" );
- }
- }
-}
-
-int matsucd_get_next_byte( UINT8 *data )
-{
- /* no more data to read on this sector */
- if ( cd.xfer_offset >= cd.sector_size )
- return -1;
-
- if ( data )
- *data = cd.sector_buffer[cd.xfer_offset++];
-
- return 0;
-}
-
-static void matsucd_cdda_stop( running_machine &machine )
-{
- if (cd.cdda != nullptr)
- {
- cd.cdda->stop_audio();
- cd.frame_timer->reset( );
- }
-}
-
-static void matsucd_cdda_play( running_machine &machine, UINT32 lba, UINT32 num_blocks )
-{
- if (cd.cdda != nullptr)
- {
- cd.cdda->start_audio(lba, num_blocks);
- cd.frame_timer->adjust(attotime::from_hz( 75 ));
- }
-}
-
-static void matsucd_cdda_pause( running_machine &machine, int pause )
-{
- if (cd.cdda != nullptr)
- {
- cd.cdda->pause_audio(pause);
-
- if ( pause )
- {
- cd.frame_timer->reset( );
- }
- else
- {
- cd.frame_timer->adjust(attotime::from_hz( 75 ));
- }
- }
-}
-
-static UINT8 matsucd_cdda_getstatus( running_machine &machine, UINT32 *lba )
-{
- if ( lba ) *lba = 0;
-
- if (cd.cdda != nullptr)
- {
- if (cd.cdda->audio_active())
- {
- if ( lba ) *lba = cd.cdda->get_audio_lba();
-
- if (cd.cdda->audio_paused())
- {
- return 0x12; /* audio paused */
- }
- else
- {
- return 0x11; /* audio in progress */
- }
- }
- else if (cd.cdda->audio_ended())
- {
- return 0x13; /* audio ended */
- }
- }
-
- return 0x15; /* no audio status */
-}
-
-void matsucd_enable_w( int level )
-{
- cd.enabled = ( level ) ? 0 : 1;
-}
-
-void matsucd_cmd_w( int level )
-{
- cd.cmd_signal = ( level ) ? 0 : 1;
-}
-
-int matsucd_stch_r( void )
-{
- return cd.stch_signal ? 0 : 1;
-}
-
-int matsucd_sten_r( void )
-{
- return cd.sten_signal ? 0 : 1;
-}
-
-int matsucd_scor_r( void )
-{
- return cd.scor_signal ? 0 : 1;
-}
-
-static void update_status_enable( running_machine &machine, int level )
-{
- cd.sten_signal = level;
-
- if ( cd.sten_cb )
- {
- (*cd.sten_cb)(machine, cd.sten_signal);
- }
-}
-
-static void update_status_changed( running_machine &machine, int level )
-{
- cd.stch_signal = level;
-
- if ( cd.stch_cb )
- {
- (*cd.stch_cb)(machine, cd.stch_signal);
- }
-}
-
-static void update_subcode_ready( running_machine &machine, int level )
-{
- cd.scor_signal = level;
-
- if ( cd.scor_cb )
- {
- (*cd.scor_cb)(machine, cd.scor_signal);
- }
-}
-
-static TIMER_CALLBACK(matsucd_set_status_end)
-{
- update_status_changed( machine, 1 );
-}
-
-static void matsucd_set_status( running_machine &machine, UINT8 status )
-{
- if ( status != cd.status )
- {
- cd.status = status;
-
- if ( cd.stch_signal != 0 )
- {
- update_status_changed( machine, 0 );
- machine.scheduler().timer_set(attotime::from_msec(1), timer_expired_delegate(FUNC(matsucd_set_status_end),&machine));
- }
- }
-}
-
-static TIMER_CALLBACK(matsu_subcode_proc)
-{
- (void)param;
-
- if (cd.cdda != nullptr)
- {
- UINT8 s = matsucd_cdda_getstatus(machine, nullptr);
- UINT8 newstatus = cd.status;
-
- if ( s == 0x11 || s == 0x12 )
- {
- if ( s == 0x11 )
- {
- update_subcode_ready( machine, 1 );
- update_subcode_ready( machine, 0 );
- }
-
- newstatus |= MATSU_STATUS_PLAYING;
-
- cd.frame_timer->adjust(attotime::from_hz( 75 ));
- }
- else
- {
- newstatus &= ~MATSU_STATUS_PLAYING;
- }
-
- matsucd_set_status( machine, newstatus );
- }
-}
-
-static void matsucd_command_error( running_machine &machine )
-{
- UINT8 newstatus = cd.status;
-
- newstatus &= ~MATSU_STATUS_SUCCESS;
- newstatus |= MATSU_STATUS_ERROR;
-
- matsucd_set_status( machine, newstatus );
-}
-
-static void matsucd_complete_cmd( running_machine &machine, UINT8 len )
-{
- UINT8 newstatus = cd.status;
-
- cd.input_pos = 0;
- cd.output_pos = 0;
- cd.output_len = len;
-
- newstatus &= ~MATSU_STATUS_ERROR;
- newstatus |= MATSU_STATUS_SUCCESS;
-
- matsucd_set_status( machine, newstatus );
-
- update_status_enable( machine, 1 );
- update_status_enable( machine, 0 );
-}
-
-UINT8 matsucd_response_r( running_machine &machine )
-{
- UINT8 v = cd.output[cd.output_pos++];
-
- if ( cd.output_pos < cd.output_len )
- {
- update_status_enable( machine, 1 );
- update_status_enable( machine, 0 );
- }
-
- return v;
-}
-
-void matsucd_command_w( running_machine &machine, UINT8 data )
-{
- UINT8 cmd;
-
- /* make sure we're enabled */
- if ( cd.enabled == 0 )
- return;
-
- /* make sure /CMD is asserted */
- if ( cd.cmd_signal == 0 )
- return;
-
- if ( cd.cdda_set == 0 )
- {
- if ( cd.cdrom )
- cd.cdda->set_cdrom(cd.cdrom);
-
- cd.cdda_set = 1;
- }
-
- cd.input[cd.input_pos++] = data;
-
- cmd = cd.input[0];
-
- switch( cmd )
- {
- case 0x01: /* seek */
- {
- if ( cd.input_pos < 7 )
- return;
-
- /* stop CDDA audio if necessary */
- matsucd_cdda_stop(machine);
-
- cd.motor = 1;
-
- memset( cd.output, 0, 6 );
- matsucd_complete_cmd( machine, 0 );
- }
- break;
-
- case 0x02: /* read sectors */
- {
- if ( cd.input_pos < 7 )
- return;
-
- /* stop CDDA audio if necessary */
- matsucd_cdda_stop(machine);
-
- /* LBA */
- cd.lba = cd.input[1];
- cd.lba <<= 8;
- cd.lba |= cd.input[2];
- cd.lba <<= 8;
- cd.lba |= cd.input[3];
-
- /* Number of blocks */
- cd.num_blocks = cd.input[4];
- cd.num_blocks <<= 8;
- cd.num_blocks |= cd.input[5];
-
- /* Reset transfer count */
- cd.xfer_offset = 0;
-
- /* go ahead and cache the first block */
- if (!cdrom_read_data(cd.cdrom, cd.lba, cd.sector_buffer, matsucd_getsector_type(machine)))
- {
- machine.logerror( "MATSUCD - Warning: Read error on CD!\n" );
- matsucd_command_error( machine );
- return;
- }
-
- cd.motor = 1;
-
- memset( cd.output, 0, 6 );
- matsucd_complete_cmd( machine, 0 );
- }
- break;
-
- case 0x04: /* motor on */
- {
- if ( cd.input_pos < 7 )
- return;
-
- cd.motor = 1;
-
- memset( cd.output, 0, 6 );
- matsucd_complete_cmd( machine, 0 );
- }
- break;
-
- case 0x05: /* motor off */
- {
- if ( cd.input_pos < 7 )
- return;
-
- /* stop CDDA audio if necessary */
- matsucd_cdda_stop(machine);
-
- cd.motor = 0;
-
- memset( cd.output, 0, 6 );
- matsucd_complete_cmd( machine, 0 );
- }
- break;
-
- case 0x09: /* play audio cd, LBA mode */
- {
- UINT32 lba, numblocks;
-
- if ( cd.input_pos < 7 )
- return;
-
- lba = cd.input[1];
- lba <<= 8;
- lba |= cd.input[2];
- lba <<= 8;
- lba |= cd.input[3];
-
- numblocks = cd.input[4];
- numblocks <<= 8;
- numblocks |= cd.input[5];
- numblocks <<= 8;
- numblocks |= cd.input[6];
-
- matsucd_cdda_play( machine, lba, numblocks );
-
- cd.motor = 1;
-
- memset( cd.output, 0, 6 );
- matsucd_complete_cmd( machine, 0 );
- }
- break;
-
- case 0x0a: /* play audio cd, MSF mode */
- {
- UINT32 start, end, lba_start, lba_end;
-
- if ( cd.input_pos < 7 )
- return;
-
- start = cd.input[1];
- start <<= 8;
- start |= cd.input[2];
- start <<= 8;
- start |= cd.input[3];
-
- end = cd.input[4];
- end <<= 8;
- end |= cd.input[5];
- end <<= 8;
- end |= cd.input[6];
-
- lba_start = MSF2LBA( start );
- lba_end = MSF2LBA( end );
-
- if ( end == 0xffffff )
- {
- lba_end = cdrom_get_track_start(cd.cdrom,cdrom_get_last_track(cd.cdrom)-1);
- lba_end += cdrom_get_toc(cd.cdrom)->tracks[cdrom_get_last_track(cd.cdrom)-1].frames;
- }
-
- if ( lba_end <= lba_start )
- {
- matsucd_cdda_stop(machine);
- }
- else
- {
- matsucd_cdda_play( machine, lba_start, lba_end - lba_start );
- cd.motor = 1;
- }
-
- memset( cd.output, 0, 6 );
- matsucd_complete_cmd( machine, 0 );
- }
- break;
-
- case 0x0b: /* play audio track and index */
- {
- UINT8 track_start = cd.input[1];
- UINT8 index_start = cd.input[2];
- UINT8 track_end = cd.input[3];
- UINT8 index_end = cd.input[4];
- UINT32 lba_start, lba_end;
-
- /* TODO: Add index support once the CDDA engine supports it */
- (void)index_start;
- (void)index_end;
-
- /* sanitize values */
- if ( track_start == 0 ) track_start++;
- if ( track_end == 0 ) track_end++;
- if ( track_end > cdrom_get_last_track(cd.cdrom) )
- track_end = cdrom_get_last_track(cd.cdrom);
-
- /* find the start and stop positions */
- lba_start = cdrom_get_track_start(cd.cdrom,track_start-1);
- lba_end = cdrom_get_track_start(cd.cdrom,track_end-1);
-
- lba_end += cdrom_get_toc(cd.cdrom)->tracks[track_end-1].frames;
-
- if ( lba_end <= lba_start )
- {
- matsucd_cdda_stop(machine);
- }
- else
- {
- matsucd_cdda_play( machine, lba_start, lba_end - lba_start );
- cd.motor = 1;
- }
-
- memset( cd.output, 0, 6 );
- matsucd_complete_cmd( machine, 0 );
- }
- break;
-
- case 0x81: /* status read */
- {
- UINT8 newstatus = cd.status;
-
- newstatus &= MATSU_STATUS_SUCCESS | MATSU_STATUS_ERROR | MATSU_STATUS_PLAYING;
- newstatus |= MATSU_STATUS_READY;
-
- if (cd.cdrom)
- {
- newstatus |= MATSU_STATUS_MEDIA;
- }
-
- if (cd.motor)
- newstatus |= MATSU_STATUS_MOTOR;
-
- cd.output[0] = newstatus;
-
- matsucd_set_status( machine, newstatus );
-
- matsucd_complete_cmd( machine, 1 );
- }
- break;
-
- case 0x82: /* error read */
- {
- if ( cd.input_pos < 7 )
- return;
-
- memset( cd.output, 0, 6 );
- matsucd_complete_cmd( machine, 6 );
- }
- break;
-
- case 0x84: /* set mode */
- {
- if ( cd.input_pos < 7 )
- return;
-
- cd.sector_size = cd.input[2];
- cd.sector_size <<= 8;
- cd.sector_size |= cd.input[3];
-
- memset( cd.output, 0, 6 );
- matsucd_complete_cmd( machine, 0 );
- }
- break;
-
- case 0x87: /* read SUBQ */
- {
- int msfmode;
- UINT32 lba;
- UINT8 track;
-
- if ( cd.input_pos < 7 )
- return;
-
- msfmode = (cd.input[1] & 0x02) ? 1 : 0;
-
- memset( cd.output, 0, 13 );
-
- cd.output[0] = matsucd_cdda_getstatus( machine, &lba );
-
- if ( lba > 0 )
- {
- UINT32 disk_pos;
- UINT32 track_pos;
-
- track = cdrom_get_track(cd.cdrom, lba);
-
- cd.output[1] = cdrom_get_adr_control(cd.cdrom, track);
- cd.output[2] = track+1;
- cd.output[3] = 0; /* index */
-
- disk_pos = lba;
- if ( msfmode ) disk_pos = LBA2MSF(disk_pos);
-
- cd.output[4] = (disk_pos >> 24) & 0xff;
- cd.output[5] = (disk_pos >> 16) & 0xff;
- cd.output[6] = (disk_pos >> 8) & 0xff;
- cd.output[7] = (disk_pos) & 0xff;
-
- track_pos = lba - cdrom_get_track_start(cd.cdrom, track);
- if ( msfmode ) track_pos = LBA2MSF(track_pos);
-
- cd.output[8] = (track_pos >> 24) & 0xff;
- cd.output[9] = (track_pos >> 16) & 0xff;
- cd.output[10] = (track_pos >> 8) & 0xff;
- cd.output[11] = (track_pos) & 0xff;
-
- /* TODO: UPC flag at offset 12 */
- cd.output[12] = 0;
- }
-
- matsucd_complete_cmd( machine, 13 );
- }
- break;
-
- case 0x89: /* read disk info */
- {
- UINT32 end;
-
- if ( cd.input_pos < 7 )
- return;
-
- memset( cd.output, 0, 5 );
-
- cd.output[0] = cdrom_get_last_track(cd.cdrom) ? 1 : 0;
- cd.output[1] = cdrom_get_last_track(cd.cdrom);
- end = cdrom_get_track_start(cd.cdrom,cd.output[1]-1);
- end += cdrom_get_toc(cd.cdrom)->tracks[cd.output[1]-1].frames;
- end = LBA2MSF(end);
- cd.output[2] = (end >> 16) & 0xff;
- cd.output[3] = (end >> 8) & 0xff;
- cd.output[4] = (end) & 0xff;
-
- matsucd_complete_cmd( machine, 5 );
- }
- break;
-
- case 0x8a: /* read toc */
- {
- UINT8 track;
- int msfmode;
- UINT32 track_start;
-
- if ( cd.input_pos < 7 )
- return;
-
- /* stop CDDA audio if necessary */
- matsucd_cdda_stop(machine);
-
- track = cd.input[2];
- msfmode = (cd.input[1] & 0x02) ? 1 : 0;
-
- if ( cd.cdrom == nullptr )
- {
- machine.logerror( "MATSUCD - Warning: Reading TOC without a CD!\n" );
- matsucd_command_error( machine );
- return;
- }
-
- if ( track > cdrom_get_last_track(cd.cdrom) )
- {
- machine.logerror( "MATSUCD - Warning: Reading invalid track entry from TOC!\n" );
- matsucd_command_error( machine );
- return;
- }
-
- memset( cd.output, 0, 7 );
-
- track_start = cdrom_get_track_start(cd.cdrom, track > 0 ? (track-1) : track );
- if ( msfmode ) track_start = LBA2MSF( track_start );
-
- cd.output[1] = cdrom_get_adr_control(cd.cdrom, track > 0 ? (track-1) : track);
- cd.output[2] = track;
- cd.output[3] = (track == 0 ) ? cdrom_get_last_track(cd.cdrom) : 0;
- cd.output[4] = (track_start >> 24) & 0xff;
- cd.output[5] = (track_start >> 16) & 0xff;
- cd.output[6] = (track_start >> 8) & 0xff;
- cd.output[7] = (track_start) & 0xff;
-
- cd.motor = 1;
-
- matsucd_complete_cmd( machine, 8 );
- }
- break;
-
- case 0x8b: /* pause audio */
- {
- if ( cd.input_pos < 7 )
- return;
-
- matsucd_cdda_pause( machine, (cd.input[1] == 0) ? 1 : 0 );
- memset( cd.output, 0, 7 );
- matsucd_complete_cmd( machine, 0 );
- }
- break;
-
- case 0xa3: /* front panel */
- {
- if ( cd.input_pos < 7 )
- return;
-
- /* TODO: ??? */
-
- memset( cd.output, 0, 7 );
- matsucd_complete_cmd( machine, 0 );
- }
- break;
-
- default:
- machine.logerror( "MATSUCD: Unknown/inimplemented command %08x\n", cmd );
- break;
- }
-}
diff --git a/src/devices/machine/matsucd.h b/src/devices/machine/matsucd.h
deleted file mode 100644
index 19a456760a6..00000000000
--- a/src/devices/machine/matsucd.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:smf, Mariusz Wojcieszek
-/***************************************************************************
-
- Matsushita/Panasonic CDR521/522 type CDROM drive emulation
-
-***************************************************************************/
-
-/* initialization */
-void matsucd_init( cdrom_image_device *cdrom_device, const char *cdda_tag );
-
-
-/* signaling */
-extern void matsucd_enable_w( int level ); /* /ENABLE pin */
-extern void matsucd_cmd_w( int level ); /* /CMD pin */
-extern int matsucd_stch_r( void ); /* /STCH pin */
-extern int matsucd_sten_r( void ); /* /STEN pin */
-extern int matsucd_scor_r( void ); /* /SCOR pin */
-
-/* callback for signal changes */
-extern void matsucd_set_status_enabled_callback( void (*sten_cb)( running_machine &machine, int level ) );
-extern void matsucd_set_status_changed_callback( void (*stch_cb)( running_machine &machine, int level ) );
-extern void matsucd_set_subcode_ready_callback( void (*scor_cb)( running_machine &machine, int level ) );
-
-/* data transfer routines */
-extern void matsucd_read_next_block( void );
-extern int matsucd_get_next_byte( UINT8 *data );
-
-/* main command interface */
-extern void matsucd_command_w( running_machine &machine, UINT8 data );
-extern UINT8 matsucd_response_r( running_machine &machine );
diff --git a/src/devices/machine/mc146818.h b/src/devices/machine/mc146818.h
index b7fffda3de7..a4651171179 100644
--- a/src/devices/machine/mc146818.h
+++ b/src/devices/machine/mc146818.h
@@ -172,7 +172,7 @@ private:
// internal state
UINT8 m_index;
- dynamic_buffer m_data;
+ std::vector<UINT8> m_data;
attotime m_last_refresh;
diff --git a/src/devices/machine/mc6846.cpp b/src/devices/machine/mc6846.cpp
index 18b9f723bfb..5958ba87f9b 100644
--- a/src/devices/machine/mc6846.cpp
+++ b/src/devices/machine/mc6846.cpp
@@ -178,7 +178,7 @@ inline void mc6846_device::update_cto()
m_old_cto = cto;
}
if ( !m_out_cto_cb.isnull() )
- m_out_cto_cb( (offs_t) 0, cto );
+ m_out_cto_cb( cto );
}
@@ -396,7 +396,7 @@ WRITE8_MEMBER(mc6846_device::write)
{
m_cp2_cpu = (data >> 3) & 1;
if ( !m_out_cp2_cb.isnull() )
- m_out_cp2_cb( (offs_t) 0, m_cp2_cpu );
+ m_out_cp2_cb( m_cp2_cpu );
}
else
logerror( "%s mc6846 acknowledge not implemented\n", machine().describe_context() );
diff --git a/src/devices/machine/mc6846.h b/src/devices/machine/mc6846.h
index bb198ee64d7..b174000b739 100644
--- a/src/devices/machine/mc6846.h
+++ b/src/devices/machine/mc6846.h
@@ -96,14 +96,14 @@ private:
/* CPU write to the outside through chip */
devcb_write8 m_out_port_cb; /* 8-bit output */
- devcb_write8 m_out_cp1_cb; /* 1-bit output */
- devcb_write8 m_out_cp2_cb; /* 1-bit output */
+ devcb_write_line m_out_cp1_cb; /* 1-bit output */
+ devcb_write_line m_out_cp2_cb; /* 1-bit output */
/* CPU read from the outside through chip */
devcb_read8 m_in_port_cb; /* 8-bit input */
/* asynchronous timer output to outside world */
- devcb_write8 m_out_cto_cb; /* 1-bit output */
+ devcb_write_line m_out_cto_cb; /* 1-bit output */
/* timer interrupt */
devcb_write_line m_irq_cb;
diff --git a/src/devices/machine/mccs1850.h b/src/devices/machine/mccs1850.h
index f7643f1465e..c029bc3e89b 100644
--- a/src/devices/machine/mccs1850.h
+++ b/src/devices/machine/mccs1850.h
@@ -22,6 +22,7 @@
#ifndef __MCCS1850__
#define __MCCS1850__
+#include "emu.h"
#include "dirtc.h"
diff --git a/src/devices/machine/mm58167.cpp b/src/devices/machine/mm58167.cpp
index 75e9e799004..148d97260e8 100644
--- a/src/devices/machine/mm58167.cpp
+++ b/src/devices/machine/mm58167.cpp
@@ -9,6 +9,7 @@
**********************************************************************/
#include "mm58167.h"
+#include "machine/timehelp.h"
//**************************************************************************
// LIVE DEVICE
@@ -91,11 +92,6 @@ void mm58167_device::device_reset()
}
-static inline UINT8 make_bcd(UINT8 data)
-{
- return ((data / 10) << 4) | (data % 10);
-}
-
//-------------------------------------------------
// device_timer - handler timer events
//-------------------------------------------------
@@ -124,8 +120,8 @@ void mm58167_device::device_timer(emu_timer &timer, device_timer_id id, int para
if ((m_regs[R_CTL_IRQCONTROL] & 0x80) && m_regs[R_CNT_MONTH] != old_month) set_irq(7); // every month
}
- m_regs[R_CNT_MILLISECONDS] = make_bcd(m_milliseconds % 10);
- m_regs[R_CNT_HUNDTENTHS] = make_bcd(m_milliseconds / 10);
+ m_regs[R_CNT_MILLISECONDS] = time_helper::make_bcd(m_milliseconds % 10);
+ m_regs[R_CNT_HUNDTENTHS] = time_helper::make_bcd(m_milliseconds / 10);
// 10Hz IRQ
if ((m_regs[R_CTL_IRQCONTROL] & 0x02) && (m_milliseconds % 100) == 0)
@@ -158,12 +154,12 @@ void mm58167_device::device_timer(emu_timer &timer, device_timer_id id, int para
void mm58167_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second)
{
- m_regs[R_CNT_SECONDS] = make_bcd(second); // seconds (BCD)
- m_regs[R_CNT_MINUTES] = make_bcd(minute); // minutes (BCD)
- m_regs[R_CNT_HOURS] = make_bcd(hour); // hour (BCD)
- m_regs[R_CNT_DAYOFWEEK] = make_bcd(day_of_week); // day of the week (BCD)
- m_regs[R_CNT_DAYOFMONTH] = make_bcd(day); // day of the month (BCD)
- m_regs[R_CNT_MONTH] = make_bcd(month); // month (BCD)
+ m_regs[R_CNT_SECONDS] = time_helper::make_bcd(second); // seconds (BCD)
+ m_regs[R_CNT_MINUTES] = time_helper::make_bcd(minute); // minutes (BCD)
+ m_regs[R_CNT_HOURS] = time_helper::make_bcd(hour); // hour (BCD)
+ m_regs[R_CNT_DAYOFWEEK] = time_helper::make_bcd(day_of_week); // day of the week (BCD)
+ m_regs[R_CNT_DAYOFMONTH] = time_helper::make_bcd(day); // day of the month (BCD)
+ m_regs[R_CNT_MONTH] = time_helper::make_bcd(month); // month (BCD)
}
void mm58167_device::set_irq(int bit)
diff --git a/src/devices/machine/mm58167.h b/src/devices/machine/mm58167.h
index 6a02497341d..ab1a1d70eb2 100644
--- a/src/devices/machine/mm58167.h
+++ b/src/devices/machine/mm58167.h
@@ -11,6 +11,7 @@
#ifndef __MM58167_H__
#define __MM58167_H__
+#include "emu.h"
#include "dirtc.h"
diff --git a/src/devices/machine/msm5832.cpp b/src/devices/machine/msm5832.cpp
index e87396bcee8..97e89eca2ff 100644
--- a/src/devices/machine/msm5832.cpp
+++ b/src/devices/machine/msm5832.cpp
@@ -145,6 +145,8 @@ void msm5832_device::device_timer(emu_timer &timer, device_timer_id id, int para
void msm5832_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second)
{
+ if (LOG) logerror("MSM5832 Clock Update: %d.%d.%d %d %d:%d:%d\n", year, month, day, day_of_week, hour, minute, second);
+
write_counter(REGISTER_Y1, year);
write_counter(REGISTER_MO1, month);
write_counter(REGISTER_D1, day);
@@ -180,7 +182,7 @@ READ8_MEMBER( msm5832_device::data_r )
}
}
- if (LOG) logerror("MSM5832 '%s' Register Read %01x: %01x\n", tag(), m_address, data & 0x0f);
+ if (LOG) logerror("MSM5832 Register Read %01x: %01x\n", m_address, data & 0x0f);
return data & 0x0f;
}
@@ -192,7 +194,7 @@ READ8_MEMBER( msm5832_device::data_r )
WRITE8_MEMBER( msm5832_device::data_w )
{
- if (LOG) logerror("MSM5832 '%s' Register Write %01x: %01x\n", tag(), m_address, data & 0x0f);
+ if (LOG) logerror("MSM5832 Register Write %01x: %01x\n", m_address, data & 0x0f);
if (m_cs && m_write)
{
@@ -217,7 +219,7 @@ WRITE8_MEMBER( msm5832_device::data_w )
void msm5832_device::address_w(UINT8 data)
{
- if (LOG) logerror("MSM5832 '%s' Address: %01x\n", tag(), data & 0x0f);
+ if (LOG) logerror("MSM5832 Address: %01x\n", data & 0x0f);
m_address = data & 0x0f;
}
@@ -229,7 +231,7 @@ void msm5832_device::address_w(UINT8 data)
WRITE_LINE_MEMBER( msm5832_device::adj_w )
{
- if (LOG) logerror("MSM5832 '%s' 30 ADJ: %u\n", tag(), state);
+ if (LOG) logerror("MSM5832 30 ADJ: %u\n", state);
if (state)
{
@@ -244,7 +246,7 @@ WRITE_LINE_MEMBER( msm5832_device::adj_w )
WRITE_LINE_MEMBER( msm5832_device::test_w )
{
- if (LOG) logerror("MSM5832 '%s' TEST: %u\n", tag(), state);
+ if (LOG) logerror("MSM5832 TEST: %u\n", state);
}
@@ -254,7 +256,7 @@ WRITE_LINE_MEMBER( msm5832_device::test_w )
WRITE_LINE_MEMBER( msm5832_device::hold_w )
{
- if (LOG) logerror("MSM5832 '%s' HOLD: %u\n", tag(), state);
+ if (LOG) logerror("MSM5832 HOLD: %u\n", state);
m_hold = state;
}
@@ -266,7 +268,7 @@ WRITE_LINE_MEMBER( msm5832_device::hold_w )
WRITE_LINE_MEMBER( msm5832_device::read_w )
{
- if (LOG) logerror("MSM5832 '%s' READ: %u\n", tag(), state);
+ if (LOG) logerror("MSM5832 READ: %u\n", state);
m_read = state;
}
@@ -278,7 +280,7 @@ WRITE_LINE_MEMBER( msm5832_device::read_w )
WRITE_LINE_MEMBER( msm5832_device::write_w )
{
- if (LOG) logerror("MSM5832 '%s' WR: %u\n", tag(), state);
+ if (LOG) logerror("MSM5832 WR: %u\n", state);
m_write = state;
}
@@ -290,7 +292,7 @@ WRITE_LINE_MEMBER( msm5832_device::write_w )
WRITE_LINE_MEMBER( msm5832_device::cs_w )
{
- if (LOG) logerror("MSM5832 '%s' CS: %u\n", tag(), state);
+ if (LOG) logerror("MSM5832 CS: %u\n", state);
m_cs = state;
}
diff --git a/src/devices/machine/msm5832.h b/src/devices/machine/msm5832.h
index aeb6e512f01..d436d4ccc78 100644
--- a/src/devices/machine/msm5832.h
+++ b/src/devices/machine/msm5832.h
@@ -23,6 +23,7 @@
#ifndef __MSM5832__
#define __MSM5832__
+#include "emu.h"
#include "dirtc.h"
diff --git a/src/devices/machine/msm58321.h b/src/devices/machine/msm58321.h
index 0013f7901cf..b4f9de48053 100644
--- a/src/devices/machine/msm58321.h
+++ b/src/devices/machine/msm58321.h
@@ -22,6 +22,7 @@
#ifndef __MSM58321__
#define __MSM58321__
+#include "emu.h"
#include "dirtc.h"
diff --git a/src/devices/machine/msm6242.h b/src/devices/machine/msm6242.h
index f59902474c4..149d58eea38 100644
--- a/src/devices/machine/msm6242.h
+++ b/src/devices/machine/msm6242.h
@@ -11,6 +11,7 @@
#ifndef __MSM6242DEV_H__
#define __MSM6242DEV_H__
+#include "emu.h"
#include "dirtc.h"
diff --git a/src/devices/machine/nscsi_s1410.cpp b/src/devices/machine/nscsi_s1410.cpp
index b486b4994e9..f1725329d9d 100644
--- a/src/devices/machine/nscsi_s1410.cpp
+++ b/src/devices/machine/nscsi_s1410.cpp
@@ -60,7 +60,7 @@ void nscsi_s1410_device::scsi_command()
blocks = (bytes_per_sector == 256) ? 32 : 17;
int track_length = blocks*bytes_per_sector;
- dynamic_buffer data(track_length);
+ std::vector<UINT8> data(track_length);
memset(&data[0], 0xc6, track_length);
if(!hard_disk_write(harddisk, lba, &data[0])) {
diff --git a/src/devices/machine/pcf8593.h b/src/devices/machine/pcf8593.h
index addf666d9fb..b2b09f9ebd0 100644
--- a/src/devices/machine/pcf8593.h
+++ b/src/devices/machine/pcf8593.h
@@ -11,6 +11,7 @@
#ifndef __PCF8593_H__
#define __PCF8593_H__
+#include "emu.h"
#include "dirtc.h"
diff --git a/src/devices/machine/pckeybrd.cpp b/src/devices/machine/pckeybrd.cpp
index 2a1d4719013..92e3bd973fd 100644
--- a/src/devices/machine/pckeybrd.cpp
+++ b/src/devices/machine/pckeybrd.cpp
@@ -893,7 +893,7 @@ WRITE8_MEMBER(at_keyboard_device::write)
unicode_char_to_at_keycode
***************************************************************************/
-UINT8 pc_keyboard_device::unicode_char_to_at_keycode(unicode_char ch)
+UINT8 pc_keyboard_device::unicode_char_to_at_keycode(char32_t ch)
{
UINT8 b;
switch(ch)
@@ -1034,7 +1034,7 @@ UINT8 pc_keyboard_device::unicode_char_to_at_keycode(unicode_char ch)
queue_chars
***************************************************************************/
-int pc_keyboard_device::queue_chars(const unicode_char *text, size_t text_len)
+int pc_keyboard_device::queue_chars(const char32_t *text, size_t text_len)
{
int i;
UINT8 b;
@@ -1293,7 +1293,7 @@ INPUT_PORTS_END
Inputx stuff
***************************************************************************/
-bool pc_keyboard_device::accept_char(unicode_char ch)
+bool pc_keyboard_device::accept_char(char32_t ch)
{
return unicode_char_to_at_keycode(ch) != 0;
}
diff --git a/src/devices/machine/pckeybrd.h b/src/devices/machine/pckeybrd.h
index 69a133df2c6..58861fc288c 100644
--- a/src/devices/machine/pckeybrd.h
+++ b/src/devices/machine/pckeybrd.h
@@ -49,13 +49,13 @@ protected:
private:
void polling(void);
UINT32 readport(int port);
- UINT8 unicode_char_to_at_keycode(unicode_char ch);
+ UINT8 unicode_char_to_at_keycode(char32_t ch);
virtual void standard_scancode_insert(int our_code, int pressed);
virtual void extended_scancode_insert(int code, int pressed) { }
int queue_size(void);
- int queue_chars(const unicode_char *text, size_t text_len);
- bool accept_char(unicode_char ch);
+ int queue_chars(const char32_t *text, size_t text_len);
+ bool accept_char(char32_t ch);
bool charqueue_empty();
bool m_on;
diff --git a/src/devices/machine/pit8253.cpp b/src/devices/machine/pit8253.cpp
index f542f3753b8..978cb6a50b5 100644
--- a/src/devices/machine/pit8253.cpp
+++ b/src/devices/machine/pit8253.cpp
@@ -317,7 +317,7 @@ void pit8253_device::simulate2(pit8253_timer *timer, INT64 elapsed_cycles)
static const UINT32 CYCLES_NEVER = (0xffffffff);
UINT32 cycles_to_output = 0;
- LOG2(("pit8253: simulate2(): simulating %d cycles for %d in mode %d, bcd = %d, phase = %d, gate = %d, output %d, value = 0x%04x\n",
+ LOG2(("simulate2(): simulating %d cycles for %d in mode %d, bcd = %d, phase = %d, gate = %d, output %d, value = 0x%04x\n",
(int)elapsed_cycles, timer->index, mode, bcd, timer->phase, timer->gate, timer->output, timer->value));
switch (mode)
@@ -698,7 +698,7 @@ void pit8253_device::simulate2(pit8253_timer *timer, INT64 elapsed_cycles)
timer->updatetimer->adjust(next_fire_time - machine().time(), timer->index);
}
- LOG2(("pit8253: simulate2(): simulating %d cycles for %d in mode %d, bcd = %d, phase = %d, gate = %d, output %d, value = 0x%04x, cycles_to_output = %04x\n",
+ LOG2(("simulate2(): simulating %d cycles for %d in mode %d, bcd = %d, phase = %d, gate = %d, output %d, value = 0x%04x, cycles_to_output = %04x\n",
(int)elapsed_cycles, timer->index, mode, bcd, timer->phase, timer->gate, timer->output, timer->value, cycles_to_output));
}
@@ -723,7 +723,7 @@ void pit8253_device::update(pit8253_timer *timer)
attotime elapsed_time = now - timer->last_updated;
INT64 elapsed_cycles = elapsed_time.as_double() * timer->clockin;
- LOG1(("pit8253: update(): timer %d, %d elapsed_cycles\n", timer->index, elapsed_cycles));
+ LOG1(("update(): timer %d, %d elapsed_cycles\n", timer->index, elapsed_cycles));
if (timer->clockin)
timer->last_updated += elapsed_cycles * attotime::from_hz(timer->clockin);
@@ -739,7 +739,7 @@ void pit8253_device::update(pit8253_timer *timer)
mask this bit off. */
UINT16 pit8253_device::masked_value(pit8253_timer *timer)
{
- LOG2(("pit8253: masked_value\n"));
+ LOG2(("masked_value\n"));
if (CTRL_MODE(timer->control) == 3)
return timer->value & 0xfffe;
return timer->value;
@@ -756,7 +756,7 @@ READ8_MEMBER( pit8253_device::read )
UINT8 data;
UINT16 value;
- LOG2(("pit8253_r(): offset %d\n", offset));
+ LOG2(("read(): offset %d\n", offset));
if (timer == nullptr)
{
@@ -816,7 +816,7 @@ READ8_MEMBER( pit8253_device::read )
}
}
- LOG2(("pit8253: read(): offset=%d data=0x%02x\n", offset, data));
+ LOG2(("read(): offset=%d data=0x%02x\n", offset, data));
return data;
}
@@ -825,7 +825,7 @@ READ8_MEMBER( pit8253_device::read )
void pit8253_device::load_count(pit8253_timer *timer, UINT16 newcount)
{
int mode = CTRL_MODE(timer->control);
- LOG1(("pit8253: load_count(): %04x\n", newcount));
+ LOG1(("load_count(): %04x\n", newcount));
if (newcount == 1)
{
@@ -912,7 +912,7 @@ void pit8253_device::readback_command(UINT8 data)
void pit8254_device::readback_command(UINT8 data)
{
- LOG1(("pit8253: write(): readback %02x\n", data & 0x3f));
+ LOG1(("write(): readback %02x\n", data & 0x3f));
/* Bit 0 of data must be 0. Todo: find out what the hardware does if it isn't. */
int read_command = (data >> 4) & 3;
@@ -933,7 +933,7 @@ WRITE8_MEMBER( pit8253_device::write )
{
pit8253_timer *timer = get_timer(offset);
- LOG2(("pit8253: write(): offset=%d data=0x%02x\n", offset, data));
+ LOG2(("write(): offset=%d data=0x%02x\n", offset, data));
if (timer == nullptr)
{
@@ -949,7 +949,7 @@ WRITE8_MEMBER( pit8253_device::write )
if (CTRL_ACCESS(data) == 0)
{
- LOG1(("pit8253: write(): timer=%d readback\n", (data >> 6) & 3));
+ LOG1(("write(): timer=%d readback\n", (data >> 6) & 3));
/* Latch current timer value */
/* Experimentally verified: this command does not affect the mode control register */
@@ -957,7 +957,7 @@ WRITE8_MEMBER( pit8253_device::write )
}
else
{
- LOG1(("pit8253: write(): timer=%d bytes=%d mode=%d bcd=%d\n", (data >> 6) & 3, (data >> 4) & 3, (data >> 1) & 7, data & 1));
+ LOG1(("write(): timer=%d bytes=%d mode=%d bcd=%d\n", (data >> 6) & 3, (data >> 4) & 3, (data >> 1) & 7, data & 1));
timer->control = (data & 0x3f);
timer->null_count = 1;
@@ -1045,7 +1045,7 @@ void pit8253_device::gate_w(int gate, int state)
if (timer == nullptr)
return;
- LOG2(("pit8253 : gate_w(): gate=%d state=%d\n", gate, state));
+ LOG2(("gate_w(): gate=%d state=%d\n", gate, state));
if (state != timer->gate)
{
@@ -1084,7 +1084,7 @@ void pit8253_device::set_clockin(int timerno, double new_clockin)
pit8253_timer *timer = get_timer(timerno);
assert(timer != nullptr);
- LOG2(("pit8253_set_clockin(): PIT timer=%d, clockin = %f\n", timerno, new_clockin));
+ LOG2(("set_clockin(): PIT timer=%d, clockin = %f\n", timerno, new_clockin));
update(timer);
timer->clockin = new_clockin;
@@ -1097,7 +1097,7 @@ void pit8253_device::set_clock_signal(int timerno, int state)
pit8253_timer *timer = get_timer(timerno);
assert(timer != nullptr);
- LOG2(("pit8253_set_clock_signal(): PIT timer=%d, state = %d\n", timerno, state));
+ LOG2(("set_clock_signal(): PIT timer=%d, state = %d\n", timerno, state));
/* Trigger on low to high transition */
if (!timer->clock && state)
diff --git a/src/devices/machine/ram.h b/src/devices/machine/ram.h
index 73e7430a6ce..73a62b61f8d 100644
--- a/src/devices/machine/ram.h
+++ b/src/devices/machine/ram.h
@@ -77,7 +77,7 @@ protected:
private:
// device state
UINT32 m_size;
- dynamic_buffer m_pointer;
+ std::vector<UINT8> m_pointer;
// device config
const char *m_default_size;
diff --git a/src/devices/machine/roc10937.cpp b/src/devices/machine/roc10937.cpp
index c76e02f13e6..c932002e310 100644
--- a/src/devices/machine/roc10937.cpp
+++ b/src/devices/machine/roc10937.cpp
@@ -125,8 +125,6 @@ static const int roc10937poslut[]=
0//15
};
-const device_type ROC10937 = &device_creator<roc10937_t>;
-
rocvfd_t::rocvfd_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) :
device_t(mconfig, type, name, tag, owner, clock, shortname, source)
{
@@ -246,6 +244,8 @@ void rocvfd_t::shift_clock(int state)
}
///////////////////////////////////////////////////////////////////////////
+const device_type ROC10937 = &device_creator<roc10937_t>;
+
roc10937_t::roc10937_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: rocvfd_t(mconfig, ROC10937, "Rockwell 10937 VFD controller and compatible", tag, owner, clock, "roc10937", __FILE__)
{
@@ -260,6 +260,22 @@ msc1937_t::msc1937_t(const machine_config &mconfig, const char *tag, device_t *o
m_port_val=0;
}
+const device_type MIC10937 = &device_creator<mic10937_t>;
+
+mic10937_t::mic10937_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : rocvfd_t(mconfig, MIC10937, "Micrel MIC10937 VFD controller", tag, owner, clock, "mic10937", __FILE__)
+{
+ m_port_val=0;
+}
+
+const device_type S16LF01 = &device_creator<s16lf01_t>;
+
+s16lf01_t::s16lf01_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : rocvfd_t(mconfig, S16LF01, "Samsung 16LF01 Series VFD controller and compatible", tag, owner, clock, "s16lf01", __FILE__)
+{
+ m_port_val=0;
+}
+
void rocvfd_t::write_char(int data)
{
if ( data & 0x80 )
@@ -378,11 +394,3 @@ void roc10957_t::write_char(int data)
}
}
}
-
-const device_type S16LF01 = &device_creator<s16lf01_t>;
-
-s16lf01_t::s16lf01_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
- : rocvfd_t(mconfig, S16LF01, "Samsung 16LF01 Series VFD controller and compatible", tag, owner, clock, "s16lf01", __FILE__)
-{
- m_port_val=0;
-}
diff --git a/src/devices/machine/roc10937.h b/src/devices/machine/roc10937.h
index 3acf90726b0..403b1bc98de 100644
--- a/src/devices/machine/roc10937.h
+++ b/src/devices/machine/roc10937.h
@@ -40,6 +40,16 @@
#define MCFG_MSC1937_REMOVE(_tag) \
MCFG_DEVICE_REMOVE(_tag)
+#define MCFG_MIC10937_ADD(_tag,_val) \
+ MCFG_DEVICE_ADD(_tag, MIC10937,60)\
+ MCFG_MIC10937_PORT(_val)
+
+#define MCFG_MIC10937_PORT(_val) \
+ MCFG_ROC10937_PORT(_val)
+
+#define MCFG_MIC10937_REMOVE(_tag) \
+ MCFG_DEVICE_REMOVE(_tag)
+
#define MCFG_S16LF01_ADD(_tag,_val) \
MCFG_DEVICE_ADD(_tag, S16LF01,60)\
MCFG_S16LF01_PORT(_val)
@@ -95,6 +105,11 @@ public:
msc1937_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
};
+class mic10937_t : public rocvfd_t {
+public:
+ mic10937_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
class roc10957_t : public rocvfd_t {
public:
roc10957_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
@@ -109,6 +124,7 @@ public:
extern const device_type ROC10937;
extern const device_type MSC1937;
+extern const device_type MIC10937;
extern const device_type ROC10957;
extern const device_type S16LF01;
diff --git a/src/devices/machine/rp5c01.cpp b/src/devices/machine/rp5c01.cpp
index f3112eab607..b2280909fa5 100644
--- a/src/devices/machine/rp5c01.cpp
+++ b/src/devices/machine/rp5c01.cpp
@@ -201,6 +201,12 @@ void rp5c01_device::device_start()
m_16hz_timer->adjust(attotime::from_hz(clock() / 1024), 0, attotime::from_hz(clock() / 1024));
}
+ memset(m_reg, 0, sizeof(m_reg));
+ memset(m_ram, 0, sizeof(m_ram));
+
+ // 24 hour mode
+ m_reg[MODE01][REGISTER_12_24_SELECT] = 1;
+
// state saving
save_item(NAME(m_reg[MODE00]));
save_item(NAME(m_reg[MODE01]));
@@ -214,20 +220,6 @@ void rp5c01_device::device_start()
//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void rp5c01_device::device_reset()
-{
- memset(m_reg, 0, sizeof(m_reg));
- memset(m_ram, 0, sizeof(m_ram));
-
- // 24 hour mode
- m_reg[MODE01][REGISTER_12_24_SELECT] = 1;
-}
-
-
-//-------------------------------------------------
// device_timer - handler timer events
//-------------------------------------------------
diff --git a/src/devices/machine/rp5c01.h b/src/devices/machine/rp5c01.h
index cba2566fcab..0043cc19b6c 100644
--- a/src/devices/machine/rp5c01.h
+++ b/src/devices/machine/rp5c01.h
@@ -23,6 +23,7 @@
#ifndef __RP5C01__
#define __RP5C01__
+#include "emu.h"
#include "dirtc.h"
@@ -64,7 +65,6 @@ public:
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;
// device_rtc_interface overrides
diff --git a/src/devices/machine/rp5c15.h b/src/devices/machine/rp5c15.h
index 4aa3c721662..4a10eaeae3c 100644
--- a/src/devices/machine/rp5c15.h
+++ b/src/devices/machine/rp5c15.h
@@ -23,6 +23,7 @@
#ifndef __RP5C15__
#define __RP5C15__
+#include "emu.h"
#include "dirtc.h"
diff --git a/src/devices/machine/rtc4543.h b/src/devices/machine/rtc4543.h
index bd94c2eb918..9a252424eb2 100644
--- a/src/devices/machine/rtc4543.h
+++ b/src/devices/machine/rtc4543.h
@@ -12,6 +12,7 @@
#ifndef __RTC4543_H__
#define __RTC4543_H__
+#include "emu.h"
#include "dirtc.h"
diff --git a/src/devices/machine/s3c2400.cpp b/src/devices/machine/s3c2400.cpp
index 157e13bbf85..8b9d4da016c 100644
--- a/src/devices/machine/s3c2400.cpp
+++ b/src/devices/machine/s3c2400.cpp
@@ -12,7 +12,6 @@
#include "cpu/arm7/arm7.h"
#include "cpu/arm7/arm7core.h"
#include "machine/s3c2400.h"
-#include "sound/dac.h"
#define VERBOSE_LEVEL ( 0 )
diff --git a/src/devices/machine/s3c2410.cpp b/src/devices/machine/s3c2410.cpp
index 24d6664dea3..c036b1f362c 100644
--- a/src/devices/machine/s3c2410.cpp
+++ b/src/devices/machine/s3c2410.cpp
@@ -12,7 +12,6 @@
#include "cpu/arm7/arm7.h"
#include "cpu/arm7/arm7core.h"
#include "machine/s3c2410.h"
-#include "sound/dac.h"
#define VERBOSE_LEVEL ( 0 )
diff --git a/src/devices/machine/s3c2440.cpp b/src/devices/machine/s3c2440.cpp
index fece3da05ab..9ad23516c8d 100644
--- a/src/devices/machine/s3c2440.cpp
+++ b/src/devices/machine/s3c2440.cpp
@@ -12,7 +12,6 @@
#include "cpu/arm7/arm7.h"
#include "cpu/arm7/arm7core.h"
#include "machine/s3c2440.h"
-#include "sound/dac.h"
#define VERBOSE_LEVEL ( 0 )
diff --git a/src/devices/machine/s3c44b0.cpp b/src/devices/machine/s3c44b0.cpp
index bf81606cf12..7660918e1a5 100644
--- a/src/devices/machine/s3c44b0.cpp
+++ b/src/devices/machine/s3c44b0.cpp
@@ -12,7 +12,6 @@
#include "cpu/arm7/arm7.h"
#include "cpu/arm7/arm7core.h"
#include "machine/s3c44b0.h"
-#include "sound/dac.h"
#include "coreutil.h"
#define VERBOSE_LEVEL ( 0 )
diff --git a/src/devices/machine/serflash.h b/src/devices/machine/serflash.h
index 9d3654fc9c3..e72432cc109 100644
--- a/src/devices/machine/serflash.h
+++ b/src/devices/machine/serflash.h
@@ -88,7 +88,7 @@ protected:
UINT16 m_flash_page_index;
- dynamic_buffer m_flashwritemap;
+ std::vector<UINT8> m_flashwritemap;
UINT8 m_last_flash_cmd;
diff --git a/src/devices/machine/stvcd.cpp b/src/devices/machine/stvcd.cpp
index aed8d46aea1..84b9cd8fb51 100644
--- a/src/devices/machine/stvcd.cpp
+++ b/src/devices/machine/stvcd.cpp
@@ -1540,7 +1540,7 @@ void saturn_state::cd_free_block(blockT *blktofree)
{
INT32 i;
- CDROM_LOG(("cd_free_block: %x\n", (UINT32)(FPTR)blktofree))
+ CDROM_LOG(("cd_free_block: %x\n", (UINT32)(uintptr_t)blktofree))
if(blktofree == nullptr)
{
@@ -2142,7 +2142,7 @@ void saturn_state::make_dir_current(UINT32 fad)
{
int i;
UINT32 nextent, numentries;
- dynamic_buffer sect(MAX_DIR_SIZE);
+ std::vector<UINT8> sect(MAX_DIR_SIZE);
direntryT *curentry;
memset(&sect[0], 0, MAX_DIR_SIZE);
diff --git a/src/devices/machine/timehelp.h b/src/devices/machine/timehelp.h
new file mode 100644
index 00000000000..38adfdee502
--- /dev/null
+++ b/src/devices/machine/timehelp.h
@@ -0,0 +1,51 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles,smf
+/***************************************************************************
+
+ timehelp.h
+
+ Assorted shared functionality between timekeeping chips and RTCs.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef SRC_DEVICES_MACHINE_TIMEHELP_H
+#define SRC_DEVICES_MACHINE_TIMEHELP_H
+
+class time_helper
+{
+public:
+ static inline UINT8 make_bcd(UINT8 data)
+ {
+ return (((data / 10) % 10) << 4) + (data % 10);
+ }
+
+ static inline UINT8 from_bcd(UINT8 data)
+ {
+ return (((data >> 4) & 15) * 10) + (data & 15);
+ }
+
+ static int inc_bcd(UINT8 *data, int mask, int min, int max)
+ {
+ int bcd = (*data + 1) & mask;
+ int carry = 0;
+
+ if ((bcd & 0x0f) > 9)
+ {
+ bcd &= 0xf0;
+ bcd += 0x10;
+ if (bcd > max)
+ {
+ bcd = min;
+ carry = 1;
+ }
+ }
+
+ *data = (*data & ~mask) | (bcd & mask);
+ return carry;
+ }
+
+};
+
+#endif // SRC_DEVICES_MACHINE_TIMEHELP_H \ No newline at end of file
diff --git a/src/devices/machine/timekpr.cpp b/src/devices/machine/timekpr.cpp
index 4b87d43ff69..e11cd089b1c 100644
--- a/src/devices/machine/timekpr.cpp
+++ b/src/devices/machine/timekpr.cpp
@@ -16,7 +16,7 @@
#include "emu.h"
#include "machine/timekpr.h"
-
+#include "machine/timehelp.h"
// device type definition
const device_type M48T02 = &device_creator<m48t02_device>;
@@ -63,39 +63,6 @@ const device_type MK48T12 = &device_creator<mk48t12_device>;
INLINE FUNCTIONS
***************************************************************************/
-static inline UINT8 make_bcd(UINT8 data)
-{
- return ( ( ( data / 10 ) % 10 ) << 4 ) + ( data % 10 );
-}
-
-static inline UINT8 from_bcd( UINT8 data )
-{
- return ( ( ( data >> 4 ) & 15 ) * 10 ) + ( data & 15 );
-}
-
-static int inc_bcd( UINT8 *data, int mask, int min, int max )
-{
- int bcd;
- int carry;
-
- bcd = ( *( data ) + 1 ) & mask;
- carry = 0;
-
- if( ( bcd & 0x0f ) > 9 )
- {
- bcd &= 0xf0;
- bcd += 0x10;
- if( bcd > max )
- {
- bcd = min;
- carry = 1;
- }
- }
-
- *( data ) = ( *( data ) & ~mask ) | ( bcd & mask );
- return carry;
-}
-
static void counter_to_ram( UINT8 *data, int offset, int counter )
{
if( offset >= 0 )
@@ -233,14 +200,14 @@ void timekeeper_device::device_start()
machine().base_datetime(systime);
m_control = 0;
- m_seconds = make_bcd( systime.local_time.second );
- m_minutes = make_bcd( systime.local_time.minute );
- m_hours = make_bcd( systime.local_time.hour );
- m_day = make_bcd( systime.local_time.weekday + 1 );
- m_date = make_bcd( systime.local_time.mday );
- m_month = make_bcd( systime.local_time.month + 1 );
- m_year = make_bcd( systime.local_time.year % 100 );
- m_century = make_bcd( systime.local_time.year / 100 );
+ m_seconds = time_helper::make_bcd( systime.local_time.second );
+ m_minutes = time_helper::make_bcd( systime.local_time.minute );
+ m_hours = time_helper::make_bcd( systime.local_time.hour );
+ m_day = time_helper::make_bcd( systime.local_time.weekday + 1 );
+ m_date = time_helper::make_bcd( systime.local_time.mday );
+ m_month = time_helper::make_bcd( systime.local_time.month + 1 );
+ m_year = time_helper::make_bcd( systime.local_time.year % 100 );
+ m_century = time_helper::make_bcd( systime.local_time.year / 100 );
m_data.resize( m_size );
save_item( NAME(m_control) );
@@ -298,14 +265,14 @@ void timekeeper_device::device_timer(emu_timer &timer, device_timer_id id, int p
return;
}
- int carry = inc_bcd( &m_seconds, MASK_SECONDS, 0x00, 0x59 );
+ int carry = time_helper::inc_bcd( &m_seconds, MASK_SECONDS, 0x00, 0x59 );
if( carry )
{
- carry = inc_bcd( &m_minutes, MASK_MINUTES, 0x00, 0x59 );
+ carry = time_helper::inc_bcd( &m_minutes, MASK_MINUTES, 0x00, 0x59 );
}
if( carry )
{
- carry = inc_bcd( &m_hours, MASK_HOURS, 0x00, 0x23 );
+ carry = time_helper::inc_bcd( &m_hours, MASK_HOURS, 0x00, 0x23 );
}
if( carry )
@@ -313,10 +280,10 @@ void timekeeper_device::device_timer(emu_timer &timer, device_timer_id id, int p
UINT8 maxdays;
static const UINT8 daysinmonth[] = { 0x31, 0x28, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0x31, 0x30, 0x31 };
- inc_bcd( &m_day, MASK_DAY, 0x01, 0x07 );
+ time_helper::inc_bcd( &m_day, MASK_DAY, 0x01, 0x07 );
- UINT8 month = from_bcd( m_month );
- UINT8 year = from_bcd( m_year );
+ UINT8 month = time_helper::from_bcd( m_month );
+ UINT8 year = time_helper::from_bcd( m_year );
if( month == 2 && ( year % 4 ) == 0 )
{
@@ -331,19 +298,19 @@ void timekeeper_device::device_timer(emu_timer &timer, device_timer_id id, int p
maxdays = 0x31;
}
- carry = inc_bcd( &m_date, MASK_DATE, 0x01, maxdays );
+ carry = time_helper::inc_bcd( &m_date, MASK_DATE, 0x01, maxdays );
}
if( carry )
{
- carry = inc_bcd( &m_month, MASK_MONTH, 0x01, 0x12 );
+ carry = time_helper::inc_bcd( &m_month, MASK_MONTH, 0x01, 0x12 );
}
if( carry )
{
- carry = inc_bcd( &m_year, MASK_YEAR, 0x00, 0x99 );
+ carry = time_helper::inc_bcd( &m_year, MASK_YEAR, 0x00, 0x99 );
}
if( carry )
{
- carry = inc_bcd( &m_century, MASK_CENTURY, 0x00, 0x99 );
+ carry = time_helper::inc_bcd( &m_century, MASK_CENTURY, 0x00, 0x99 );
if( type() == M48T35 ||
type() == M48T58 )
diff --git a/src/devices/machine/timekpr.h b/src/devices/machine/timekpr.h
index f6ecb8dcbfc..e0e9aa6e60d 100644
--- a/src/devices/machine/timekpr.h
+++ b/src/devices/machine/timekpr.h
@@ -91,7 +91,7 @@ private:
UINT8 m_year;
UINT8 m_century;
- dynamic_buffer m_data;
+ std::vector<UINT8> m_data;
optional_region_ptr<UINT8> m_default_data;
protected:
diff --git a/src/devices/machine/upd1990a.h b/src/devices/machine/upd1990a.h
index 9071d843cc2..a526e920017 100644
--- a/src/devices/machine/upd1990a.h
+++ b/src/devices/machine/upd1990a.h
@@ -21,6 +21,7 @@
#ifndef __UPD1990A__
#define __UPD1990A__
+#include "emu.h"
#include "dirtc.h"
diff --git a/src/devices/machine/z80scc.cpp b/src/devices/machine/z80scc.cpp
index 3d6aa9cf19e..251596f6fac 100644
--- a/src/devices/machine/z80scc.cpp
+++ b/src/devices/machine/z80scc.cpp
@@ -53,10 +53,10 @@ DONE (x) (p=partly) NMOS CMOS ESCC EMSCC
DPLL clock recov Y Y Y Y
-- Additional features CMOS versions -----------------------------------
x Status FIFO N Y Y Y
- SWI ack feat N Y Y Y
+ x SWI ack feat N Y Y Y
higher bps w ext DPLL N 32Mbps 32Mbps 32Mbps
-- Additional features 85C30 -------------------------------------------
- New WR7 feat N 85C30 Y Y
+ x New WR7 feat N 85C30 Y Y
Improved SDLC N 85C30 Y Y
Improved reg handl N 85C30 Y Y
Improved auto feat N 85C30 Y Y
@@ -81,9 +81,11 @@ DONE (x) (p=partly) NMOS CMOS ESCC EMSCC
#define VERBOSE 0
#define LOGPRINT(x) do { if (VERBOSE) logerror x; } while (0)
#define LOG(x) LOGPRINT(x)
-#define LOGR(x)
+#define LOGR(x) LOGPRINT(x)
#define LOGSETUP(x) LOGPRINT(x)
-#define LOGRCV(x) LOGPRINT(x)
+#define LOGINT(x) {} LOGPRINT(x)
+#define LOGTX(x) {} LOGPRINT(x)
+#define LOGRCV(x){}
#if VERBOSE == 2
#define logerror printf
#endif
@@ -250,6 +252,8 @@ void z80scc_device::device_start()
// state saving
save_item(NAME(m_int_state));
+ save_item(NAME(m_int_source));
+ save_item(NAME(m_wr9));
save_item(NAME(m_wr0_ptrbits));
LOG((" - SCC variant %02x\n", m_variant));
}
@@ -263,40 +267,58 @@ void z80scc_device::device_reset()
{
LOG(("%s %s \n",tag(), FUNCNAME));
+ // Do channel reset on both channels
m_chanA->reset();
m_chanB->reset();
+
+ // Fix hardware reset values for registers where it differs from channel reset values
+ m_wr9 &= 0x3c;
+ m_wr9 |= 0xc0;
+ m_chanA->m_wr10 = 0x00;
+ m_chanB->m_wr10 = 0x00;
+ m_chanA->m_wr11 = 0x08;
+ m_chanB->m_wr11 = 0x08;
+ m_chanA->m_wr14 &= 0xf0;
+ m_chanA->m_wr14 |= 0x30;
+ m_chanB->m_wr14 &= 0xf0;
+ m_chanB->m_wr14 |= 0x30;
}
/*
* Interrupts
Each of the SCC's two channels contain three sources of interrupts, making a total of six interrupt
sources. These three sources of interrupts are: 1) Receiver, 2) Transmitter, and 3) External/Status
-conditions. In addition, there are several conditions that may cause these interrupts.*/
+conditions. In addition, there are several conditions that may cause these interrupts.
+
+To allow for control over the daisy chain, the SCC has a Disable Lower Chain (DLC) software command (WR9 bit 2)
+that pulls IEO Low. This selectively deactivates parts of the daisy chain regardless of the interrupt status.
+*/
//-------------------------------------------------
// z80daisy_irq_state - get interrupt status
//-------------------------------------------------
-
int z80scc_device::z80daisy_irq_state()
{
int state = 0;
- int i;
LOG(("%s %s A:%d%d%d B:%d%d%d ",tag(), FUNCNAME,
m_int_state[0], m_int_state[1], m_int_state[2],
m_int_state[3], m_int_state[4], m_int_state[5]));
// loop over all interrupt sources
- for (i = 0; i < 6; i++)
+ for (auto & elem : m_int_state)
{
// if we're servicing a request, don't indicate more interrupts
- if (m_int_state[i] & Z80_DAISY_IEO)
+ if (elem & Z80_DAISY_IEO)
{
state |= Z80_DAISY_IEO;
break;
}
- state |= m_int_state[i];
+ state |= elem;
}
+ // Last chance to keep the control of the interrupt line
+ state |= (m_wr9 & z80scc_channel::WR9_BIT_DLC) ? Z80_DAISY_IEO : 0;
+
LOG(("Interrupt State %u\n", state));
return state;
@@ -309,57 +331,46 @@ int z80scc_device::z80daisy_irq_state()
int z80scc_device::z80daisy_irq_ack()
{
- int i;
-
- LOG(("%s %s - needs fixing for SCC\n",tag(), FUNCNAME));
-
// loop over all interrupt sources
- for (i = 0; i < 6; i++)
+ for (auto & elem : m_int_state)
{
// find the first channel with an interrupt requested
- if (m_int_state[i] & Z80_DAISY_INT)
+ if (elem & Z80_DAISY_INT)
{
- // clear interrupt, switch to the IEO state, and update the IRQs
- m_int_state[i] = Z80_DAISY_IEO;
- //m_chanA->m_rr0 &= ~z80scc_channel::RR0_INTERRUPT_PENDING;
+ elem = Z80_DAISY_IEO; // Set IUS bit (called IEO in z80 daisy lingo)
check_interrupts();
-
- //LOG(("%s %s : Interrupt Acknowledge Vector %02x\n",tag(), FUNCNAME, m_chanB->m_rr2));
-
- return m_chanB->m_rr2;
+ LOGINT((" - Found an INT request, "));
+ if (m_wr9 & z80scc_channel::WR9_BIT_VIS)
+ {
+ LOGINT(("but WR9 D1 set to use autovector, returning -1\n"));
+ return -1;
+ }
+ else
+ {
+ LOGINT(("returning RR2: %02x\n", m_chanB->m_rr2 ));
+ return m_chanB->m_rr2;
+ }
}
}
//logerror("z80scc_irq_ack: failed to find an interrupt to ack!\n");
- return m_chanB->m_rr2;
+ return -1;
}
//-------------------------------------------------
// z80daisy_irq_reti - return from interrupt
//-------------------------------------------------
-
+/*
+"SCC Interrupt Daisy-Chain Operation
+In the SCC, the IUS bit normally controls the state of the IEO line. The IP bit affects the daisy
+chain only during an Interrupt Acknowledge cycle. Since the IP bit is normally not part of the SCC
+interrupt daisy chain, there is no need to decode the RETI instruction. To allow for control over the
+daisy chain, the SCC has a Disable Lower Chain (DLC) software command (WR9 bit 2) that pulls IEO Low."
+*/
void z80scc_device::z80daisy_irq_reti()
{
- int i;
-
- LOG(("%s %s \n",tag(), FUNCNAME));
-
- // loop over all interrupt sources
- for (i = 0; i < 6; i++)
- {
- // find the first channel with an IEO pending
- if (m_int_state[i] & Z80_DAISY_IEO)
- {
- // clear the IEO state and update the IRQs
- m_int_state[i] &= ~Z80_DAISY_IEO;
- check_interrupts();
- return;
- }
- }
-
- //logerror("z80scc_irq_reti: failed to find an interrupt to clear IEO on!\n");
}
@@ -394,29 +405,33 @@ void z80scc_device::reset_interrupts()
UINT8 z80scc_device::modify_vector(UINT8 vec, int i, UINT8 src)
{
- /*
- Interrupt Vector Modification
- V3 V2 V1 Status High/Status Low =0
- V4 V5 V6 Status High/Status Low =1
- 0 0 0 Ch B Transmit Buffer Empty
- 0 0 1 Ch B External/Status Change
- 0 1 0 Ch B Receive Char. Available
- 0 1 1 Ch B Special Receive Condition
- 1 0 0 Ch A Transmit Buffer Empty
- 1 0 1 Ch A External/Status Change
- 1 1 0 Ch A Receive Char. Available
- 1 1 1 Ch A Special Receive Condition
- */
- // Add channel offset according to table above
+ /*
+ Interrupt Vector Modification
+ V3 V2 V1 Status High/Status Low =0
+ V4 V5 V6 Status High/Status Low =1
+ 0 0 0 Ch B Transmit Buffer Empty
+ 0 0 1 Ch B External/Status Change
+ 0 1 0 Ch B Receive Char. Available
+ 0 1 1 Ch B Special Receive Condition
+ 1 0 0 Ch A Transmit Buffer Empty
+ 1 0 1 Ch A External/Status Change
+ 1 1 0 Ch A Receive Char. Available
+ 1 1 1 Ch A Special Receive Condition
+ */
+
+ // Add channel offset according to table above
+ src &= 3;
src |= (i == CHANNEL_A ? 0x04 : 0x00 );
// Modify vector according to Hi/lo bit of WR9
- if (m_chanA->m_wr9 & z80scc_channel::WR9_BIT_SHSL) // Affect V4-V6
+ if (m_wr9 & z80scc_channel::WR9_BIT_SHSL) // Affect V4-V6
{
+ vec &= 0x8f;
vec |= src << 4;
}
else // Affect V1-V3
{
+ vec &= 0xf1;
vec |= src << 1;
}
return vec;
@@ -428,7 +443,7 @@ UINT8 z80scc_device::modify_vector(UINT8 vec, int i, UINT8 src)
//-------------------------------------------------
void z80scc_device::trigger_interrupt(int index, int state)
{
- UINT8 vector = m_chanB->m_wr2;
+ UINT8 vector = m_chanA->m_rr2;
UINT8 source = 0;
int priority;
@@ -437,7 +452,7 @@ void z80scc_device::trigger_interrupt(int index, int state)
LOG(("%s %s:%c %02x \n",FUNCNAME, tag(), 'A' + index, state));
/* The Master Interrupt Enable (MIE) bit, WR9 D3, must be set to enable the SCC to generate interrupts.*/
- if (!(m_chanA->m_wr9 & z80scc_channel::WR9_BIT_MIE))
+ if (!(m_wr9 & z80scc_channel::WR9_BIT_MIE))
{
LOG(("Master Interrupt Enable is not set, blocking attempt to interrupt\n"));
return;
@@ -452,6 +467,12 @@ void z80scc_device::trigger_interrupt(int index, int state)
source = 2;
prio_level = 2;
break;
+ case z80scc_channel::INT_EXTERNAL:
+ /* The External/status interrupts have several sources which may be individually enabled in WR15.
+ The sources are zero count, /DCD, Sync/Hunt, /CTS, transmitter under-run/EOM and Break/Abort.*/
+ source = 1;
+ prio_level = 0;
+ break;
case z80scc_channel::INT_TRANSMIT:
/*The NMOS/CMOS version of the SCC only has a one byte deep transmit buffer. The status of the
transmit buffer can be determined through TBE bit in RR0, bit D2, which shows whether the
@@ -483,15 +504,15 @@ void z80scc_device::trigger_interrupt(int index, int state)
}
// Vector modification requested?
- if (m_chanA->m_wr9 & z80scc_channel::WR9_BIT_VIS)
+ if (m_wr9 & z80scc_channel::WR9_BIT_VIS)
{
vector = modify_vector(vector, index, source);
}
LOG((" Interrupt Request fired of type %u and vector %02x\n", state, vector));
- // update vector register // TODO: What if interrupts are nested? May we loose the modified vector or even get the wrong one?
- m_chanB->m_wr2 = vector;
+ // update vector register
+ m_chanB->m_rr2 = vector;
/* Check the interrupt source and build the vector modification */
/*Interrupt Source Priority order
@@ -508,8 +529,12 @@ void z80scc_device::trigger_interrupt(int index, int state)
// trigger interrupt
m_int_state[priority] |= Z80_DAISY_INT;
- // Based on the fact that prio levels are aligned with the bitorder of rr3 we can do this... TODO: field needs blanking?
- m_chanA->m_rr3 |= (prio_level << (index == CHANNEL_A ? 3 : 0 ));
+ // remember the source
+ m_int_source[priority] = source;
+
+ // Based on the fact that prio levels are aligned with the bitorder of rr3 we can do this...
+ m_chanA->m_rr3 &= ~( 0x07 << (index == CHANNEL_A ? 3 : 0 ));
+ m_chanA->m_rr3 |= (prio_level << (index == CHANNEL_A ? 3 : 0 ));
// check for interrupt
check_interrupts();
@@ -527,6 +552,72 @@ int z80scc_device::m1_r()
//-------------------------------------------------
+// zbus_r - Z-Bus read
+//-------------------------------------------------
+READ8_MEMBER( z80scc_device::zbus_r )
+{
+ int ba = 0;
+ int reg = 0x20; // Default point to a non register number
+ UINT8 data = 0;
+
+ /* Expell non- Z-Bus variants */
+ if ( !(m_variant & SET_Z80X30))
+ {
+ logerror(" zbus_r not supported by this device variant, you should probably use the universal bus variants c*_r/w and d*_r/w (see z80scc.h)\n");
+ return data;
+ }
+
+ switch ((m_chanB->m_wr0) & 7)
+ {
+ case z80scc_channel::WR0_Z_SEL_SHFT_LEFT: ba = offset & 0x01; reg = (offset >> 1) & 0x0f; break; /* Shift Left mode */
+ case z80scc_channel::WR0_Z_SEL_SHFT_RIGHT: ba = offset & 0x10; reg = (offset >> 1) & 0x0f; break; /* Shift Right mode */
+ default:
+ logerror("Malformed Z-bus SCC read: offset %02x WR0 bits %02x\n", offset, m_chanB->m_wr0);
+ LOG(("Malformed Z-bus SCC read: offset %02x WR0 bits %02x\n", offset, m_chanB->m_wr0));
+ return data;
+ }
+
+ if (ba == 0)
+ data = m_chanB->scc_register_read(reg);
+ else
+ data = m_chanA->scc_register_read(reg);
+
+ return data;
+}
+
+//-------------------------------------------------
+// zbus_w - Z-Bus write
+//-------------------------------------------------
+WRITE8_MEMBER( z80scc_device::zbus_w )
+{
+ int ba = 0;
+ int reg = 0x20; // Default point to a non register number
+
+ /* Expell non- Z-Bus variants */
+ if ( !(m_variant & SET_Z80X30))
+ {
+ logerror(" zbus_w not supported by this device variant, you should probably use the universal bus variants c*_r/w and d*_r/w (see z80scc.h)\n");
+ return;
+ }
+
+ switch ((m_chanB->m_wr0) & 7)
+ {
+ case z80scc_channel::WR0_Z_SEL_SHFT_LEFT: ba = offset & 0x01; reg = (offset >> 1) & 0x0f; break; /* Shift Left mode */
+ case z80scc_channel::WR0_Z_SEL_SHFT_RIGHT: ba = offset & 0x10; reg = (offset >> 1) & 0x0f; break; /* Shift Right mode */
+ default:
+ logerror("Malformed Z-bus SCC write: offset %02x WR0 bits %02x\n", offset, m_chanB->m_wr0);
+ LOG(("Malformed Z-bus SCC write: offset %02x WR0 bits %02x\n", offset, m_chanB->m_wr0));
+ }
+
+ if (ba == 0)
+ m_chanB->scc_register_write(reg, data);
+ else
+ m_chanA->scc_register_write(reg, data);
+
+ return;
+}
+
+//-------------------------------------------------
// cd_ba_r - Universal Bus read
//-------------------------------------------------
READ8_MEMBER( z80scc_device::cd_ba_r )
@@ -593,7 +684,7 @@ READ8_MEMBER( z80scc_device::ba_cd_r )
//-------------------------------------------------
-// ba_cd_w -
+// ba_cd_w - Universal Bus write
//-------------------------------------------------
WRITE8_MEMBER( z80scc_device::ba_cd_w )
@@ -618,7 +709,7 @@ WRITE8_MEMBER( z80scc_device::ba_cd_w )
}
//-------------------------------------------------
-// ba_cd_r - Universal Bus read
+// ba_cd_inv_r - Universal Bus read
//-------------------------------------------------
READ8_MEMBER( z80scc_device::ba_cd_inv_r )
@@ -640,7 +731,7 @@ READ8_MEMBER( z80scc_device::ba_cd_inv_r )
//-------------------------------------------------
-// ba_cd_w -
+// ba_cd_inv_w - Universal Bus read
//-------------------------------------------------
WRITE8_MEMBER( z80scc_device::ba_cd_inv_w )
@@ -690,7 +781,6 @@ z80scc_channel::z80scc_channel(const machine_config &mconfig, const char *tag, d
m_rxd(0),
m_cts(0),
m_dcd(0),
- m_tx_data(0),
m_tx_clock(0),
m_dtr(0),
m_rts(0),
@@ -702,16 +792,19 @@ z80scc_channel::z80scc_channel(const machine_config &mconfig, const char *tag, d
LOG(("%s\n",FUNCNAME));
// Reset all registers
- m_rr0 = m_rr1 = m_rr2 = m_rr3 = m_rr4 = m_rr5 = m_rr6 = m_rr7 = m_rr8
+ m_rr0 = m_rr1 = m_rr2 = m_rr3 = m_rr4 = m_rr5 = m_rr6 = m_rr7 = m_rr7p = m_rr8
= m_rr9 = m_rr10 = m_rr11 = m_rr12 = m_rr13 = m_rr14 = m_rr15 = 0;
- m_wr0 = m_wr1 = m_wr2 = m_wr3 = m_wr4 = m_wr5 = m_wr6 = m_wr7 = m_wr8
- = m_wr9 = m_wr10 = m_wr11 = m_wr12 = m_wr13 = m_wr14 = m_wr15 = 0;
+ m_wr0 = m_wr1 = m_wr2 = m_wr3 = m_wr4 = m_wr5 = m_wr6 = m_wr7 = m_wr7p = m_wr8
+ = m_wr10 = m_wr11 = m_wr12 = m_wr13 = m_wr14 = m_wr15 = 0;
- for (int i = 0; i < 3; i++) // TODO adapt to SCC fifos
- {
- m_rx_data_fifo[i] = 0;
- m_rx_error_fifo[i] = 0;
- }
+ for (auto & elem : m_rx_data_fifo)
+ elem = 0;
+ for (auto & elem : m_rx_error_fifo) // TODO: Status FIFO needs to be fixed
+ elem = 0;
+ for (auto & elem : m_tx_data_fifo)
+ elem = 0;
+ for (auto & elem : m_tx_error_fifo) // TODO: Status FIFO needs to be fixed
+ elem = 0;
}
@@ -730,6 +823,9 @@ void z80scc_channel::device_start()
m_rx_fifo_sz = (m_uart->m_variant & SET_ESCC) ? 8 : 3;
m_rx_fifo_wp = m_rx_fifo_rp = 0;
+ m_tx_fifo_sz = (m_uart->m_variant & SET_ESCC) ? 4 : 1;
+ m_tx_fifo_wp = m_tx_fifo_rp = 0;
+
#if LOCAL_BRG
// baudrate clocks and timers
baudtimer = timer_alloc(TIMER_ID_BAUD);
@@ -744,6 +840,7 @@ void z80scc_channel::device_start()
save_item(NAME(m_rr5));
save_item(NAME(m_rr6));
save_item(NAME(m_rr7));
+ save_item(NAME(m_rr7p));
save_item(NAME(m_rr8));
save_item(NAME(m_rr9));
save_item(NAME(m_rr10));
@@ -760,16 +857,21 @@ void z80scc_channel::device_start()
save_item(NAME(m_wr5));
save_item(NAME(m_wr6));
save_item(NAME(m_wr7));
+ save_item(NAME(m_wr7p));
save_item(NAME(m_wr8));
- save_item(NAME(m_wr9));
save_item(NAME(m_wr10));
save_item(NAME(m_wr11));
save_item(NAME(m_wr12));
save_item(NAME(m_wr13));
save_item(NAME(m_wr14));
save_item(NAME(m_wr15));
+ save_item(NAME(m_tx_data_fifo));
+ save_item(NAME(m_tx_error_fifo)); // TODO: Status FIFO needs to be fixed
+ save_item(NAME(m_tx_fifo_rp));
+ save_item(NAME(m_tx_fifo_wp));
+ save_item(NAME(m_tx_fifo_sz));
save_item(NAME(m_rx_data_fifo));
- save_item(NAME(m_rx_error_fifo));
+ save_item(NAME(m_rx_error_fifo)); // TODO: Status FIFO needs to be fixed
save_item(NAME(m_rx_fifo_rp));
save_item(NAME(m_rx_fifo_wp));
save_item(NAME(m_rx_fifo_sz));
@@ -780,7 +882,6 @@ void z80scc_channel::device_start()
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));
@@ -802,41 +903,32 @@ void z80scc_channel::device_reset()
receive_register_reset();
transmit_register_reset();
- // Soft/Channel Reset values according to SCC users manual
+ // Soft/Channel Reset values (mostly) according to SCC users manual
m_wr0 = 0x00;
m_wr1 &= 0x24;
m_wr3 &= 0x01;
- m_wr4 |= 0x04;
- m_wr5 &= 0x61;
+ m_wr4 = 0x04;
+ m_wr5 = 0x00;
if (m_uart->m_variant & (z80scc_device::TYPE_SCC85C30 | SET_ESCC))
m_wr7 = 0x20;
- m_wr9 &= 0xdf; // WR9 has a different hard reset value
- m_wr10 &= 0x60; // WR10 has a different hard reset value
- m_wr11 &= 0xff; // WR11 has a different hard reset value
- m_wr14 &= 0xc3; // WR14 has a different hard reset value
+ // WR9,WR10,WR11 and WR14 has a different hard reset (see z80scc_device::device_reset()) values
+ m_uart->m_wr9 &= 0xdf;
+ m_wr10 &= 0x60;
+ m_wr11 &= 0xff;
+ m_wr14 &= 0xc3;
m_wr14 |= 0x20;
m_wr15 = 0xf8;
m_rr0 &= 0xfc;
m_rr0 |= 0x44;
m_rr1 &= 0x07;
- m_rr1 |= 0x06;
+ m_rr1 |= 0x06; // Required reset value
+ m_rr1 |= RR1_ALL_SENT; // It is a don't care in the SCC user manual but drivers hangs without it set
m_rr3 = 0x00;
m_rr10 &= 0x40;
-#if 1 // old reset code
- // disable receiver
- m_wr3 &= ~WR3_RX_ENABLE;
-
- // disable transmitter
- m_wr5 &= ~WR5_TX_ENABLE;
- m_rr0 |= RR0_TX_BUFFER_EMPTY;
-#endif
- // TODO: check dependencies on RR1_ALL_SENT and (re)move this setting
- m_rr1 |= RR1_ALL_SENT; // It is a don't care in the SCC user manual
-
- // reset external lines TODO: check relation to control bits and reset
- set_rts(1);
- set_dtr(1);
+ // reset external lines
+ set_rts(m_wr5 & WR5_RTS ? 0 : 1);
+ set_dtr(m_wr14 & WR14_DTR_REQ_FUNC ? 0 : (m_wr5 & WR5_DTR ? 0 : 1));
// reset interrupts
if (m_index == z80scc_device::CHANNEL_A)
@@ -931,23 +1023,48 @@ void z80scc_channel::tra_callback()
void z80scc_channel::tra_complete()
{
+ // Delayed baudrate change according to SCC specs
if ( m_delayed_tx_brg_change == 1)
{
m_delayed_tx_brg_change = 0;
set_tra_rate(m_brg_rate);
LOG(("Delayed setup - Baud Rate Generator: %d mode: %dx\n", m_brg_rate, get_clock_mode() ));
}
- if ((m_wr5 & WR5_TX_ENABLE) && !(m_wr5 & WR5_SEND_BREAK) && !(m_rr0 & RR0_TX_BUFFER_EMPTY))
- {
- LOG((LLFORMAT " %s() \"%s \"Channel %c Transmit Data Byte '%02x' m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_tx_data, m_wr5));
- transmit_register_setup(m_tx_data);
+ if ((m_wr5 & WR5_TX_ENABLE) && !(m_wr5 & WR5_SEND_BREAK))
+ {
+ if ( (m_rr0 & RR0_TX_BUFFER_EMPTY) == 0 || // Takes care of the NMOS/CMOS 1 slot TX FIFO
+ m_tx_fifo_rp != m_tx_fifo_wp) // or there are more characters to send in a longer FIFO.
+ {
+ LOGTX((" %s() %s %c done sending, loading data from fifo:%02x '%c'\n", FUNCNAME, m_owner->tag(), 'A' + m_index,
+ m_tx_data_fifo[m_tx_fifo_rp], isascii(m_tx_data_fifo[m_tx_fifo_rp]) ? m_tx_data_fifo[m_tx_fifo_rp] : ' '));
+ transmit_register_setup(m_tx_data_fifo[m_tx_fifo_rp]); // Reload the shift register
+ m_tx_fifo_rp_step();
+ m_rr0 |= RR0_TX_BUFFER_EMPTY; // Now here is room in the tx fifo again
+ }
+ else
+ {
+ LOGTX((" %s() %s %c done sending, setting all sent bit\n", FUNCNAME, m_owner->tag(), 'A' + m_index));
+ m_rr1 |= RR1_ALL_SENT;
- // empty transmit buffer
- m_rr0 |= RR0_TX_BUFFER_EMPTY;
+ // when the RTS bit is reset, the _RTS output goes high after the transmitter empties
+ if (!m_rts) // TODO: Clean up RTS handling
+ set_rts(1);
+ }
if (m_wr1 & WR1_TX_INT_ENABLE)
- m_uart->trigger_interrupt(m_index, INT_TRANSMIT);
+ {
+ if ((m_uart->m_variant & SET_ESCC) &&
+ (m_wr7p & WR7P_TX_FIFO_EMPTY) &&
+ m_tx_fifo_wp == m_tx_fifo_rp) // ESCC and fifo empty bit set and fifo is completelly empty?
+ {
+ m_uart->trigger_interrupt(m_index, INT_TRANSMIT); // Set TXIP bit
+ }
+ else if(m_rr0 & RR0_TX_BUFFER_EMPTY) // Check TBE bit and interrupt if one or more FIFO slots availble
+ {
+ m_uart->trigger_interrupt(m_index, INT_TRANSMIT); // Set TXIP bit
+ }
+ }
}
else if (m_wr5 & WR5_SEND_BREAK)
{
@@ -967,18 +1084,6 @@ void z80scc_channel::tra_complete()
else
m_uart->m_out_txdb_cb(1);
}
-
- // if transmit buffer is empty
- if (m_rr0 & RR0_TX_BUFFER_EMPTY)
- {
- LOG((LLFORMAT " %s() \"%s \"Channel %c Transmit buffer empty m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5));
- // then all characters have been sent
- m_rr1 |= RR1_ALL_SENT;
-
- // when the RTS bit is reset, the _RTS output goes high after the transmitter empties
- if (!m_rts)
- set_rts(1);
- }
}
@@ -1170,15 +1275,24 @@ UINT8 z80scc_channel::do_sccreg_rr2()
// If we are chan B we have to modify the vector regardless of the VIS bit
if (m_index == z80scc_device::CHANNEL_B)
{
+ int i = 0;
+
// loop over all interrupt sources
- for (int i = 0; i < 6; i++)
+ for (auto & elem : m_uart->m_int_state)
{
// find the first channel with an interrupt requested
- if (m_uart->m_int_state[i] & Z80_DAISY_INT)
+ if (elem & Z80_DAISY_INT)
{
- m_rr2 = m_uart->modify_vector(m_rr2, i < 3 ? z80scc_device::CHANNEL_A : z80scc_device::CHANNEL_B, i & 3);
+ m_rr2 = m_uart->modify_vector(m_rr2, i < 3 ? z80scc_device::CHANNEL_A : z80scc_device::CHANNEL_B, m_uart->m_int_source[i] & 3);
+ if ((m_uart->m_variant & (SET_ESCC | SET_CMOS)) && (m_uart->m_wr9 & WR9_BIT_IACK))
+ {
+ LOGINT((" - Found an INT request to ack while reading RR2\n"));
+ elem = Z80_DAISY_IEO; // Set IUS bit (called IEO in z80 daisy lingo)
+ m_uart->check_interrupts();
+ }
break;
}
+ i++;
}
}
return m_rr2;
@@ -1231,12 +1345,12 @@ UINT8 z80scc_channel::do_sccreg_rr5()
UINT8 z80scc_channel::do_sccreg_rr6()
{
LOGR(("%s\n", FUNCNAME));
- if (!(m_uart->m_variant & (SET_NMOS)))
+ if (m_wr15 & WR15_STATUS_FIFO)
{
- logerror(" %s() not implemented feature\n", FUNCNAME);
+ logerror(" - Status FIFO for synchronous mode - not implemented\n");
return 0;
}
- return m_rr2;
+ return m_rr2; /* Note that NMOS calls are redirected to do_sccreg_rr2() before getting here */
}
/* (not on NMOS)
@@ -1304,6 +1418,7 @@ UINT8 z80scc_channel::do_sccreg_rr11()
RR12 returns the value stored in WR12, the lower byte of the time constant, for the BRG.*/
UINT8 z80scc_channel::do_sccreg_rr12()
{
+ LOGR(("%s\n", FUNCNAME));
return m_wr12;
}
@@ -1311,6 +1426,7 @@ UINT8 z80scc_channel::do_sccreg_rr12()
RR13 returns the value stored in WR13, the upper byte of the time constant for the BRG. */
UINT8 z80scc_channel::do_sccreg_rr13()
{
+ LOGR(("%s\n", FUNCNAME));
return m_wr13;
}
@@ -1338,41 +1454,55 @@ UINT8 z80scc_channel::do_sccreg_rr15()
}
//-------------------------------------------------
-// control_read - read control register
+// scc_register_read - read a SCC register
//-------------------------------------------------
-UINT8 z80scc_channel::control_read()
+UINT8 z80scc_channel::scc_register_read( UINT8 reg)
{
+ if (reg > 1)
+ LOG(("%s %02x\n", FUNCNAME, reg));
UINT8 data = 0;
- int reg = m_uart->m_wr0_ptrbits; //m_wr0;
- int regmask = (WR0_REGISTER_MASK | (m_uart->m_wr0_ptrbits & WR0_POINT_HIGH));
-
- LOGR(("%s(%02x) reg %02x, regmask %02x, WR0 %02x\n", FUNCNAME, data, reg, regmask, m_wr0));
- m_uart->m_wr0_ptrbits = 0;
- reg &= regmask;
+ UINT8 wreg = 0;
- if (reg != 0)
+ /* Sort out 80X30 limitations in register access */
+// if ((BIT(m_wr15, 2) == 0) || m_uart->m_variant == z80scc_device::TYPE_SCC8030)
+ if (BIT(m_wr15, 2) == 0 || m_uart->m_variant & SET_NMOS)
{
- LOG(("%s(%02x) reg %02x, regmask %02x, WR0 %02x\n", FUNCNAME, data, reg, regmask, m_wr0));
- // mask out register index
- m_wr0 &= ~regmask;
+ if (reg > 3 && reg < 8) reg &= 0x03;
+ else if (reg == 9) reg = 13;
+ else if (reg == 11) reg = 15;
+ }
+ else if (BIT(m_wr15, 2) != 0)
+ {
+// if (m_uart->variant == z80scc_device::TYPE_SCC80230 && BIT(m_wr7p, 6) != 0)
+ if (m_uart->m_variant & SET_ESCC && BIT(m_wr7p, 6) != 0)
+ {
+ if (reg > 3 && reg < 6) wreg = 1;
+ else if (reg == 9) { reg = 3; wreg = 1; }
+ else if (reg == 11) { reg = 10; wreg = 1; }
+ else if (reg == 14) { reg = 7; wreg = 1; }
+ }
+ else
+ {
+ if (reg > 3 && reg < 6) reg &= 3;
+ else if (reg == 9) { reg = 13; }
+ else if (reg == 11) { reg = 15; }
+ }
}
-
- /* TODO. Sort out 80X30 limitations in register access */
switch (reg)
{
- case REG_RR0_STATUS: data = do_sccreg_rr0(); break; // TODO: verify handling of SCC specific bits: D6 and D1
+ case REG_RR0_STATUS: data = do_sccreg_rr0(); break; // TODO: verify handling of SCC specific bits: D6 and D1
case REG_RR1_SPEC_RCV_COND: data = do_sccreg_rr1(); break;
case REG_RR2_INTERRUPT_VECT: data = do_sccreg_rr2(); break; // Channel dependent and SCC specific handling compared to SIO
/* registers 3-7 are specific to SCC. TODO: Check variant and log/stop misuse */
- case REG_RR3_INTERUPPT_PEND: data = do_sccreg_rr3(); break;
- case REG_RR4_WR4_OR_RR0: data = do_sccreg_rr4(); break;
- case REG_RR5_WR5_OR_RR0: data = do_sccreg_rr5(); break;
+ case REG_RR3_INTERUPPT_PEND: data = wreg ? m_wr3 : do_sccreg_rr3(); break;
+ case REG_RR4_WR4_OR_RR0: data = wreg ? m_wr4 : do_sccreg_rr4(); break;
+ case REG_RR5_WR5_OR_RR0: data = wreg ? m_wr5 : do_sccreg_rr5(); break;
case REG_RR6_LSB_OR_RR2: data = do_sccreg_rr6(); break;
- case REG_RR7_MSB_OR_RR3: data = do_sccreg_rr7(); break;
+ case REG_RR7_MSB_OR_RR3: data = wreg ? m_wr7p : do_sccreg_rr7(); break;
/* registers 8-15 are specific to SCC */
case REG_RR8_RECEIVE_DATA: data = data_read(); break;
case REG_RR9_WR3_OR_RR13: data = do_sccreg_rr9(); break;
- case REG_RR10_MISC_STATUS: data = do_sccreg_rr10(); break;
+ case REG_RR10_MISC_STATUS: data = wreg ? m_wr10 : do_sccreg_rr10(); break;
case REG_RR11_WR10_OR_RR15: data = do_sccreg_rr11(); break;
case REG_RR12_LO_TIME_CONST: data = do_sccreg_rr12(); break;
case REG_RR13_HI_TIME_CONST: data = do_sccreg_rr13(); break;
@@ -1381,6 +1511,30 @@ UINT8 z80scc_channel::control_read()
default:
logerror(" \"%s\" %s: %c : Unsupported RRx register:%02x\n", m_owner->tag(), FUNCNAME, 'A' + m_index, reg);
}
+ return data;
+}
+
+//-------------------------------------------------
+// control_read - read control register
+//-------------------------------------------------
+UINT8 z80scc_channel::control_read()
+{
+ UINT8 data = 0;
+ int reg = m_uart->m_wr0_ptrbits; //m_wr0;
+ int regmask = (WR0_REGISTER_MASK | (m_uart->m_wr0_ptrbits & WR0_POINT_HIGH));
+
+ LOGR(("%s(%02x) reg %02x, regmask %02x, WR0 %02x\n", FUNCNAME, data, reg, regmask, m_wr0));
+ m_uart->m_wr0_ptrbits = 0;
+ reg &= regmask;
+
+ if (reg != 0)
+ {
+ LOG(("%s(%02x) reg %02x, regmask %02x, WR0 %02x\n", FUNCNAME, data, reg, regmask, m_wr0));
+ // mask out register index
+ m_wr0 &= ~regmask;
+ }
+
+ data = scc_register_read(reg);
//LOG(("%s \"%s\": %c : Register R%d read '%02x'\n", FUNCNAME, m_owner->tag(), 'A' + m_index, reg, data));
return data;
@@ -1414,7 +1568,9 @@ void z80scc_channel::do_sccreg_wr0_resets(UINT8 data)
void z80scc_channel::do_sccreg_wr0(UINT8 data)
{
m_wr0 = data;
- m_uart->m_wr0_ptrbits = data & WR0_REGISTER_MASK;
+
+ if (m_uart->m_variant & SET_Z85X3X)
+ m_uart->m_wr0_ptrbits = data & WR0_REGISTER_MASK;
/* Sort out SCC specific behaviours from legacy SIO behaviour */
/* WR0_Z_* are Z80X30 specific commands */
@@ -1430,7 +1586,6 @@ void z80scc_channel::do_sccreg_wr0(UINT8 data)
if (m_uart->m_variant & SET_Z85X3X)
{
LOG(("%s %s: %c : - Point High command\n", FUNCNAME, m_owner->tag(), 'A' + m_index));
- //m_ph = 8;
m_uart->m_wr0_ptrbits |= 8;
}
else
@@ -1459,8 +1614,17 @@ void z80scc_channel::do_sccreg_wr0(UINT8 data)
/* This command resets the highest priority Interrupt Under Service (IUS) bit, allowing lower
priority conditions to request interrupts. This command allows the use of the internal
daisy chain (even in systems without an external daisy chain) and is the last operation in
- an interrupt service routine.TODO: Implement internal Daisychain */
- LOG(("\"%s\" %s: %c : Reset Highest IUS\n", m_owner->tag(), FUNCNAME, 'A' + m_index));
+ an interrupt service routine. */
+ if (m_uart->m_variant & (SET_NMOS))
+ {
+ logerror("WR0 SWI ack command not supported on NMOS\n");
+ LOG(("\"%s\" %s: %c : Reset Highest IUS command not available on NMOS!\n", m_owner->tag(), FUNCNAME, 'A' + m_index));
+ }
+ else
+ {
+ m_uart->z80daisy_irq_ack();
+ LOG(("\"%s\" %s: %c : Reset Highest IUS\n", m_owner->tag(), FUNCNAME, 'A' + m_index));
+ }
break;
case WR0_ERROR_RESET:
/*Error Reset Command (110). This command resets the error bits in RR1. If interrupt on first Rx
@@ -1499,41 +1663,6 @@ void z80scc_channel::do_sccreg_wr0(UINT8 data)
m_uart->m_wr0_ptrbits &= ~WR0_REGISTER_MASK;
m_uart->m_wr0_ptrbits |= (m_wr0 & (WR0_REGISTER_MASK));
}
- else if ( m_uart->m_variant & SET_Z80X30) // TODO: Implement adress decoding for Z80X30 using the shift logic described below
- {
- /*The registers in the Z80X30 are addressed via the address on AD7-AD0 and are latched by the rising
- edge of /AS. The Shift Right/Shift Left bit in the Channel B WR0 controls which bits are
- decoded to form the register address. It is placed in this register to simplify programming when the
- current state of the Shift Right/Shift Left bit is not known.
- A hardware reset forces Shift Left mode where the address is decoded from AD5-AD1. In Shift
- Right mode, the address is decoded from AD4-AD0. The Shift Right/Shift Left bit is written via a
- command to make the software writing to WR0 independent of the state of the Shift Right/Shift
- Left bit.
- While in the Shift Left mode, the register address is placed on AD4-AD1 and the Channel Select
- bit, A/B, is decoded from AD5. The register map for this case is listed in Table on page 21. In
- Shift Right mode, the register address is again placed on AD4-AD1 but the channel select A/B is
- decoded from AD0. The register map for this case is listed in Table on page 23.
- Because the Z80X30 does not contain 16 read registers, the decoding of the read registers is not
- complete; this is listed in Table on page 21 and Table on page 23 by parentheses around the register
- name. These addresses may also be used to access the read registers. Also, note that the
- Z80X30 contains only one WR2 and WR9; these registers may be written from either channel.
- Shift Left Mode is used when Channel A and B are to be programmed differently. This allows the
- software to sequence through the registers of one channel at a time. The Shift Right Mode is used
- when the channels are programmed the same. By incrementing the address, the user can program
- the same data value into both the Channel A and Channel B register.*/
- switch(data & WR0_Z_SHIFT_MASK)
- {
- case WR0_Z_SEL_SHFT_LEFT:
- LOG(("\"%s\": %c : %s - Shift Left Addressing Mode - not implemented\n", m_owner->tag(), 'A' + m_index, FUNCNAME));
- break;
- case WR0_Z_SEL_SHFT_RIGHT:
- LOG(("\"%s\": %c : %s - Shift Right Addressing Mode - not implemented\n", m_owner->tag(), 'A' + m_index, FUNCNAME));
- break;
- default:
- break;
- // LOG(("\"%s\": %c : %s - Null commands\n", m_owner->tag(), 'A' + m_index, FUNCNAME));
- }
- }
}
/* Write Register 1 is the control register for the various SCC interrupt and Wait/Request modes.*/
@@ -1625,6 +1754,7 @@ void z80scc_channel::do_sccreg_wr5(UINT8 data)
}
else
{
+ // UINT8 old_wr5 = m_wr5;
m_wr5 = data;
LOG(("- Transmitter Enable %u\n", (data & WR5_TX_ENABLE) ? 1 : 0));
LOG(("- Transmitter Bits/Character %u\n", get_tx_word_length()));
@@ -1634,6 +1764,10 @@ void z80scc_channel::do_sccreg_wr5(UINT8 data)
update_serial();
safe_transmit_register_reset();
update_rts();
+#if 0
+ if ( !(old_wr5 & WR5_TX_ENABLE) && m_wr5 & WR5_TX_ENABLE )
+ write_data(m_tx_data);
+#endif
m_rr0 |= RR0_TX_BUFFER_EMPTY;
}
}
@@ -1653,7 +1787,7 @@ void z80scc_channel::do_sccreg_wr7(UINT8 data)
/* WR8 is the transmit buffer register */
void z80scc_channel::do_sccreg_wr8(UINT8 data)
{
- LOG(("%s(%02x) \"%s\": %c : Transmit Buffer read %02x\n", FUNCNAME, data, m_owner->tag(), 'A' + m_index, data));
+ LOG(("%s(%02x) \"%s\": %c : Transmit Buffer write %02x\n", FUNCNAME, data, m_owner->tag(), 'A' + m_index, data));
data_write(data);
}
@@ -1663,13 +1797,7 @@ at the same time as the Reset command, because these bits are only reset by a ha
note that the Z80X30 contains only one WR2 and WR9; these registers may be written from either channel.*/
void z80scc_channel::do_sccreg_wr9(UINT8 data)
{
- if (m_uart->m_variant & SET_Z80X30)
- {
- m_uart->m_chanA->m_wr9 = data;
- m_uart->m_chanB->m_wr9 = data;
- }
- else
- m_wr9 = data;
+ m_uart->m_wr9 = data; // There is only one WR9 register and is written from both channels A and B (if exists)
switch (data & WR9_CMD_MASK)
{
@@ -1688,10 +1816,22 @@ void z80scc_channel::do_sccreg_wr9(UINT8 data)
LOG(("\"%s\": %c : Master Interrupt Control - Device reset %02x\n", m_owner->tag(), 'A' + m_index, data));
/*"The effects of this command are identical to those of a hardware reset, except that the Shift Right/Shift Left bit is
not changed and the MIE, Status High/Status Low and DLC bits take the programmed values that accompany this command."
- The Shift Right/Shift Left bits of the WR0 is only valid on SCC8030 device hence not implemented yet, just the SCC8530 */
- if (data & (WR9_BIT_MIE | WR9_BIT_IACK | WR9_BIT_SHSL | WR9_BIT_DLC | WR9_BIT_NV))
- logerror(" SCC Interrupt system not yet implemented, please be patient.\n");
- m_uart->device_reset();
+ */
+ if (m_uart->m_variant & SET_Z80X30)
+ {
+ UINT8 tmp_wr0 = m_wr0; // Save the Shift Left/Shift Right bits
+ m_uart->device_reset();
+ // Restore the Shift Left/Shift Right bits
+ m_wr0 &= 0xfc;
+ m_wr0 |= (tmp_wr0 & 0x03);
+ }
+ else
+ {
+ m_uart->device_reset();
+ }
+ // Set the MIE, Status High/Status Low and DLC bits as given in this command
+ m_uart->m_wr9 &= ~(WR9_BIT_MIE | WR9_BIT_SHSL | WR9_BIT_DLC );
+ m_uart->m_wr9 |= (data & (WR9_BIT_MIE | WR9_BIT_SHSL | WR9_BIT_DLC ));
break;
default:
logerror("Code is broken in WR9, please report!\n");
@@ -1795,7 +1935,6 @@ void z80scc_channel::do_sccreg_wr11(UINT8 data)
*/
void z80scc_channel::do_sccreg_wr12(UINT8 data)
{
- // TODO: Check if BRG enabled already and restart timer with new value in case advice above is not followed by ROM
m_wr12 = data;
update_serial();
LOG(("\"%s\": %c : %s %02x Low byte of Time Constant for Baudrate generator\n", m_owner->tag(), 'A' + m_index, FUNCNAME, data));
@@ -1804,7 +1943,6 @@ void z80scc_channel::do_sccreg_wr12(UINT8 data)
/* WR13 contains the upper byte of the time constant for the baud rate generator. */
void z80scc_channel::do_sccreg_wr13(UINT8 data)
{
- // TODO: Check if BRG enabled already and restart timer with new value in case advice above is not followed by ROM
m_wr13 = data;
update_serial();
LOG(("\"%s\": %c : %s %02x High byte of Time Constant for Baudrate generator\n", m_owner->tag(), 'A' + m_index, FUNCNAME, data));
@@ -1908,17 +2046,47 @@ void z80scc_channel::do_sccreg_wr14(UINT8 data)
as a group via WR1, bits in this register control which External/Status conditions cause an interrupt.
Only the External/Status conditions that occur after the controlling bit is set to 1 cause an
interrupt. This is true, even if an External/Status condition is pending at the time the bit is set*/
+#define WR15EN "enabled"
+#define WR15NO "not implemented"
void z80scc_channel::do_sccreg_wr15(UINT8 data)
{
- LOG(("%s(%02x) \"%s\": %c : External/Status Control Bits - not implemented\n",
+ LOGINT(("%s(%02x) \"%s\": %c : External/Status Control Bits\n",
FUNCNAME, data, m_owner->tag(), 'A' + m_index));
+ LOGINT(("WR7 prime ints : %s\n", data & WR15_WR7PRIME ? WR15NO : "disabled"));
+ LOGINT(("Zero count ints : %s\n", data & WR15_ZEROCOUNT ? WR15NO : "disabled"));
+ LOGINT(("14 bit Status FIFO : %s\n", data & WR15_STATUS_FIFO ? WR15NO : "disabled"));
+ LOGINT(("DCD ints : %s\n", data & WR15_DCD ? WR15EN : "disabled"));
+ LOGINT(("SYNC/Hunt ints : %s\n", data & WR15_SYNC ? WR15NO : "disabled"));
+ LOGINT(("CTS ints : %s\n", data & WR15_CTS ? WR15EN : "disabled"));
+ LOGINT(("Tx underr./EOM ints: %s\n", data & WR15_TX_EOM ? WR15NO : "disabled"));
+ LOGINT(("Break/Abort ints : %s\n", data & WR15_BREAK_ABORT ? WR15NO : "disabled"));
m_wr15 = data;
}
-/*TODO: Z80X30 Register Access
- ----------------------------
-The Shift Right/Shift Left bit in the Channel B WR0 controls which bits are decoded to form the register
-address. See do_sccreg_wr0() for details */
+void z80scc_channel::scc_register_write(UINT8 reg, UINT8 data)
+{
+ switch (reg)
+ {
+ case REG_WR0_COMMAND_REGPT: do_sccreg_wr0(data); break;
+ case REG_WR1_INT_DMA_ENABLE: do_sccreg_wr1(data); m_uart->check_interrupts(); break;
+ case REG_WR2_INT_VECTOR: do_sccreg_wr2(data); break;
+ case REG_WR3_RX_CONTROL: do_sccreg_wr3(data); break;
+ case REG_WR4_RX_TX_MODES: do_sccreg_wr4(data); break;
+ case REG_WR5_TX_CONTROL: do_sccreg_wr5(data); break;
+ case REG_WR6_SYNC_OR_SDLC_A: do_sccreg_wr6(data); break;
+ case REG_WR7_SYNC_OR_SDLC_F: do_sccreg_wr7(data); break;
+ case REG_WR8_TRANSMIT_DATA: do_sccreg_wr8(data); break;
+ case REG_WR9_MASTER_INT_CTRL: do_sccreg_wr9(data); break;
+ case REG_WR10_MSC_RX_TX_CTRL: do_sccreg_wr10(data); break;
+ case REG_WR11_CLOCK_MODES: do_sccreg_wr11(data); break;
+ case REG_WR12_LO_BAUD_GEN: do_sccreg_wr12(data); break;
+ case REG_WR13_HI_BAUD_GEN: do_sccreg_wr13(data); break;
+ case REG_WR14_MISC_CTRL: do_sccreg_wr14(data); break;
+ case REG_WR15_EXT_ST_INT_CTRL: do_sccreg_wr15(data); break;
+ default:
+ logerror("\"%s\": %c : Unsupported WRx register:%02x\n", m_owner->tag(), 'A' + m_index, reg);
+ }
+}
/*Z85X30 Register Access
-----------------------
@@ -1959,28 +2127,7 @@ void z80scc_channel::control_write(UINT8 data)
//LOG(("\n%s(%02x) reg %02x, regmask %02x\n", FUNCNAME, data, reg, regmask));
LOGSETUP((" * %s %c Reg %02x <- %02x \n", m_owner->tag(), 'A' + m_index, reg, data));
- /* TODO. Sort out 80X30 & other SCC variants limitations in register access */
- switch (reg)
- {
- case REG_WR0_COMMAND_REGPT: do_sccreg_wr0(data); break;
- case REG_WR1_INT_DMA_ENABLE: do_sccreg_wr1(data); m_uart->check_interrupts(); break;
- case REG_WR2_INT_VECTOR: do_sccreg_wr2(data); break;
- case REG_WR3_RX_CONTROL: do_sccreg_wr3(data); break;
- case REG_WR4_RX_TX_MODES: do_sccreg_wr4(data); break;
- case REG_WR5_TX_CONTROL: do_sccreg_wr5(data); break;
- case REG_WR6_SYNC_OR_SDLC_A: do_sccreg_wr6(data); break;
- case REG_WR7_SYNC_OR_SDLC_F: do_sccreg_wr7(data); break;
- case REG_WR8_TRANSMIT_DATA: do_sccreg_wr8(data); break;
- case REG_WR9_MASTER_INT_CTRL: do_sccreg_wr9(data); break;
- case REG_WR10_MSC_RX_TX_CTRL: do_sccreg_wr10(data); break;
- case REG_WR11_CLOCK_MODES: do_sccreg_wr11(data); break;
- case REG_WR12_LO_BAUD_GEN: do_sccreg_wr12(data); break;
- case REG_WR13_HI_BAUD_GEN: do_sccreg_wr13(data); break;
- case REG_WR14_MISC_CTRL: do_sccreg_wr14(data); break;
- case REG_WR15_EXT_ST_INT_CTRL: do_sccreg_wr15(data); break;
- default:
- logerror("\"%s\": %c : Unsupported WRx register:%02x\n", m_owner->tag(), 'A' + m_index, reg);
- }
+ scc_register_write(reg, data);
}
@@ -2014,7 +2161,7 @@ UINT8 z80scc_channel::data_read()
data = m_rx_fifo_rp_data();
// load error status from the FIFO
- m_rr1 = (m_rr1 & ~(RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR)) | m_rx_error_fifo[m_rx_fifo_rp];
+ m_rr1 = (m_rr1 & ~(RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR)) | m_rx_error_fifo[m_rx_fifo_rp]; // TODO: Status FIFO needs to be fixed
// trigger interrup and lock the fifo if an error is present
if (m_rr1 & (RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR))
@@ -2072,7 +2219,7 @@ void z80scc_channel::m_rx_fifo_rp_step()
m_rx_fifo_rp = 0;
}
- // check if FIFO is empty
+ // check if RX FIFO is empty
if (m_rx_fifo_rp == m_rx_fifo_wp)
{
// no more characters available in the FIFO
@@ -2080,6 +2227,16 @@ void z80scc_channel::m_rx_fifo_rp_step()
}
}
+/* Step TX read pointer */
+void z80scc_channel::m_tx_fifo_rp_step()
+{
+ m_tx_fifo_rp++;
+ if (m_tx_fifo_rp >= m_tx_fifo_sz)
+ {
+ m_tx_fifo_rp = 0;
+ }
+}
+
READ8_MEMBER (z80scc_device::da_r) { return m_chanA->data_read(); }
WRITE8_MEMBER (z80scc_device::da_w) { m_chanA->data_write(data); }
READ8_MEMBER (z80scc_device::db_r) { return m_chanB->data_read(); }
@@ -2090,28 +2247,65 @@ WRITE8_MEMBER (z80scc_device::db_w) { m_chanB->data_write(data); }
//-------------------------------------------------
void z80scc_channel::data_write(UINT8 data)
{
- m_tx_data = data;
-
- if ((m_wr5 & WR5_TX_ENABLE) && is_transmit_register_empty())
+ /* Tx FIFO is full or...? */
+ if ( !(m_rr0 & RR0_TX_BUFFER_EMPTY) && // NMOS/CMOS 1 slot "FIFO" is controlled by the TBE bit instead of fifo logic
+ ( (m_tx_fifo_wp + 1 == m_tx_fifo_rp) || ( (m_tx_fifo_wp + 1 == m_tx_fifo_sz) && (m_tx_fifo_rp == 0) )))
{
- LOG(("%s(%02x) \"%s\": %c : Transmit Data Byte '%02x' %c\n", FUNCNAME, data, m_owner->tag(), 'A' + m_index, m_tx_data, m_tx_data));
- transmit_register_setup(m_tx_data);
+ 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;
+ if (m_tx_fifo_wp >= m_tx_fifo_sz)
+ {
+ m_tx_fifo_wp = 0;
+ }
- // empty transmit buffer
- m_rr0 |= RR0_TX_BUFFER_EMPTY;
+ // Check FIFO fullness and set TBE bit accordingly
+ if (m_tx_fifo_sz == 1)
+ {
+ m_rr0 &= ~RR0_TX_BUFFER_EMPTY; // If only one FIFO position it is full now!
+ }
+ else 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_rr0 &= ~RR0_TX_BUFFER_EMPTY; // Indicate that the TX fifo is full
+ }else
+ m_rr0 |= RR0_TX_BUFFER_EMPTY; // or there is a slot in the FIFO available
- if (m_wr1 & WR1_TX_INT_ENABLE)
+ m_rr1 &= ~RR1_ALL_SENT; // All is definitelly not sent anymore
+ }
+
+ /* Transmitter enabled? */
+ if (m_wr5 & WR5_TX_ENABLE)
+ {
+ if (is_transmit_register_empty()) // Is the shift register loaded?
{
- m_uart->trigger_interrupt(m_index, INT_TRANSMIT);
+ 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();
+ m_rr1 |= RR1_ALL_SENT; // Now stuff is on its way again
+ m_rr0 |= RR0_TX_BUFFER_EMPTY; // And there is a slot in the FIFO available
}
}
- else
+ /* "While transmit interrupts are enabled, the nmos/cmos version sets the transmit interrupt pending
+ (TxIP) bit whenever the transmit buffer becomes empty. this means that the transmit buffer
+ must be full before the TxIP can be set. thus, when transmit interrupts are first enabled, the TxIP
+ will not be set until after the first character is written to the nmos/cmos." */
+ // check if to fire interrupt
+ if (m_wr1 & WR1_TX_INT_ENABLE)
{
- m_rr0 &= ~RR0_TX_BUFFER_EMPTY;
- //LOG(("%s(%02x) \"%s\": %c : failed to send %c,(%02x)\n", FUNCNAME, data, m_owner->tag(), 'A' + m_index, isascii(data) ? data : ' ', data));
+ if ((m_uart->m_variant & SET_ESCC) &&
+ (m_wr7p & WR7P_TX_FIFO_EMPTY) &&
+ m_tx_fifo_wp == m_tx_fifo_rp) // ESCC and fifo empty bit set and fifo is completelly empty?
+ {
+ m_uart->trigger_interrupt(m_index, INT_TRANSMIT); // Set TXIP bit
+ }
+ else if(m_rr0 & RR0_TX_BUFFER_EMPTY) // Check TBE bit and interrupt if one or more FIFO slots availble
+ {
+ m_uart->trigger_interrupt(m_index, INT_TRANSMIT); // Set TXIP bit
+ }
}
-
- m_rr1 &= ~RR1_ALL_SENT;
}
@@ -2126,12 +2320,12 @@ void z80scc_channel::receive_data(UINT8 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_rx_error_fifo[m_rx_fifo_wp] |= RR1_RX_OVERRUN_ERROR; // = m_rx_error;
+ m_rx_error_fifo[m_rx_fifo_wp] |= RR1_RX_OVERRUN_ERROR; // = m_rx_error; TODO: Status FIFO needs to be fixed
logerror("Receive_data() Error %02x\n", m_rx_error_fifo[m_rx_fifo_wp] & (RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR));
}
else
{
- m_rx_error_fifo[m_rx_fifo_wp] &= ~RR1_RX_OVERRUN_ERROR; // = m_rx_error;
+ m_rx_error_fifo[m_rx_fifo_wp] &= ~RR1_RX_OVERRUN_ERROR; // = m_rx_error; TODO: Status FIFO needs to be fixed
m_rx_fifo_wp++;
if (m_rx_fifo_wp >= m_rx_fifo_sz)
{
@@ -2191,8 +2385,13 @@ WRITE_LINE_MEMBER( z80scc_channel::cts_w )
else
m_rr0 &= ~RR0_CTS;
- // trigger interrupt
- if (m_wr1 & WR1_EXT_INT_ENABLE)
+ /* If the CTS IE bit in WR15 is set, this bit indicates the state of the /CTS pin while no interrupt is
+ pending, latches the state of the /CTS pin and generates an External/Status interrupt. Any odd
+ number of transitions on the /CTS pin causes another External/Status interrupt condition. If the
+ CTS IE bit is reset, it merely reports the current unlatched state of the /CTS pin.
+
+ Check that external interrupts are enabled and this one in particular and generate an interrupt on any change */
+ if ((m_wr1 & WR1_EXT_INT_ENABLE) && (m_wr15 & WR15_CTS))
{
// trigger interrupt
m_uart->trigger_interrupt(m_index, INT_EXTERNAL);
@@ -2235,7 +2434,14 @@ WRITE_LINE_MEMBER( z80scc_channel::dcd_w )
else
m_rr0 &= ~RR0_DCD;
- if (m_wr1 & WR1_EXT_INT_ENABLE)
+ /* If the DCD IE bit in WR15 is set, this bit indicates the state of the /DCD pin the last time the
+ Enabled External/Status bits changed. Any transition on the /DCD pin, while no interrupt is pending,
+ latches the state of the /DCD pin and generates an External/Status interrupt. Any odd number
+ of transitions on the /DCD pin while another External/Status interrupt condition. If the DCD IE is
+ reset, this bit merely reports the current, unlatched state of the /DCD pin.
+
+ Check that external interrupts are enabled and this one in particular and generate an interrupt on any change */
+ if ((m_wr1 & WR1_EXT_INT_ENABLE) && (m_wr15 & WR15_DCD))
{
// trigger interrupt
m_uart->trigger_interrupt(m_index, INT_EXTERNAL);
@@ -2333,7 +2539,9 @@ WRITE_LINE_MEMBER( z80scc_channel::rxc_w )
m_rx_clock++;
if (m_rx_clock == clocks)
+ {
m_rx_clock = 0;
+ }
}
}
}
@@ -2462,8 +2670,6 @@ void z80scc_channel::set_dtr(int state)
m_uart->m_out_dtrb_cb(m_dtr);
}
-
-
//-------------------------------------------------
// write_rx - called by terminal through rs232/diserial
// when character is sent to board
diff --git a/src/devices/machine/z80scc.h b/src/devices/machine/z80scc.h
index f68ad9760e6..69143eed02a 100644
--- a/src/devices/machine/z80scc.h
+++ b/src/devices/machine/z80scc.h
@@ -169,6 +169,7 @@ public:
UINT8 do_sccreg_rr5();
UINT8 do_sccreg_rr6();
UINT8 do_sccreg_rr7();
+ UINT8 do_sccreg_rr7p(){ return 0; } // Needs to be implemented for Synchronous mode
// UINT8 do_sccreg_rr8(); Short cutted due to frequent use
UINT8 do_sccreg_rr9();
UINT8 do_sccreg_rr10();
@@ -188,6 +189,7 @@ public:
void do_sccreg_wr5(UINT8 data);
void do_sccreg_wr6(UINT8 data);
void do_sccreg_wr7(UINT8 data);
+ void do_sccreg_wr7p(UINT8 data){}; // Needs to be implemented for Synchronous mode
void do_sccreg_wr8(UINT8 data);
void do_sccreg_wr9(UINT8 data);
void do_sccreg_wr10(UINT8 data);
@@ -204,6 +206,7 @@ public:
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();
@@ -228,6 +231,7 @@ public:
UINT8 m_rr5; // REG_RR5_WR5_OR_RR0
UINT8 m_rr6; // REG_RR6_LSB_OR_RR2
UINT8 m_rr7; // REG_RR7_MSB_OR_RR3
+ UINT8 m_rr7p;
UINT8 m_rr8; // REG_RR8_RECEIVE_DATA
UINT8 m_rr9; // REG_RR9_WR3_OR_RR13
UINT8 m_rr10; // REG_RR10_MISC_STATUS
@@ -246,8 +250,9 @@ public:
UINT8 m_wr5; // REG_WR5_TX_CONTROL
UINT8 m_wr6; // REG_WR6_SYNC_OR_SDLC_A
UINT8 m_wr7; // REG_WR7_SYNC_OR_SDLC_F
+ UINT8 m_wr7p; //
UINT8 m_wr8; // REG_WR8_TRANSMIT_DATA
- UINT8 m_wr9; // REG_WR9_MASTER_INT_CTRL
+ // UINT8 m_wr9; // REG_WR9_MASTER_INT_CTRL
UINT8 m_wr10; // REG_WR10_MSC_RX_TX_CTRL
UINT8 m_wr11; // REG_WR11_CLOCK_MODES
UINT8 m_wr12; // REG_WR12_LO_BAUD_GEN
@@ -454,7 +459,12 @@ protected:
WR5_DTR = 0x80
};
- /* SCC specifics */
+
+ enum
+ {
+ WR7P_TX_FIFO_EMPTY = 0x04
+ };
+
enum
{
WR9_CMD_MASK = 0xC0,
@@ -506,7 +516,19 @@ protected:
WR14_BRG_SOURCE = 0x02,
WR14_DTR_REQ_FUNC = 0x04,
WR14_AUTO_ECHO = 0x08,
- WR14_LOCAL_LOOPBACK = 0x010
+ WR14_LOCAL_LOOPBACK = 0x10
+ };
+
+ enum
+ {
+ WR15_WR7PRIME = 0x01,
+ WR15_ZEROCOUNT = 0x02,
+ WR15_STATUS_FIFO = 0x04,
+ WR15_DCD = 0x08,
+ WR15_SYNC = 0x10,
+ WR15_CTS = 0x20,
+ WR15_TX_EOM = 0x40,
+ WR15_BREAK_ABORT = 0x80
};
enum
@@ -526,6 +548,8 @@ protected:
unsigned int m_delayed_tx_brg_change;
unsigned int m_brg_const;
+ void scc_register_write(UINT8 reg, UINT8 data);
+ UINT8 scc_register_read(UINT8 reg);
void update_serial();
void set_dtr(int state);
void set_rts(int state);
@@ -557,7 +581,13 @@ protected:
int m_dcd; // data carrier detect latch
// transmitter state
- UINT8 m_tx_data; // transmit data register
+ UINT8 m_tx_data_fifo[4]; // data FIFO
+ UINT8 m_tx_error_fifo[4]; // 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
+ // UINT8 m_tx_data; // transmit data register
int m_tx_clock; // transmit clock pulse count
int m_dtr; // data terminal ready
@@ -631,9 +661,15 @@ public:
DECLARE_READ8_MEMBER( cb_r ) { return m_chanB->control_read(); }
DECLARE_WRITE8_MEMBER( cb_w ) { m_chanB->control_write(data); }
+ DECLARE_READ8_MEMBER( zbus_r );
+ DECLARE_WRITE8_MEMBER( zbus_w );
+
// interrupt acknowledge
int m1_r();
+ // Single registers instances accessed from both channels
+ UINT8 m_wr9; // REG_WR9_MASTER_INT_CTRL
+
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); }
@@ -726,6 +762,7 @@ protected:
devcb_write_line m_out_txdrqb_cb;
int m_int_state[6]; // interrupt state
+ int m_int_source[6]; // interrupt source
int m_variant;
UINT8 m_wr0_ptrbits;