summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Michael Zapf <Michael.Zapf@mizapf.de>2018-03-14 18:17:00 +0100
committer Michael Zapf <Michael.Zapf@mizapf.de>2018-03-31 00:38:31 +0200
commitfda26ee7dded25d83e4936d906984bf40a2ae980 (patch)
treec50e7428c1ddf7050df047fb58013088dff747a5
parentbdc4288fe117b65ee11438e1e1e5601219e859f7 (diff)
ti99: Hexbus floppy system; logging updates
-rw-r--r--scripts/src/bus.lua2
-rw-r--r--src/devices/bus/hexbus/hexbus.cpp83
-rw-r--r--src/devices/bus/hexbus/hexbus.h24
-rw-r--r--src/devices/bus/hexbus/hx5102.cpp665
-rw-r--r--src/devices/bus/hexbus/hx5102.h79
-rw-r--r--src/devices/bus/hexbus/tp0370.cpp340
-rw-r--r--src/devices/bus/hexbus/tp0370.h85
-rw-r--r--src/devices/bus/ti99/internal/998board.cpp435
-rw-r--r--src/devices/bus/ti99/internal/998board.h63
-rw-r--r--src/devices/cpu/tms9900/tms9995.cpp301
10 files changed, 1703 insertions, 374 deletions
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua
index 95761c42aef..5dc09dceda3 100644
--- a/scripts/src/bus.lua
+++ b/scripts/src/bus.lua
@@ -870,6 +870,8 @@ if (BUSES["HEXBUS"]~=null) then
MAME_DIR .. "src/devices/bus/hexbus/hexbus.h",
MAME_DIR .. "src/devices/bus/hexbus/hx5102.cpp",
MAME_DIR .. "src/devices/bus/hexbus/hx5102.h",
+ MAME_DIR .. "src/devices/bus/hexbus/tp0370.cpp",
+ MAME_DIR .. "src/devices/bus/hexbus/tp0370.h",
}
end
diff --git a/src/devices/bus/hexbus/hexbus.cpp b/src/devices/bus/hexbus/hexbus.cpp
index 907c77fa745..257a82b5054 100644
--- a/src/devices/bus/hexbus/hexbus.cpp
+++ b/src/devices/bus/hexbus/hexbus.cpp
@@ -128,6 +128,11 @@
By default, instances of "hexbus_chained_device" own an outbound
hexbus slot as a subdevice; this may be overwritten by subclasses.
+ Line state received via the Hexbus
+ +------+------+------+------+------+------+------+------+
+ | ADB3 | ADB2 | - | HSK* | 0 | BAV* | ADB1 | ADB0 |
+ +------+------+------+------+------+------+------+------+
+
References
----------
@@ -145,8 +150,14 @@
// Devices
#include "hx5102.h"
+#define LOG_WRITE (1U<<1) // Write operation
+
+#define VERBOSE ( LOG_GENERAL )
+
+#include "logmacro.h"
+
// Hexbus instance
-DEFINE_DEVICE_TYPE_NS(HEXBUS, bus::hexbus, hexbus_device, "hexbus", "Hexbus")
+DEFINE_DEVICE_TYPE_NS(HEXBUS, bus::hexbus, hexbus_device, "hexbus", "Hexbus connector")
namespace bus { namespace hexbus {
@@ -226,24 +237,20 @@ void hexbus_chained_device::hexbus_write(uint8_t data)
{
m_myvalue = data;
- uint8_t inbound_value = 0xff;
- uint8_t outbound_value = 0xff;
-
- // Determine the current bus level from the values of the
- // other devices left and right from us
- if (m_hexbus_inbound != nullptr)
- inbound_value = m_hexbus_inbound->read(INBOUND);
-
- if (m_hexbus_outbound != nullptr)
- outbound_value = m_hexbus_outbound->read(OUTBOUND);
+ uint8_t otherval = hexbus_get_levels();
+ // LOGMASKED(LOG_WRITE, ".. otherval=%02x\n", otherval);
// What is the new bus level?
- uint8_t newvalue = inbound_value & outbound_value & m_myvalue;
+ // The data lines are not supposed to be set by multiple devices
+ // We assume that sending data overrides all data line levels.
+ // This is emulated by pulling the data lines to ones.
+ uint8_t newvalue = (otherval | 0xc3) & m_myvalue;
// If it changed, propagate to both directions.
if (newvalue != m_current_bus_value)
{
- hexbus_value_changed(newvalue);
+ LOGMASKED(LOG_WRITE, "Trying to write %02x, actually: %02x (current=%02x)\n", data, newvalue, m_current_bus_value);
+
m_current_bus_value = newvalue;
if (m_hexbus_inbound != nullptr)
@@ -251,10 +258,29 @@ void hexbus_chained_device::hexbus_write(uint8_t data)
if (m_hexbus_outbound != nullptr)
m_hexbus_outbound->write(OUTBOUND, m_current_bus_value);
+
}
}
/*
+ Get levels from other devices (without changing anything).
+*/
+uint8_t hexbus_chained_device::hexbus_get_levels()
+{
+ uint8_t inbound_value = 0xff;
+ uint8_t outbound_value = 0xff;
+
+ // other devices left and right from us
+ if (m_hexbus_inbound != nullptr)
+ inbound_value = m_hexbus_inbound->read(INBOUND);
+
+ if (m_hexbus_outbound != nullptr)
+ outbound_value = m_hexbus_outbound->read(OUTBOUND);
+
+ return (inbound_value & outbound_value);
+}
+
+/*
Called from the Hexbus user, that is, the device that subclasses
hexbus_chained_device, like the HX5102
*/
@@ -284,20 +310,33 @@ void hexbus_chained_device::bus_write(int dir, uint8_t data)
{
hexbus_device* hexbuscont = (dir == INBOUND)? m_hexbus_inbound : m_hexbus_outbound;
- // Notify device
- if (data != m_current_bus_value)
- hexbus_value_changed(data);
+ // Propagate this value first
+ if (hexbuscont != nullptr)
+ hexbuscont->write(dir, data);
+ uint8_t oldvalue = m_current_bus_value;
m_current_bus_value = data;
- // Propagate
- if (hexbuscont != nullptr)
- hexbuscont->write(dir, data);
+ // Notify device
+ // Caution: Calling hexbus_value_changed may cause further activities
+ // that change the bus again
+ if (data != oldvalue)
+ {
+ LOGMASKED(LOG_WRITE, "Hexbus value changed: %02x -> %02x\n", oldvalue, data);
+ hexbus_value_changed(data);
+ }
}
-MACHINE_CONFIG_START(hexbus_chained_device::device_add_mconfig)
- MCFG_HEXBUS_ADD("hexbus")
-MACHINE_CONFIG_END
+/*
+ Convenience function to calculate the bus value. Used by subclasses.
+*/
+uint8_t hexbus_chained_device::to_line_state(uint8_t data, bool bav, bool hsk)
+{
+ uint8_t lines = ((data & 0x0c)<<4) | (data & 0x03);
+ if (!bav) lines |= 0x04;
+ if (!hsk) lines |= 0x10;
+ return lines;
+}
// ------------------------------------------------------------------------
diff --git a/src/devices/bus/hexbus/hexbus.h b/src/devices/bus/hexbus/hexbus.h
index 3c3280cca91..d94a91c47a5 100644
--- a/src/devices/bus/hexbus/hexbus.h
+++ b/src/devices/bus/hexbus/hexbus.h
@@ -23,6 +23,15 @@ enum
OUTBOUND = 1
};
+/* Line */
+enum
+{
+ HEXBUS_LINE_HSK = 0x10,
+ HEXBUS_LINE_BAV = 0x04,
+ HEXBUS_LINE_BIT32 = 0xc0,
+ HEXBUS_LINE_BIT10 = 0x03
+};
+
class hexbus_device;
class hexbus_chained_device;
@@ -54,8 +63,6 @@ public:
virtual void device_start() override;
protected:
- virtual void device_add_mconfig(machine_config &config) override;
-
void set_outbound_hexbus(hexbus_device *outbound) { m_hexbus_outbound = outbound; }
// Link to the inbound Hexbus (if not null, see Oso chip)
@@ -72,13 +79,24 @@ protected:
virtual void bus_write(int dir, uint8_t data) override;
// Methods to be used from subclasses
+ // Write a byte to the Hexbus. Returns the actual line state.
+ // This is important because the bus is a wired-and bus.
void hexbus_write(uint8_t data);
+
+ // Levels on the bus, except for this device
+ uint8_t hexbus_get_levels();
+
+ // Read hexbus
uint8_t hexbus_read();
- // For interrupts
+ // Callback for changes on the hexbus
virtual void hexbus_value_changed(uint8_t data) { };
+ // Levels of the lines at this device. 0 means pull down, 1 means release.
uint8_t m_myvalue;
+
+ // Utility method to create a Hexbus line state
+ uint8_t to_line_state(uint8_t data, bool bav, bool hsk);
};
// ------------------------------------------------------------------------
diff --git a/src/devices/bus/hexbus/hx5102.cpp b/src/devices/bus/hexbus/hx5102.cpp
index 71fe674506f..03d00497741 100644
--- a/src/devices/bus/hexbus/hx5102.cpp
+++ b/src/devices/bus/hexbus/hx5102.cpp
@@ -5,30 +5,683 @@
Hexbus floppy disk drive
HX5102
- Work in progress
+ Memory map
+ 0000 - 1FFF: ROM1 (8 KiB, circuit u25, EPROM 2564)
+ 2000 - 3FFF: ROM2 (8 KiB, circuit u29, EPROM 2564)
+ 4000 - DFFF: Mirrors of ROM1/ROM2
+ E000 - EFFF: SRAM (4 KiB)
+ F000 - F0F9: On-Chip RAM (TMS9995)
+ F7E0 - F7EF: Memory-mapped access to NEC uPD765 / Intel 8272A
+ F7F0 - F7FF: Memory-mapped access to IBC
+ F800 - FFF9: Unmapped
+ FFFA - FFFF: On-Chip RAM (TMS9995)
+
+ NEC uPD765 / Intel 8272A
+ F7E0 R Main status register (MSR)
+ F7E4 R Data register (FIFO read)
+ F7E8 W Command register (FIFO write)
+
+ Supporting circuitry
+ F7E2 R DMA read
+ F7E6 - -
+ F7EA W DMA write
+ F7EC W Ready lock
+ F7EE - -
+
+ Intelligent Bus Controller (Hexbus)
+ F7F0 R Received data
+ F7F2 R Status register
+ F7F4 -
+ F7F6 -
+ F7F8 W Transmit data
+ F7FA W Control register
+ F7FC -
+ F7FE -
+
+ Ports (CRU bit): read
+ 17E0 (0): Controller INT line
+ 17E2 (1): Motor spinning (monoflop 1)
+ 17E4 (2): Timeout for disk operations (monoflop 2)
+ 17E6 (3): -
+ 17E8 (4): Drive 0 cylinder count (0=40, 1=77)
+ 17EA (5): Drive 1 cylinder count
+ 17EC (6): Drive 2 cylinder count
+ 17EE (7): Drive 3 cylinder count
+
+ Ports (CRU bit): write
+ 17E0 (0): Precompensation
+ 17E2 (1): Motor trigger
+ 17E4 (2): -
+ 17E6 (3): Step dir (1=inwards)
+ 17E8 (4): When 1, assert DACK* (set to 0)
+ 17EA (5): Step pulse (up)
+ 17EC (6): Timeout flipflop trigger
+ 17EE (7): RESET* the controller (goes to RESET input, inverted)
+ 17F0 (8): Drive select drive 0 (DSK1)
+ 17F2 (9): Drive select drive 1 (DSK2)
+ 17F4 (10): Drive select drive 2 (DSK3)
+ 17F6 (11): Drive select drive 3 (DSK4)
+ 17F8 (12): Separate Motor line for internal drive (not used)
+ 17FA (13): Not connected; turned on before sector I/O, format track, reset drives; turned off once when reporting status
+ 17FC (14): Arm READY circuit
+ 17FE (15): Not connected; possibly in test mode only
Michael Zapf
- June 2017
+ March 2018
*****************************************************************************/
#include "emu.h"
#include "hx5102.h"
+#include "formats/ti99_dsk.h"
+
+#define LOG_HEXBUS (1U<<1) // Hexbus operation
+#define LOG_RESET (1U<<2) // Reset
+#define LOG_WARN (1U<<3) // Warnings
+#define LOG_READY (1U<<4) // READY
+#define LOG_SIGNALS (1U<<5) // IRQ/DRQ
+#define LOG_CRU (1U<<6) // CRU
+#define LOG_RAM (1U<<7) // RAM
+#define LOG_DMA (1U<<8) // DMA
+#define LOG_MOTOR (1U<<9) // Motor activity
+#define LOG_STATUS (1U<<10) // Main status register
+#define LOG_FIFO (1U<<11) // Data register
+
+// Minimum log should be config and warnings
+#define VERBOSE ( LOG_GENERAL | LOG_WARN )
+
+#include "logmacro.h"
-#define TRACE_HEXBUS 0
+#define TMS9995_TAG "drivecpu"
+#define DSR_TAG "dsr"
+#define FDC_TAG "i8272a"
+#define IBC_TAG "ibc_1052911"
+#define MTRD_TAG "u24_motor_mf"
+#define MTSPD_TAG "u24_motor_speed_mf"
+#define READYFF_TAG "u21_ready_ff"
+#define RAM1_TAG "u12_ram"
+#define RAM2_TAG "u19_ram"
+#define ROM1_TAG "u25_rom"
+#define ROM2_TAG "u29_rom"
-DEFINE_DEVICE_TYPE_NS(HX5102, bus::hexbus, hx5102_device, "hx5102", "TI Hexbus Floppy")
+#define MOTOR_TIMER 1
+
+DEFINE_DEVICE_TYPE_NS(HX5102, bus::hexbus, hx5102_device, "ti_hx5102", "TI Hexbus Floppy Drive")
namespace bus { namespace hexbus {
+ADDRESS_MAP_START(hx5102_device::memmap)
+ AM_RANGE(0x0000, 0xffff) AM_READWRITE(read, write)
+ADDRESS_MAP_END
+
+/*
+ CRU access to CRU addresses 1700 - 17FE)
+*/
+ADDRESS_MAP_START(hx5102_device::crumap)
+ AM_RANGE(0x17e0>>4,0x17fe>>4) AM_READ(cruread)
+ AM_RANGE(0x17e0>>1,0x17fe>>1) AM_WRITE(cruwrite)
+ADDRESS_MAP_END
+
hx5102_device::hx5102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock):
- hexbus_chained_device(mconfig, HX5102, tag, owner, clock)
+ hexbus_chained_device(mconfig, HX5102, tag, owner, clock),
+ m_flopcpu(*this, TMS9995_TAG),
+ m_ready_old(CLEAR_LINE),
+ m_motor_on(false),
+ m_mspeed_on(false),
+ m_pending_int(false),
+ m_dcs(false),
+ m_dack(false),
+ m_dacken(false),
+ m_wait(false),
+ m_hexbus_ctrl(*this, IBC_TAG),
+ m_floppy_ctrl(*this, FDC_TAG),
+ m_motormf(*this, MTRD_TAG),
+ m_speedmf(*this, MTSPD_TAG),
+ m_readyff(*this, READYFF_TAG),
+ m_ram1(*this, RAM1_TAG),
+ m_ram2(*this, RAM2_TAG)
+{
+}
+
+WRITE8_MEMBER( hx5102_device::external_operation )
+{
+ static const char* extop[8] = { "inv1", "inv2", "IDLE", "RSET", "inv3", "CKON", "CKOF", "LREX" };
+ if (offset != IDLE_OP) LOGMASKED(LOG_WARN, "External operation %s not implemented on HX5102 board\n", extop[offset]);
+}
+
+
+/*
+ Read operation. We cannot use the convenient address maps because the
+ READY circuit requires a flag created from the address lines (m_dcs) which
+ must be reset on accesses outside of the i8272a memory mapping area.
+
+ V1 = A0 & A1 (A0=MSB) 11.. .... .... ....
+ V2 = A4* & A5 & A6 & A7 & A8 & A9 & A10 .... 0111 111. ....
+
+ PAL equations
+ ROM1 = MEM & V1* & A2* & WE* = 0000..1FFF, 4000..5FFF, 8000..9FFF
+ ROM2 = MEM & V1* & A2 & WE* = 2000..3FFF, 6000..7FFF, A000..BFFF
+ RAM = MEM & V1 & A2 & A3* = E000..EFFF
+ DCS = MEM & V1 & A2 & A3 & A15* & V2 & A11* & A14* = F7E0,F7E4,F7E8,F7EC
+ HCS = MEM & V1 & A2 & A3 & A15* & V2 & A11 & A13* = F7F0,F7F2,F7F8,F7FA
+ DACK = MEM & V1 & A2 & A3 & A15* & V2 & A11* & A13* & A14 = F7E2,F7EA
+ AZ = MEM & V1 & A2 & A3 & A15* & V2 & A11* & A12* & A13* & A14* = F7E0
+ CRU = MEM* & V1* & A2* & A3 & V2 = 17E0..17FE
+ RD = MEM & V1 & A2 & A3 & A15* & V2 & A12* & DBIN = F7E0,F7E2,F7E4,F7E6,F7F0,F7F2,F7F4,F7F6
+ | MEM & V1 & A2 & A3* & DBIN = E000-EFFF
+ WR = MEM & V1 & A2 & A3 & A15* & V2 & A12 & A13* & WE = F7E8,F7EA,F7F8,F7FA
+ | MEM & V1 & A2 & A3* & WE = E000-EFFF
+
+*/
+
+/*
+ Reading from the address space of the drive.
+*/
+READ8_MEMBER( hx5102_device::read )
+{
+ bool ramen1 = ((offset & 0xf800)==0xe000);
+ bool ramen2 = ((offset & 0xf800)==0xe800);
+ bool romen1 = ((offset & 0xc000)!=0xc000) && ((offset & 0x2000)==0);
+ bool romen2 = ((offset & 0xc000)!=0xc000) && ((offset & 0x2000)!=0);
+ bool hcs = ((offset & 0xfff5)==0xf7f0);
+
+ m_dcs = ((offset & 0xfff3)==0xf7e0);
+ m_dack = ((offset & 0xfff7)==0xf7e2);
+
+ // RAM 1
+ uint8_t val;
+ if (ramen1)
+ {
+ val = m_ram1->pointer()[offset & 0x07ff];
+ LOGMASKED(LOG_RAM, "RAM %04x -> %02x\n", (offset & 0x07ff)|0xe000, val);
+ return val;
+ }
+
+ // RAM 2
+ if (ramen2)
+ {
+ val = m_ram2->pointer()[offset & 0x07ff];
+ LOGMASKED(LOG_RAM, "RAM %04x -> %02x\n", (offset & 0x07ff)|0xe800, val);
+ return val;
+ }
+
+ // ROM 1
+ if (romen1)
+ return m_rom1[offset & 0x1fff];
+
+ // ROM 2
+ if (romen2)
+ return m_rom2[offset & 0x1fff];
+
+ // Floppy drive controller
+ if (m_dcs)
+ return fdc_read(space, offset&0x000f);
+
+ // Hexbus controller
+ if (hcs)
+ return ibc_read(space, offset&0x000f);
+
+ // DMA
+ if (m_dack)
+ {
+ // Pick DMA byte from the controller; this automatically signals DACK*
+ // Thus the drive CPU is the target for the DMA transfer
+ uint8_t val = m_floppy_ctrl->dma_r();
+ LOGMASKED(LOG_DMA, "i8272a.dma -> %02x '%c'\n", val, (val>33 && val<127)? val : '.');
+ return val;
+ }
+
+ if ((offset & 1)==0) LOGMASKED(LOG_WARN, "Unmapped read access: %04x\n", offset);
+ return 0;
+}
+
+/*
+ Writing into the address space of the drive.
+*/
+WRITE8_MEMBER( hx5102_device::write )
{
+ bool ramen1 = ((offset & 0xf800)==0xe000);
+ bool ramen2 = ((offset & 0xf800)==0xe800);
+ bool hcs = ((offset & 0xfff5)==0xf7f0);
+ m_dcs = ((offset & 0xfff3)==0xf7e0);
+ m_dack = ((offset & 0xfff7)==0xf7e2);
+
+ // RAM 1
+ if (ramen1)
+ {
+ LOGMASKED(LOG_RAM, "RAM %04x <- %02x\n", (offset & 0x07ff)|0xe000, data);
+ m_ram1->pointer()[offset & 0x07ff] = data;
+ return;
+ }
+
+ // RAM 2
+ if (ramen2)
+ {
+ LOGMASKED(LOG_RAM, "RAM %04x <- %02x\n", (offset & 0x07ff)|0xe800, data);
+ m_ram2->pointer()[offset & 0x07ff] = data;
+ return;
+ }
+
+ // Floppy drive controller
+ if (m_dcs)
+ {
+ fdc_write(space, offset&0x000f, data);
+ return;
+ }
+
+ // Hexbus controller
+ if (hcs)
+ {
+ ibc_write(space, offset&0x000f, data);
+ return;
+ }
+
+ // DMA
+ if (m_dack)
+ {
+ m_floppy_ctrl->dma_w(data);
+ LOGMASKED(LOG_DMA, "i8272a.dma <- %02x '%c'\n", data, (data>33 && data<127)? data : '.');
+ return;
+ }
+
+ if ((offset & 1)==0) LOGMASKED(LOG_WARN, "Unmapped write access: %04x\n", offset);
}
+
+/*
+ Clock line from the CPU. Used to control wait state generation.
+*/
+WRITE_LINE_MEMBER( hx5102_device::clock_out )
+{
+ m_readyff->clock_w(state);
+}
+
+/*
+ Input from the Hexbus
+*/
void hx5102_device::hexbus_value_changed(uint8_t data)
{
- if (TRACE_HEXBUS) logerror("Hexbus value changed to %02x\n", data);
+ m_hexbus_ctrl->from_hexbus(data);
+}
+
+/*
+ Propagate READY signals to the CPU. This is used to hold the CPU
+ during DMA accesses.
+*/
+WRITE_LINE_MEMBER( hx5102_device::board_ready )
+{
+ if (m_ready_old != state)
+ {
+ LOGMASKED(LOG_READY, "READY = %d\n", state);
+ }
+
+ m_ready_old = (line_state)state;
+ m_flopcpu->ready_line(state);
+}
+
+/*
+ Trigger RESET.
+*/
+WRITE_LINE_MEMBER( hx5102_device::board_reset )
+{
+ LOGMASKED(LOG_RESET, "Incoming RESET line = %d\n", state);
+
+ if (machine().phase() != machine_phase::INIT)
+ {
+ // Setting ready to true so that automatic wait states are disabled
+ m_flopcpu->ready_line(ASSERT_LINE);
+ m_flopcpu->reset_line(ASSERT_LINE);
+ }
+}
+
+/*
+ Effect from the motor monoflop.
+*/
+WRITE_LINE_MEMBER( hx5102_device::motor_w )
+{
+ m_motor_on = (state==ASSERT_LINE);
+ LOGMASKED(LOG_MOTOR, "Motor %s\n", m_motor_on? "start" : "stop");
+ m_floppy->mon_w(m_motor_on? 0 : 1);
+ update_readyff_input();
+}
+
+/*
+ Effect from the speed monoflop. This is essentially a watchdog to
+ check whether the lock on the CPU must be released due to an error.
+*/
+WRITE_LINE_MEMBER( hx5102_device::mspeed_w )
+{
+ m_mspeed_on = (state==ASSERT_LINE);
+ LOGMASKED(LOG_READY, "Speedcheck %s\n", m_mspeed_on? "on" : "off");
+ update_readyff_input();
+}
+
+/*
+ Read access to the floppy controller
+*/
+READ8_MEMBER(hx5102_device::fdc_read)
+{
+ uint8_t val = 0;
+ switch (offset)
+ {
+ case 0:
+ // Main status register
+ val = m_floppy_ctrl->msr_r();
+ LOGMASKED(LOG_STATUS, "i8272A.msr -> %02x\n", val);
+ break;
+ case 4:
+ // FIFO read
+ val = m_floppy_ctrl->fifo_r();
+ LOGMASKED(LOG_FIFO, "i8272A.fifo -> %02x\n", val);
+ break;
+ }
+ return val;
+}
+
+/*
+ Write access to the floppy controller
+*/
+WRITE8_MEMBER(hx5102_device::fdc_write)
+{
+ m_dcs = ((offset & 0x0003)==0);
+
+ switch (offset)
+ {
+ case 0x08:
+ // Command register (FIFO write)
+ LOGMASKED(LOG_STATUS, "i8272A.fifo <- %02x\n", data);
+ m_floppy_ctrl->fifo_w(data);
+ break;
+ case 0x0c:
+ // DMA lock
+ LOGMASKED(LOG_READY, "Lock READY\n", data);
+ update_readyff_input();
+ break;
+ }
+}
+
+void hx5102_device::update_readyff_input()
+{
+ LOGMASKED(LOG_READY, "MON=%d, MSP=%d, WAIT=%d, INT*=%d, DRQ*=%d, DCS=%d\n", m_motor_on, m_mspeed_on, m_wait, !m_pending_int, !m_pending_drq, m_dcs);
+ m_readyff->d_w(m_motor_on && m_mspeed_on && m_wait && !m_pending_int && !m_pending_drq && m_dcs);
+}
+
+/*
+ Access to the Hexbus controller
+*/
+READ8_MEMBER(hx5102_device::ibc_read)
+{
+ if ((offset & 1)==0)
+ return m_hexbus_ctrl->read(space, (offset>>1)&1);
+ else
+ return 0;
+}
+
+WRITE8_MEMBER(hx5102_device::ibc_write)
+{
+ if ((offset & 1)==0)
+ m_hexbus_ctrl->write(space, (offset>>1)&1, data);
+}
+
+WRITE8_MEMBER(hx5102_device::hexbus_out)
+{
+ LOGMASKED(LOG_HEXBUS, "hexbus out: %02x\n", data);
+
+ // Get the other levels and set our own states
+ uint8_t newlevel = hexbus_get_levels() & data;
+ m_hexbus_ctrl->update_lines((newlevel & 0x04)==0, (newlevel & 0x10)==0);
+
+ // Now set the bus. This may entail further changes, incoming via hexbus_value_changed.
+ hexbus_write(data);
+}
+
+/*
+ Latch the HSK* to low.
+*/
+WRITE_LINE_MEMBER(hx5102_device::hsklatch_out)
+{
+ LOGMASKED(LOG_HEXBUS, "Latching HSK*\n");
+ m_myvalue &= ~HEXBUS_LINE_HSK;
+}
+
+/*
+ CRU read access.
+
+ 7 6 5 4 3 2 1 0
+ +-----+-----+-----+-----+-----+-----+-----+-----+
+ | TD3 | TD2 | TD1 | TD0 | 0 | TIM | MON | INT |
+ +-----+-----+-----+-----+-----+-----+-----+-----+
+
+ TDx = Tracks for drive x; 0 = 40, 1 = 77
+ TIM = Timeout
+ MON = Motor on
+ INT = Interrupt from i8272A
+*/
+READ8_MEMBER(hx5102_device::cruread)
+{
+ uint8_t crubits = 0;
+ // LOGMASKED(LOG_CRU, "Reading CRU addresses %04x-%04x\n", 0x17e0 + (offset<<4), 0x17ee + (offset<<4));
+ if (m_pending_int) crubits |= 0x01;
+ if (m_motor_on) crubits |= 0x02;
+ if (m_mspeed_on) crubits |= 0x04;
+ return crubits;
+}
+
+/*
+ CRU write access.
+*/
+WRITE8_MEMBER(hx5102_device::cruwrite)
+{
+ // LOG("Writing CRU address %04x: %x\n", 0x17e0 + (offset<<1), data);
+ switch (offset)
+ {
+ case 0:
+ LOGMASKED(LOG_CRU, "Set precompensation = %d\n", data);
+ break;
+ case 1:
+ if (data==1)
+ {
+ LOGMASKED(LOG_CRU, "Trigger motor monoflop\n");
+ }
+ m_motormf->b_w(data);
+ break;
+ case 2:
+ LOGMASKED(LOG_CRU, "Set undefined CRU bit 2 to %d\n", data);
+ break;
+ case 3:
+ LOGMASKED(LOG_CRU, "Set step direction = %d\n", data);
+ m_floppy->dir_w((data==0)? 1 : 0);
+ break;
+ case 4:
+ if (data==1)
+ {
+ LOGMASKED(LOG_CRU, "Assert DACK*\n");
+ m_dacken = (data != 0);
+ }
+ break;
+ case 5:
+ if (data==1)
+ {
+ LOGMASKED(LOG_CRU, "Step pulse\n");
+ }
+ m_floppy->stp_w((data==0)? 1 : 0);
+ break;
+ case 6:
+ if (data==1)
+ {
+ LOGMASKED(LOG_CRU, "Start watchdog\n");
+ }
+ m_speedmf->b_w(data);
+ break;
+ case 7:
+ if (data==0)
+ {
+ LOGMASKED(LOG_CRU, "Reset i8272A controller\n");
+ m_floppy_ctrl->soft_reset();
+ }
+ break;
+ case 8:
+ LOGMASKED(LOG_CRU, "Set drive select 0 to %d\n", data);
+ break;
+ case 9:
+ LOGMASKED(LOG_CRU, "Set drive select 1 to %d\n", data);
+ break;
+ case 10:
+ LOGMASKED(LOG_CRU, "Set drive select 2 to %d\n", data);
+ break;
+ case 11:
+ LOGMASKED(LOG_CRU, "Set drive select 3 to %d\n", data);
+ break;
+ case 12:
+ LOGMASKED(LOG_CRU, "Set auxiliary motor line to %d\n", data);
+ break;
+ case 13:
+ LOGMASKED(LOG_CRU, "Set CRU bit 13 to %d (unused)\n", data);
+ break;
+ case 14:
+ m_wait = (data!=0);
+ LOGMASKED(LOG_CRU, "READY circuit %s\n", m_wait? "active" : "inactive" );
+ update_readyff_input();
+ break;
+ case 15:
+ LOGMASKED(LOG_CRU, "Set CRU bit 15 to %d (unused)\n", data);
+ break;
+ }
+}
+
+/*
+ Device lifecycle.
+*/
+void hx5102_device::device_start()
+{
+ m_floppy = static_cast<floppy_image_device*>(subdevice("d0")->subdevices().first());
+
+ m_rom1 = (uint8_t*)memregion(DSR_TAG)->base();
+ m_rom2 = (uint8_t*)memregion(DSR_TAG)->base() + 0x2000;
+}
+
+/*
+ Device lifecycle.
+*/
+void hx5102_device::device_reset()
+{
+ board_reset(ASSERT_LINE);
+ board_ready(ASSERT_LINE);
+ // set_floppy must be here, because upd765_family_device::device_start
+ // resets the device links to null
+ m_floppy_ctrl->set_floppy(m_floppy);
+}
+
+/*
+ Callbacks from the i8272A chip
+ Interrupt
+*/
+WRITE_LINE_MEMBER( hx5102_device::fdc_irq_w )
+{
+ line_state irq = state? ASSERT_LINE : CLEAR_LINE;
+ LOGMASKED(LOG_SIGNALS, "INTRQ callback = %d\n", irq);
+ m_pending_int = state;
+ update_readyff_input();
+}
+
+/*
+ Callbacks from the i8272A chip
+ DMA request
+*/
+WRITE_LINE_MEMBER( hx5102_device::fdc_drq_w )
+{
+ line_state drq = state? ASSERT_LINE : CLEAR_LINE;
+ LOGMASKED(LOG_SIGNALS, "DRQ callback = %d\n", drq);
+ m_pending_drq = state;
+ update_readyff_input();
+}
+
+/*
+ Define the floppy formats.
+*/
+FLOPPY_FORMATS_MEMBER(hx5102_device::floppy_formats)
+ FLOPPY_TI99_SDF_FORMAT,
+ FLOPPY_TI99_TDF_FORMAT
+FLOPPY_FORMATS_END
+
+/*
+ Only one fixed floppy drive in the device.
+ External connectors are available, though.
+*/
+static SLOT_INTERFACE_START( hx5102_drive )
+ SLOT_INTERFACE( "525dd", FLOPPY_525_DD )
+SLOT_INTERFACE_END
+
+/*
+ HX5102 configuration
+*/
+MACHINE_CONFIG_START(hx5102_device::device_add_mconfig)
+ // Hexbus controller
+ MCFG_DEVICE_ADD(IBC_TAG, IBC, 0)
+ MCFG_IBC_HEXBUS_OUT_CALLBACK(WRITE8(hx5102_device, hexbus_out))
+ MCFG_IBC_HSKLATCH_CALLBACK(WRITELINE(hx5102_device, hsklatch_out))
+
+ // Outgoing socket for downstream devices
+ MCFG_HEXBUS_ADD("hexbus")
+
+ // TMS9995 CPU @ 12.0 MHz
+ MCFG_TMS99xx_ADD(TMS9995_TAG, TMS9995, XTAL(12'000'000), memmap, crumap)
+ MCFG_TMS9995_EXTOP_HANDLER( WRITE8(hx5102_device, external_operation) )
+ MCFG_TMS9995_CLKOUT_HANDLER( WRITELINE(hx5102_device, clock_out) )
+
+ // Disk controller i8272A
+ // Not connected: Select lines (DS0, DS1), Head load (HDL), VCO
+ // Tied to 1: READY
+ // Tied to 0: TC
+ MCFG_I8272A_ADD(FDC_TAG, false)
+ MCFG_UPD765_INTRQ_CALLBACK(WRITELINE(hx5102_device, fdc_irq_w))
+ MCFG_UPD765_DRQ_CALLBACK(WRITELINE(hx5102_device, fdc_drq_w))
+ MCFG_FLOPPY_DRIVE_ADD("d0", hx5102_drive, "525dd", hx5102_device::floppy_formats)
+ MCFG_FLOPPY_DRIVE_SOUND(true)
+
+ // Monoflops
+ MCFG_DEVICE_ADD(MTRD_TAG, TTL74123, 0)
+ MCFG_TTL74123_CONNECTION_TYPE(TTL74123_GROUNDED)
+ MCFG_TTL74123_RESISTOR_VALUE(RES_K(200))
+ MCFG_TTL74123_CAPACITOR_VALUE(CAP_U(47))
+ MCFG_TTL74123_A_PIN_VALUE(0)
+ MCFG_TTL74123_B_PIN_VALUE(1)
+ MCFG_TTL74123_CLEAR_PIN_VALUE(1)
+ MCFG_TTL74123_OUTPUT_CHANGED_CB(WRITELINE(hx5102_device, motor_w))
+
+ MCFG_DEVICE_ADD(MTSPD_TAG, TTL74123, 0)
+ MCFG_TTL74123_CONNECTION_TYPE(TTL74123_GROUNDED)
+ MCFG_TTL74123_RESISTOR_VALUE(RES_K(200))
+ MCFG_TTL74123_CAPACITOR_VALUE(CAP_U(10))
+ MCFG_TTL74123_A_PIN_VALUE(0)
+ MCFG_TTL74123_B_PIN_VALUE(1)
+ MCFG_TTL74123_CLEAR_PIN_VALUE(1)
+ MCFG_TTL74123_OUTPUT_CHANGED_CB(WRITELINE(hx5102_device, mspeed_w))
+
+ // READY flipflop
+ MCFG_DEVICE_ADD(READYFF_TAG, TTL7474, 0)
+ MCFG_7474_COMP_OUTPUT_CB(WRITELINE(hx5102_device, board_ready))
+
+ // RAM
+ MCFG_RAM_ADD(RAM1_TAG)
+ MCFG_RAM_DEFAULT_SIZE("2048")
+ MCFG_RAM_DEFAULT_VALUE(0)
+
+ MCFG_RAM_ADD(RAM2_TAG)
+ MCFG_RAM_DEFAULT_SIZE("2048")
+ MCFG_RAM_DEFAULT_VALUE(0)
+
+MACHINE_CONFIG_END
+
+ROM_START( hx5102 )
+ ROM_REGION( 0x4000, DSR_TAG, 0 )
+ ROM_LOAD( "hx5102_rom1.u25", 0x0000, 0x2000, CRC(40621a77) SHA1(1532f6f23e0104326c21909cb0ec46936242a12a) )
+ ROM_LOAD( "hx5102_rom2.u29", 0x2000, 0x2000, CRC(57c2603b) SHA1(2f1d01378943436f0abd5b20710f6c8c175fde13) )
+ROM_END
+
+const tiny_rom_entry *hx5102_device::device_rom_region() const
+{
+ return ROM_NAME( hx5102 );
}
} } // end namespace bus::hexbus
diff --git a/src/devices/bus/hexbus/hx5102.h b/src/devices/bus/hexbus/hx5102.h
index fdb0c198f8d..d554497bc65 100644
--- a/src/devices/bus/hexbus/hx5102.h
+++ b/src/devices/bus/hexbus/hx5102.h
@@ -18,6 +18,14 @@
#pragma once
#include "hexbus.h"
+#include "cpu/tms9900/tms9995.h"
+#include "machine/upd765.h"
+#include "machine/7474.h"
+#include "machine/74123.h"
+#include "machine/rescap.h"
+#include "machine/ram.h"
+#include "imagedev/floppy.h"
+#include "tp0370.h"
namespace bus { namespace hexbus {
@@ -25,7 +33,76 @@ class hx5102_device : public hexbus_chained_device
{
public:
hx5102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- void hexbus_value_changed(uint8_t data) override;
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ void crumap(address_map &map);
+ void memmap(address_map &map);
+ DECLARE_WRITE8_MEMBER(external_operation);
+ DECLARE_WRITE_LINE_MEMBER( clock_out );
+ DECLARE_WRITE_LINE_MEMBER( board_ready );
+ DECLARE_WRITE_LINE_MEMBER( board_reset );
+ DECLARE_FLOPPY_FORMATS( floppy_formats );
+
+ void device_start() override;
+ void device_reset() override;
+ virtual void hexbus_value_changed(uint8_t data) override;
+
+private:
+ required_device<tms9995_device> m_flopcpu;
+ line_state m_ready_old;
+
+ DECLARE_READ8_MEMBER(read);
+ DECLARE_WRITE8_MEMBER(write);
+
+ DECLARE_WRITE_LINE_MEMBER(fdc_irq_w);
+ DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
+ DECLARE_WRITE_LINE_MEMBER(motor_w);
+ DECLARE_WRITE_LINE_MEMBER(mspeed_w);
+
+ DECLARE_READ8_MEMBER(fdc_read);
+ DECLARE_WRITE8_MEMBER(fdc_write);
+ DECLARE_READ8_MEMBER(ibc_read);
+ DECLARE_WRITE8_MEMBER(ibc_write);
+ DECLARE_WRITE8_MEMBER(hexbus_out);
+ DECLARE_WRITE_LINE_MEMBER(hsklatch_out);
+
+ DECLARE_READ8_MEMBER(cruread);
+ DECLARE_WRITE8_MEMBER(cruwrite);
+
+ // Operate the floppy motors
+ bool m_motor_on;
+ bool m_mspeed_on;
+
+ bool m_pending_int;
+ bool m_pending_drq;
+
+ bool m_dcs;
+
+ bool m_dack;
+ bool m_dacken;
+
+ bool m_wait;
+
+ void update_readyff_input();
+
+ // Link to the attached floppy drive
+ floppy_image_device* m_floppy;
+
+ required_device<ibc_device> m_hexbus_ctrl;
+ required_device<i8272a_device> m_floppy_ctrl;
+ required_device<ttl74123_device> m_motormf;
+ required_device<ttl74123_device> m_speedmf;
+ required_device<ttl7474_device> m_readyff;
+
+ // RAM
+ required_device<ram_device> m_ram1;
+ required_device<ram_device> m_ram2;
+
+ // System ROM
+ uint8_t* m_rom1;
+ uint8_t* m_rom2;
};
} } // end namespace bus::hexbus
diff --git a/src/devices/bus/hexbus/tp0370.cpp b/src/devices/bus/hexbus/tp0370.cpp
new file mode 100644
index 00000000000..6753f387015
--- /dev/null
+++ b/src/devices/bus/hexbus/tp0370.cpp
@@ -0,0 +1,340 @@
+// license:BSD-3-Clause
+// copyright-holders:Michael Zapf
+/*
+
+ Intelligent peripheral bus controller (IBC)
+
+ This is a simple circuit used to connect to the Hexbus infrastructure.
+
+ Two variants are known, with the only difference being the voltage pins
+ and a split of incoming/outgoing lines from/to the Hexbus.
+
+ The 22-pin version is the earlier one, but it is used in the HX5102
+ floppy drive.
+
+ 22-pin 28-pin
+ +-----------+ +-----------+
+ I/O-0 | 1 \/ 22| O-2 I/O-0 | 1 \/ 28| Vcc
+ I/O-1 | 2 21| O-1 I/O-1 | 2 27| O-0
+ I/O-2 | 3 20| O-0 I/O-2 | 3 26| O-1
+ I/O-3 | 4 19| Vdd I/O-3 | 4 25| O-2
+ BAV | 5 18| MS BAVI | 5 24| O-3,R/W
+ HSK | 6 17| D-3 BAV | 6 23| D-3I
+ IRQ | 7 16| D-2 HSKI | 7 22| D-3
+ E | 8 15| D-1 HSK | 8 21| D-2I
+ Vss | 9 14| D-0 IRQ | 9 20| D-2
+ RES |10 13| RS E |10 19| D-1I
+ R/W,O-3 |11 12| CS CS |11 18| D-1
+ +-----------+ RES |12 17| D-0I
+ 1052911 MS |13 16| D-0
+ GND |14 15| RS
+ +-----------+
+ TP0370
+
+ Pins Dir Meaning (MS=0) Dir Meaning (MS=1)
+ -------------------------------------------------------------------
+ I/O-0 i/o Data lines (Host) in Data lines (Host)
+ I/O-1 i/o Data lines (Host) in Data lines (Host)
+ I/O-2 i/o Data lines (Host) in Data lines (Host)
+ I/O-3 i/o Data lines (Host) in Data lines (Host)
+ BAV i/o Bus available (Hexbus) i/o Bus available (Hexbus)
+ HSK i/o Handshake line (Hexbus) i/o Handshake line (Hexbus)
+ IRQ out Interrupt out Interrupt
+ E in See below in Write strobe
+ MS in Mode select=0 in Mode select=1
+ RS in Register select in Register select
+ CS in Chip select in Chip select
+ RES in Reset in Reset
+ O-0 in Option select out Data output (Host)
+ O-1 in Option select out Data output (Host)
+ O-2 in Option select out Data output (Host)
+ R/W in Read/write select out Data output (Host, O-3)
+ D-0 i/o Data lines (Hexbus) i/o Data lines (Hexbus)
+ D-1 i/o Data lines (Hexbus) i/o Data lines (Hexbus)
+ D-2 i/o Data lines (Hexbus) i/o Data lines (Hexbus)
+ D-3 i/o Data lines (Hexbus) i/o Data lines (Hexbus)
+ Vss
+ Vdd
+ Vcc +5V
+ GND 0V
+
+ Options for MS=0
+ O-2 O-1 O-0
+ -----------
+ 0 0 0 TMS7000 mode (E active low)
+ 0 0 1 6500 mode (E active high, using R/W)
+ 0 1 0 8048/8085 mode (WR*->R/W, RD*->E)
+ 1 * * Multiplexed A/D Buses (ALATCH/ALE->RS)
+
+ MS=1 is used for 4-bit MPUs which do not have a bidirectional bus
+ (e.g. TMS1000).
+
+
+ All registers are 4-bit wide
+
+ RS Dir Access
+ ---------------------------------
+ 0 Read Receive data register
+ 0 Write Transmit data register
+ 1 Read Status register
+ 1 Write Control register
+
+ Control register
+ MSB 3 DISABLE: 1->Disable clearing of Inhibit by new BAV
+ 2 INHIBIT: 1->Inhibit latching of HSK and IRQ until new BAV
+ 1 BAV: 1-> Assert BAV* line; 0->Release BAV* when HSK* low
+ LSB 0 HSK: 1-> Assert HSK* line, clear IRQ; 0->Release HSK*
+
+ Special: 1100 -> Hardware reset
+
+
+ Status register
+ MSB 3 \_ 00 = Enable state; 01 = Inhibit/disable state;
+ 2 / 10 = Active IRQ; 11 = Start of message
+ 1 BAV* asserted (1=low)
+ LSB 0 HSK* asserted (1=low)
+
+ Special: 01** after hardware reset
+
+ [1] Texas Instruments Consumer Products Group: Hexbus(TM) specifications,
+ Sep 1983
+*/
+
+#include "emu.h"
+#include "hexbus.h"
+
+// Devices
+#include "tp0370.h"
+
+#define LOG_DATA (1U<<1) // Data transfer
+#define LOG_DETAIL (1U<<2)
+#define LOG_WRITE (1U<<3)
+#define LOG_LINES (1U<<4)
+#define LOG_STATUS (1U<<5)
+#define LOG_MODE (1U<<6)
+
+// Minimum log should be config and warnings
+#define VERBOSE ( LOG_GENERAL )
+
+enum
+{
+ CTRL_DISABLE=0x80,
+ CTRL_INHIBIT=0x40,
+ CTRL_BAV=0x20,
+ CTRL_HSK=0x10
+};
+
+
+#include "logmacro.h"
+
+// Hexbus instance
+DEFINE_DEVICE_TYPE_NS(IBC, bus::hexbus, ibc_device, "ibc", "Intelligent Peripheral Bus Controller")
+
+namespace bus { namespace hexbus {
+
+ibc_device::ibc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, IBC, tag, owner, clock),
+ m_int(*this),
+ m_hexout(*this),
+ m_latch(*this),
+ m_inhibit(false),
+ m_disable(true),
+ m_bavold(true),
+ m_hskold(true),
+ m_int_pending(false),
+ m_incoming_message(false),
+ m_message_started(false),
+ m_data(0),
+ m_transmit(0xff)
+{
+}
+
+/*
+ Reading from host
+*/
+READ8_MEMBER( ibc_device::read )
+{
+ uint8_t status = 0;
+ switch (offset)
+ {
+ case 0:
+ LOGMASKED(LOG_DATA, "Data reg -> %01x\n", m_data&0x0f);
+ return (m_data<<4)&0xf0; // returned in the first 4 bits
+ case 1:
+ if (m_message_started)
+ status |= 0xc0;
+ else
+ {
+ if (m_int_pending)
+ status |= 0x80;
+ else
+ {
+ if (m_disable || m_inhibit)
+ status |= 0x40;
+ }
+ }
+ if (m_bav) status |= 0x20;
+ if (m_hsk) status |= 0x10;
+
+ LOGMASKED(LOG_STATUS, "Status -> %02x\n", status);
+
+ // Reset flag
+ m_message_started = false;
+ return status;
+
+ default:
+ LOG("Unknown read address: %02x\n", offset);
+ break;
+ }
+ return 0;
+}
+
+/*
+ Writing from host
+*/
+WRITE8_MEMBER( ibc_device::write )
+{
+ switch (offset)
+ {
+ case 0:
+ LOGMASKED(LOG_WRITE, "Writing transmit data %02x\n", data);
+ m_transmit = data;
+ break;
+ case 1:
+ set_disable_inhibit((data & CTRL_DISABLE)!=0, (data & CTRL_INHIBIT)!=0);
+ if ((data & CTRL_HSK)!=0 && m_int_pending)
+ {
+ // Reset INT
+ LOGMASKED(LOG_DETAIL, "Reset Interrupt\n");
+ m_int_pending = false;
+ m_int(CLEAR_LINE);
+ }
+ else
+ {
+ set_lines((data & CTRL_BAV)!=0, (data & CTRL_HSK)!=0);
+ }
+
+ break;
+ default:
+ LOG("Unknown write address: %02x\n", offset);
+ break;
+ }
+}
+
+void ibc_device::set_disable_inhibit(bool dis, bool inh)
+{
+ LOGMASKED(LOG_MODE, "Setting disable=%s, inhibit=%s\n", dis? "on" : "off", inh? "on" : "off");
+ m_disable = dis;
+ m_inhibit = inh;
+}
+
+/*
+ Called from the HSK latch or by command.
+*/
+void ibc_device::set_lines(bool bav, bool hsk)
+{
+ LOGMASKED(LOG_LINES, "%s BAV*, %s HSK*\n", bav? "Pull down" : "Release", hsk? "Pull down" : "Release");
+
+ // Assert HSK* (110 0 0111)
+ // Release HSK* (110 1 0111)
+ // Assert BAV* (11010 0 11)
+ // Release BAv* (11010 1 11)
+ uint8_t val = (m_transmit & 0xc0)|((m_transmit & 0x30)>>4);
+ if (!bav) val |= 0x04;
+ if (!hsk) val |= 0x10;
+ if (m_transmit != 0xff) LOGMASKED(LOG_LINES, "Data = %01x\n", m_transmit>>4);
+
+ m_hexout(val);
+ m_transmit=0xff; // TODO: Check this
+}
+
+/*
+ Line state received via the Hexbus
+ +------+------+------+------+------+------+------+------+
+ | ADB3 | ADB2 | - | HSK* | 0 | BAV* | ADB1 | ADB0 |
+ +------+------+------+------+------+------+------+------+
+*/
+void ibc_device::from_hexbus(uint8_t val)
+{
+ uint8_t data = ((val >> 4)&0x0c) | (val & 0x03);
+
+ m_bavold = m_bav;
+ m_hskold = m_hsk;
+
+ m_hsk = ((val & 0x10)==0);
+ m_bav = ((val & 0x04)==0);
+ LOGMASKED(LOG_LINES, "Hexbus -> BAV*=%x, HSK*=%x, HSKold*=%x, DATA=%1x\n", m_bav? 0:1, m_hsk? 0:1, m_hskold? 0:1, data);
+
+ if (m_disable)
+ {
+ // When disabled, do not latch HSK
+ LOGMASKED(LOG_MODE, "Disabled, not latching HSK*\n");
+ }
+ else
+ {
+ // Falling edge of BAV*
+ // Reset inhibit flag
+ if (m_bav && !m_bavold)
+ {
+ LOGMASKED(LOG_LINES, "Bus acquired\n");
+ m_inhibit = false;
+ m_incoming_message = true;
+ }
+
+ // The message may combine a change of BAV* and of HSK*.
+ if (!m_inhibit)
+ {
+ // Falling edge of HSK*
+ if (m_hsk && !m_hskold)
+ {
+ // On this falling edge, the nibble is supposed to be stable,
+ // so keep it
+ m_data = data;
+ if (m_incoming_message && !m_message_started)
+ {
+ // Set flag for new message
+ m_incoming_message = false;
+ m_message_started = true;
+ LOGMASKED(LOG_DETAIL, "New message started\n", data);
+ }
+ else
+ m_message_started = false;
+
+ LOGMASKED(LOG_DETAIL, "Data reg <- %1x\n", data);
+
+ // set the latch
+ m_latch(ASSERT_LINE);
+
+ // and set interrupt
+ m_int_pending = true;
+ m_int(ASSERT_LINE);
+ }
+ }
+ }
+}
+
+/*
+ Called from the hexbus_chained_device.
+*/
+void ibc_device::update_lines(bool bav, bool hsk)
+{
+ LOGMASKED(LOG_LINES, "Actual Hexbus line states: BAV*=%d, HSK*=%d\n", bav? 0:1, hsk? 0:1);
+ m_bav = bav;
+ m_hsk = hsk;
+}
+
+void ibc_device::device_start()
+{
+ m_int.resolve_safe();
+ m_hexout.resolve_safe();
+ m_latch.resolve_safe();
+}
+
+void ibc_device::device_reset()
+{
+ m_inhibit = true;
+ m_disable = true;
+}
+
+} }
+
diff --git a/src/devices/bus/hexbus/tp0370.h b/src/devices/bus/hexbus/tp0370.h
new file mode 100644
index 00000000000..94d32a5b87c
--- /dev/null
+++ b/src/devices/bus/hexbus/tp0370.h
@@ -0,0 +1,85 @@
+// license:BSD-3-Clause
+// copyright-holders:Michael Zapf
+/****************************************************************************
+
+ Intelligent peripheral bus controller (IBC)
+
+ This is a simple circuit used to connect to the Hexbus infrastructure.
+
+ See tp0370.cpp for documentation
+
+ Michael Zapf
+
+*****************************************************************************/
+#ifndef MAME_BUS_HEXBUS_TP0370_H
+#define MAME_BUS_HEXBUS_TP0370_H
+
+#pragma once
+
+namespace bus { namespace hexbus {
+
+class ibc_device : public device_t
+{
+public:
+ ibc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ void device_start() override;
+ void device_reset() override;
+
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+
+ template <class Object> static devcb_base &set_ibc_int_callback(device_t &device, Object &&cb) { return downcast<ibc_device &>(device).m_int.set_callback(std::forward<Object>(cb)); }
+ template <class Object> static devcb_base &set_hexbus_wr_callback(device_t &device, Object &&cb) { return downcast<ibc_device &>(device).m_hexout.set_callback(std::forward<Object>(cb)); }
+ template <class Object> static devcb_base &set_hsklatch_wr_callback(device_t &device, Object &&cb) { return downcast<ibc_device &>(device).m_latch.set_callback(std::forward<Object>(cb)); }
+
+ // INT line
+ devcb_write_line m_int;
+
+ // Outgoing connection to Hexbus
+ devcb_write8 m_hexout;
+
+ // Callback to set the HSK latch
+ devcb_write_line m_latch;
+
+ // Incoming connection
+ void from_hexbus(uint8_t val);
+
+ // Update the lines from the Hexbus
+ void update_lines(bool bav, bool hsk);
+
+private:
+ bool m_inhibit;
+ bool m_disable;
+ bool m_bav;
+ bool m_hsk;
+ bool m_bavold;
+ bool m_hskold;
+ bool m_int_pending;
+ bool m_incoming_message;
+ bool m_message_started;
+
+ uint8_t m_data;
+ uint8_t m_transmit;
+
+ void set_disable_inhibit(bool dis, bool inh);
+ void set_lines(bool bav, bool hsk);
+};
+
+} }
+
+
+/*
+ Links to outside
+*/
+
+#define MCFG_IBC_HEXBUS_OUT_CALLBACK(_write) \
+ devcb = &ibc_device::set_hexbus_wr_callback(*device, DEVCB_##_write);
+
+#define MCFG_IBC_HSKLATCH_CALLBACK(_write) \
+ devcb = &ibc_device::set_hsklatch_wr_callback(*device, DEVCB_##_write);
+
+#define MCFG_IBC_INT_CALLBACK(_write) \
+ devcb = &ibc_device::set_ibc_int_callback(*device, DEVCB_##_write);
+
+DECLARE_DEVICE_TYPE_NS(IBC, bus::hexbus, ibc_device)
+#endif
diff --git a/src/devices/bus/ti99/internal/998board.cpp b/src/devices/bus/ti99/internal/998board.cpp
index 486130d5ac9..9a4fc5cca8e 100644
--- a/src/devices/bus/ti99/internal/998board.cpp
+++ b/src/devices/bus/ti99/internal/998board.cpp
@@ -106,6 +106,26 @@
#include "emu.h"
#include "998board.h"
+#define LOG_DETAIL (1U<<1) // More detail
+#define LOG_CRU (1U<<2) // CRU logging
+#define LOG_ADDRESS (1U<<3) // Address bus
+#define LOG_MEM (1U<<4) // Memory access
+#define LOG_MAP (1U<<5) // Mapper
+#define LOG_READY (1U<<6) // READY line
+#define LOG_CLOCK (1U<<7) // CLKOUT
+#define LOG_MOFETTA (1U<<8) // Mofetta operation
+#define LOG_AMIGO (1U<<9) // Amigo operation
+#define LOG_OSO (1U<<10) // Oso operation
+#define LOG_HEXBUS (1U<<11) // Hexbus operation
+#define LOG_WS (1U<<12) // Wait states
+#define LOG_CPURY (1U<<13) // Combined ready line
+#define LOG_GROM (1U<<14) // GROM operation
+#define LOG_PUNMAP (1U<<15) // Unmapped physical addresss
+
+#define VERBOSE ( LOG_GENERAL )
+
+#include "logmacro.h"
+
DEFINE_DEVICE_TYPE_NS(TI99_MAINBOARD8, bus::ti99::internal, mainboard8_device, "ti998_mainboard", "TI-99/8 Mainboard")
DEFINE_DEVICE_TYPE_NS(TI99_VAQUERRO, bus::ti99::internal, vaquerro_device, "ti998_vaquerro", "TI-99/8 Logical Address Space Decoder")
DEFINE_DEVICE_TYPE_NS(TI99_MOFETTA, bus::ti99::internal, mofetta_device, "ti998_mofetta", "TI-99/8 Physical Address Space Decoder")
@@ -114,22 +134,6 @@ DEFINE_DEVICE_TYPE_NS(TI99_AMIGO, bus::ti99::internal, amigo_device, "ti998_amig
namespace bus { namespace ti99 { namespace internal {
-#define TRACE_CRU 0
-#define TRACE_ADDRESS 0
-#define TRACE_MAP 0
-#define TRACE_OSO 0
-#define TRACE_DECODE 0
-#define TRACE_READY 0
-#define TRACE_MEM 0
-#define TRACE_CLOCK 0
-#define TRACE_DETAIL 0
-#define TRACE_MOFETTA 0
-#define TRACE_AMIGO 0
-#define TRACE_WS 0
-#define TRACE_CPURY 0
-#define TRACE_GROM 0
-#define TRACE_PUNMAP 0
-
enum
{
SGMSEL = 1,
@@ -345,7 +349,7 @@ WRITE_LINE_MEMBER( mainboard8_device::dbin_in )
SETOFFSET_MEMBER( mainboard8_device::setoffset )
{
- if (TRACE_ADDRESS) logerror("set %s %04x\n", (m_dbin_level==ASSERT_LINE)? "R" : "W", offset);
+ LOGMASKED(LOG_ADDRESS, "set %s %04x\n", (m_dbin_level==ASSERT_LINE)? "R" : "W", offset);
// No data is waiting on the data bus
m_pending_write = false;
@@ -407,7 +411,7 @@ WRITE_LINE_MEMBER( mainboard8_device::holda_line )
*/
WRITE_LINE_MEMBER( mainboard8_device::clock_in )
{
- if (TRACE_CLOCK) logerror("CLKOUT = %d\n", state);
+ LOGMASKED(LOG_CLOCK, "CLKOUT = %d\n", state);
// Propagate to Vaquerro; may change GGRDY (trailing edge) and the GROM select lines
m_vaquerro->clock_in((line_state)state);
@@ -469,7 +473,7 @@ WRITE_LINE_MEMBER( mainboard8_device::clock_in )
if (m_A14_set) m_video->register_write(*m_space, 0, m_latched_data);
else m_video->vram_write(*m_space, 0, m_latched_data);
m_pending_write = false;
- if (TRACE_MEM) logerror("Write %04x (video) <- %02x\n", m_logical_address, m_latched_data);
+ LOGMASKED(LOG_MEM, "Write %04x (video) <- %02x\n", m_logical_address, m_latched_data);
cycle_end();
return;
}
@@ -486,14 +490,14 @@ WRITE_LINE_MEMBER( mainboard8_device::clock_in )
{
m_dram->pointer()[m_physical_address & 0xffff] = m_latched_data;
m_pending_write = false;
- if (TRACE_MEM) logerror("Write %04x (phys %06x, DRAM) <- %02x\n", m_logical_address, m_physical_address, m_latched_data);
+ LOGMASKED(LOG_MEM, "Write %04x (phys %06x, DRAM) <- %02x\n", m_logical_address, m_physical_address, m_latched_data);
}
if (m_mofetta->alccs_out()==ASSERT_LINE)
{
m_oso->write(*m_space, m_physical_address>>1, m_latched_data);
m_pending_write = false;
- if (TRACE_MEM) logerror("Write %04x (phys %06x, OSO) <- %02x\n", m_logical_address, m_physical_address, m_latched_data);
+ LOGMASKED(LOG_MEM, "Write %04x (phys %06x, OSO) <- %02x\n", m_logical_address, m_physical_address, m_latched_data);
}
if (m_mofetta->cmas_out()==ASSERT_LINE)
@@ -501,7 +505,7 @@ WRITE_LINE_MEMBER( mainboard8_device::clock_in )
m_gromport->romgq_line(ASSERT_LINE);
m_gromport->write(*m_space, m_physical_address & 0x3fff, m_latched_data);
m_pending_write = false;
- if (TRACE_MEM) logerror("Write %04x (phys %06x, cartridge) <- %02x\n", m_logical_address, m_physical_address, m_latched_data);
+ LOGMASKED(LOG_MEM, "Write %04x (phys %06x, cartridge) <- %02x\n", m_logical_address, m_physical_address, m_latched_data);
}
else
{
@@ -512,7 +516,7 @@ WRITE_LINE_MEMBER( mainboard8_device::clock_in )
{
m_ioport->write(*m_space, m_physical_address, m_latched_data);
m_pending_write = false;
- if (TRACE_MEM) logerror("Write %04x (phys %06x, PEB) <- %02x\n", m_logical_address, m_physical_address, m_latched_data);
+ LOGMASKED(LOG_MEM, "Write %04x (phys %06x, PEB) <- %02x\n", m_logical_address, m_physical_address, m_latched_data);
}
}
@@ -553,7 +557,7 @@ void mainboard8_device::select_groms()
for (int i=0; i < 3; i++)
m_p3grom[i]->set_lines(*m_space, lines, select & P3GSEL);
- // Write to the cartridge port. The GROMs on cartridges are accesses as system GROMs
+ // Write to the cartridge port. The GROMs on cartridges are accessed as system GROMs
if (select & SGMSEL) m_gromport->romgq_line(CLEAR_LINE);
m_gromport->set_gromlines(*m_space, lines, select & SGMSEL);
}
@@ -569,7 +573,7 @@ void mainboard8_device::select_groms()
{
m_sgrom[i]->write(*m_space, 0, m_latched_data);
}
- if (TRACE_MEM) logerror("Write GS <- %02x\n", m_latched_data);
+ LOGMASKED(LOG_MEM, "Write GS <- %02x\n", m_latched_data);
m_gromport->write(*m_space, 0, m_latched_data);
break;
@@ -578,7 +582,7 @@ void mainboard8_device::select_groms()
{
m_tsgrom[i]->write(*m_space, 0, m_latched_data);
}
- if (TRACE_MEM) logerror("Write GT <- %02x\n", m_latched_data);
+ LOGMASKED(LOG_MEM, "Write GT <- %02x\n", m_latched_data);
break;
case P8GSEL:
@@ -586,7 +590,7 @@ void mainboard8_device::select_groms()
{
m_p8grom[i]->write(*m_space, 0, m_latched_data);
}
- if (TRACE_MEM) logerror("Write G8 <- %02x\n", m_latched_data);
+ LOGMASKED(LOG_MEM, "Write G8 <- %02x\n", m_latched_data);
break;
case P3GSEL:
@@ -594,7 +598,7 @@ void mainboard8_device::select_groms()
{
m_p3grom[i]->write(*m_space, 0, m_latched_data);
}
- if (TRACE_MEM) logerror("Write G3 <- %02x\n", m_latched_data);
+ LOGMASKED(LOG_MEM, "Write G3 <- %02x\n", m_latched_data);
break;
default:
@@ -608,7 +612,7 @@ void mainboard8_device::set_paddress(int address)
{
// Keep this value as the current address
m_physical_address = (m_physical_address << 16) | address;
- if (TRACE_DETAIL) logerror("Setting physical address %06x\n", m_physical_address);
+ LOGMASKED(LOG_DETAIL, "Setting physical address %06x\n", m_physical_address);
m_mofetta->set_address(*m_space, address, m_dbin_level);
m_ioport->setaddress_dbin(*m_space, address, m_dbin_level);
@@ -616,7 +620,7 @@ void mainboard8_device::set_paddress(int address)
WRITE_LINE_MEMBER( mainboard8_device::msast_in )
{
- if (TRACE_DETAIL) logerror("msast = %d\n", state);
+ LOGMASKED(LOG_DETAIL, "msast = %d\n", state);
// Start physical space cycle on the trailing edge
if (state==CLEAR_LINE)
@@ -692,7 +696,7 @@ READ8_MEMBER( mainboard8_device::read )
m_sgrom[i]->readz(space, 0, &value);
}
m_gromport->readz(space, 0, &value);
- if (TRACE_GROM && !m_A14_set) logerror("GS>%04x\n", m_sgrom[0]->debug_get_address()-1);
+ if (!m_A14_set) LOGMASKED(LOG_GROM, "GS>%04x\n", m_sgrom[0]->debug_get_address()-1);
what = "system GROM";
goto readdone;
@@ -702,7 +706,7 @@ READ8_MEMBER( mainboard8_device::read )
{
m_tsgrom[i]->readz(space, 0, &value);
}
- if (TRACE_GROM && !m_A14_set) logerror("GT>%04x\n", m_tsgrom[0]->debug_get_address()-1);
+ if (!m_A14_set) LOGMASKED(LOG_GROM, "GT>%04x\n", m_tsgrom[0]->debug_get_address()-1);
what = "TTS GROM";
goto readdone;
@@ -712,7 +716,7 @@ READ8_MEMBER( mainboard8_device::read )
{
m_p8grom[i]->readz(space, 0, &value);
}
- if (TRACE_GROM && !m_A14_set) logerror("G8>%04x\n", m_p8grom[0]->debug_get_address()-1);
+ if (!m_A14_set) LOGMASKED(LOG_GROM, "G8>%04x\n", m_p8grom[0]->debug_get_address()-1);
what = "P8 GROM";
goto readdone;
@@ -722,7 +726,7 @@ READ8_MEMBER( mainboard8_device::read )
{
m_p3grom[i]->readz(space, 0, &value);
}
- if (TRACE_GROM && !m_A14_set) logerror("G3>%04x\n", m_p3grom[0]->debug_get_address()-1);
+ if (!m_A14_set) LOGMASKED(LOG_GROM, "G3>%04x\n", m_p3grom[0]->debug_get_address()-1);
what = "P3 GROM";
goto readdone;
default:
@@ -758,7 +762,7 @@ READ8_MEMBER( mainboard8_device::read )
if (m_mofetta->rom1al_out()==ASSERT_LINE) address |= 0x2000;
value = m_rom1[address];
- if (TRACE_MEM) logerror("Read %04x (ROM1@%04x) -> %02x\n", m_logical_address, address, value);
+ LOGMASKED(LOG_MEM, "Read %04x (ROM1@%04x) -> %02x\n", m_logical_address, address, value);
cycle_end();
return value;
}
@@ -792,7 +796,7 @@ READ8_MEMBER( mainboard8_device::read )
goto readdonephys;
}
- if (TRACE_PUNMAP) logerror("Read %04x (phys %06x, unmapped) ignored\n", m_logical_address, m_physical_address);
+ LOGMASKED(LOG_PUNMAP, "Read %04x (phys %06x, unmapped) ignored\n", m_logical_address, m_physical_address);
// Memory cycle ends
cycle_end();
@@ -801,12 +805,12 @@ READ8_MEMBER( mainboard8_device::read )
readdone:
- if (TRACE_MEM) logerror("Read %04x (%s) -> %02x\n", m_logical_address, what, value);
+ LOGMASKED(LOG_MEM, "Read %04x (%s) -> %02x\n", m_logical_address, what, value);
cycle_end();
return value;
readdonephys:
- if (TRACE_MEM) logerror("Read %04x (phys %06x, %s) -> %02x\n", m_logical_address, m_physical_address, what, value);
+ LOGMASKED(LOG_MEM, "Read %04x (phys %06x, %s) -> %02x\n", m_logical_address, m_physical_address, what, value);
cycle_end();
return value;
}
@@ -841,7 +845,7 @@ WRITE8_MEMBER( mainboard8_device::write )
// GROMs and video must wait to be selected
if (m_amigo->mapper_accessed())
{
- if (TRACE_MEM) logerror("Write %04x (mapper) <- %02x\n", m_logical_address, data);
+ LOGMASKED(LOG_MEM, "Write %04x (mapper) <- %02x\n", m_logical_address, data);
m_amigo->write(space, 0, data);
m_pending_write = false;
}
@@ -850,7 +854,7 @@ WRITE8_MEMBER( mainboard8_device::write )
// sound address lies within the SRAM area
if (m_vaquerro->sccs_out()==ASSERT_LINE)
{
- if (TRACE_MEM) logerror("Write %04x (sound) <- %02x\n", m_logical_address, data);
+ LOGMASKED(LOG_MEM, "Write %04x (sound) <- %02x\n", m_logical_address, data);
m_sound->write(space, 0, data); // Sound chip will lower READY after this access
m_pending_write = false;
}
@@ -859,7 +863,7 @@ WRITE8_MEMBER( mainboard8_device::write )
// SRAM
if (m_amigo->sramcs_out()==ASSERT_LINE)
{
- if (TRACE_MEM) logerror("Write %04x (SRAM) <- %02x\n", m_logical_address, data);
+ LOGMASKED(LOG_MEM, "Write %04x (SRAM) <- %02x\n", m_logical_address, data);
m_sram->pointer()[m_logical_address & 0x07ff] = data;
m_pending_write = false;
}
@@ -868,7 +872,7 @@ WRITE8_MEMBER( mainboard8_device::write )
// Speech
if (m_vaquerro->spwt_out()==ASSERT_LINE)
{
- if (TRACE_MEM) logerror("Write %04x (speech) <- %02x\n", m_logical_address, data);
+ LOGMASKED(LOG_MEM, "Write %04x (speech) <- %02x\n", m_logical_address, data);
m_speech->data_w(space, 0, data);
m_pending_write = false;
}
@@ -884,7 +888,7 @@ WRITE8_MEMBER( mainboard8_device::write )
*/
WRITE_LINE_MEMBER( mainboard8_device::crus_in )
{
- if (TRACE_CRU) logerror("%s CRUS\n", (state==1)? "Assert" : "Clear");
+ LOGMASKED(LOG_CRU, "%s CRUS\n", (state==1)? "Assert" : "Clear");
m_vaquerro->crus_in(state);
m_amigo->crus_in(state);
m_crus_debug = (line_state)state;
@@ -896,7 +900,7 @@ WRITE_LINE_MEMBER( mainboard8_device::crus_in )
*/
WRITE_LINE_MEMBER( mainboard8_device::ptgen_in )
{
- if (TRACE_CRU) logerror("%s PTGEN*\n", (state==0)? "Assert" : "Clear");
+ LOGMASKED(LOG_CRU, "%s PTGEN*\n", (state==0)? "Assert" : "Clear");
m_vaquerro->crusgl_in((state==0)? ASSERT_LINE : CLEAR_LINE);
}
@@ -1124,7 +1128,7 @@ SETADDRESS_DBIN_MEMBER( vaquerro_device::set_address )
// =================== TI (compatibility) mode ======================
if (m_crus == ASSERT_LINE)
{
- if (TRACE_DETAIL) logerror("Compatibility mode\n");
+ LOGMASKED(LOG_DETAIL, "Compatibility mode\n");
// SPRD (Speech read)
m_sprd = ((offbase==0x9000) && reading);
@@ -1147,7 +1151,7 @@ SETADDRESS_DBIN_MEMBER( vaquerro_device::set_address )
// ====================== Native mode ======================
else
{
- if (TRACE_DETAIL) logerror("Native mode\n");
+ LOGMASKED(LOG_DETAIL, "Native mode\n");
// SPRD (Speech read)
m_sprd = ((offbase==0xf820) && reading);
@@ -1176,7 +1180,7 @@ SETADDRESS_DBIN_MEMBER( vaquerro_device::set_address )
m_lasreq = (m_sprd || m_spwt || m_sccs || m_sromcs || m_grom_or_video);
- if (TRACE_DETAIL) logerror("sgfap=%d tsgfap=%d p8gfap=%d p3gfap=%d vfap=%d\n", sgfap, tsgfap, p8gfap, p3gfap, vfap);
+ LOGMASKED(LOG_DETAIL, "sgfap=%d tsgfap=%d p8gfap=%d p3gfap=%d vfap=%d\n", sgfap, tsgfap, p8gfap, p3gfap, vfap);
// Pass the selection to the wait state generators
// and pick up the current select line states
@@ -1195,7 +1199,7 @@ SETADDRESS_DBIN_MEMBER( vaquerro_device::set_address )
{
// We don't see the current selection now; only with next clock pulse.
m_mainboard->ggrdy_in(m_sry);
- if (TRACE_READY) logerror("GGRDY = %d\n", m_sry);
+ LOGMASKED(LOG_READY, "GGRDY = %d\n", m_sry);
}
}
@@ -1227,25 +1231,25 @@ READ_LINE_MEMBER( vaquerro_device::lascsq_out )
*/
WRITE_LINE_MEMBER( vaquerro_device::sgmry )
{
- if (TRACE_READY) logerror("Incoming SGMRY = %d\n", state);
+ LOGMASKED(LOG_READY, "Incoming SGMRY = %d\n", state);
m_sgmws.ready_in((line_state)state);
}
WRITE_LINE_MEMBER( vaquerro_device::tsgry )
{
- if (TRACE_READY) logerror("Incoming TSGRY = %d\n", state);
+ LOGMASKED(LOG_READY, "Incoming TSGRY = %d\n", state);
m_tsgws.ready_in((line_state)state);
}
WRITE_LINE_MEMBER( vaquerro_device::p8gry )
{
- if (TRACE_READY) logerror("Incoming 8GRY = %d\n", state);
+ LOGMASKED(LOG_READY, "Incoming 8GRY = %d\n", state);
m_p8gws.ready_in((line_state)state);
}
WRITE_LINE_MEMBER( vaquerro_device::p3gry )
{
- if (TRACE_READY) logerror("Incoming P3GRY = %d\n", state);
+ LOGMASKED(LOG_READY, "Incoming P3GRY = %d\n", state);
m_p3gws.ready_in((line_state)state);
}
@@ -1254,7 +1258,7 @@ WRITE_LINE_MEMBER( vaquerro_device::p3gry )
*/
READ_LINE_MEMBER( vaquerro_device::ggrdy_out )
{
- if (TRACE_READY) logerror("GGRDY out = %d\n", m_ggrdy);
+ LOGMASKED(LOG_READY, "GGRDY out = %d\n", m_ggrdy);
return m_ggrdy;
}
@@ -1335,7 +1339,7 @@ WRITE_LINE_MEMBER( vaquerro_device::clock_in )
if (level==CLEAR_LINE)
{
m_sry = m_sgmws.ready_out() || m_tsgws.ready_out() || m_p8gws.ready_out() || m_p3gws.ready_out() || m_vidws.ready_out();
- if (TRACE_WS) logerror("ready_out = (%d, %d, %d, %d, %d)\n", m_sgmws.ready_out(), m_tsgws.ready_out(), m_p8gws.ready_out(), m_p3gws.ready_out(),m_vidws.ready_out());
+ LOGMASKED(LOG_WS, "ready_out = (%d, %d, %d, %d, %d)\n", m_sgmws.ready_out(), m_tsgws.ready_out(), m_p8gws.ready_out(), m_p3gws.ready_out(),m_vidws.ready_out());
}
// If the output gate is closed, propagate ASSERT_LINE (pulled up)
@@ -1345,7 +1349,6 @@ WRITE_LINE_MEMBER( vaquerro_device::clock_in )
void vaquerro_device::device_start()
{
- logerror("Starting\n");
m_mainboard = downcast<mainboard8_device*>(owner());
m_sgmws.init(SGMSEL);
m_tsgws.init(TSGSEL);
@@ -1558,13 +1561,13 @@ SETADDRESS_DBIN_MEMBER( mofetta_device::set_address )
if (!m_gotfirstword)
{
// Store the first word and wait for clearing of MSAST
- if (TRACE_MOFETTA) logerror("Got the upper word of the address: %04x\n", offset);
+ LOGMASKED(LOG_MOFETTA, "Got the upper word of the address: %04x\n", offset);
m_address_latch = offset;
}
else
{
// Second part - now decode the address
- if (TRACE_MOFETTA) logerror("Got the lower word of the address: %04x\n", offset);
+ LOGMASKED(LOG_MOFETTA, "Got the lower word of the address: %04x\n", offset);
bool acs, tcs, rcs, acsx;
bool reading = (state==ASSERT_LINE);
@@ -1685,14 +1688,14 @@ WRITE8_MEMBER(mofetta_device::cruwrite)
{
// SWRST (Software reset)
// Value seems to be irrelevant
- if (TRACE_CRU) logerror("Doing a software reset by SBO 2702\n");
+ LOGMASKED(LOG_CRU, "Doing a software reset by SBO 2702\n");
m_mainboard->reset_console(ASSERT_LINE);
m_mainboard->reset_console(CLEAR_LINE);
}
else
{
m_txspg = (data!=0); // CRU>2700
- if (TRACE_CRU) logerror("Turning %s CRU>2700\n", m_txspg? "on" : "off");
+ LOGMASKED(LOG_CRU, "Turning %s CRU>2700\n", m_txspg? "on" : "off");
}
}
else
@@ -1700,7 +1703,7 @@ WRITE8_MEMBER(mofetta_device::cruwrite)
if ((offset & 0xff00)==0x1700)
{
m_alcpg = (data!=0); // CRU>1700
- if (TRACE_CRU) logerror("Turning %s CRU>1700\n", m_alcpg? "on" : "off");
+ LOGMASKED(LOG_CRU, "Turning %s CRU>1700\n", m_alcpg? "on" : "off");
}
}
}
@@ -1740,7 +1743,6 @@ WRITE_LINE_MEMBER( mofetta_device::skdrcs_in )
void mofetta_device::device_start()
{
- logerror("Starting\n");
m_mainboard = downcast<mainboard8_device*>(owner());
save_item(NAME(m_pmemen));
@@ -1873,13 +1875,13 @@ int amigo_device::get_physical_address_debug(offs_t offset)
*/
WRITE_LINE_MEMBER( amigo_device::srdy_in )
{
- if (TRACE_READY) logerror("Incoming SRDY = %d\n", state);
+ LOGMASKED(LOG_READY, "Incoming SRDY = %d\n", state);
m_srdy = (line_state)state;
// If the access is going to logical space, pass through the READY line
if (m_logical_space)
{
- if (TRACE_CPURY) logerror("Setting CPURY = %d (SRDY)\n", m_ready_out);
+ LOGMASKED(LOG_CPURY, "Setting CPURY = %d (SRDY)\n", m_ready_out);
m_ready_out = m_srdy;
}
}
@@ -1958,7 +1960,7 @@ SETOFFSET_MEMBER( amigo_device::set_address )
// Is the address not in the logical address space?
if (!m_logical_space)
{
- if (TRACE_AMIGO) logerror("Amigo decoding; %04x is a physical address.\n", offset);
+ LOGMASKED(LOG_AMIGO, "Amigo decoding; %04x is a physical address.\n", offset);
// Build the physical address
// The first three bits are the protection bits (Write, Execute, Read)
// Theoretically, the addition of the logical address could mess up those
@@ -1979,7 +1981,7 @@ SETOFFSET_MEMBER( amigo_device::set_address )
// Pull down READY
m_ready_out = CLEAR_LINE;
- if (TRACE_CPURY) logerror("Setting CPURY = %d (PAS)\n", m_ready_out);
+ LOGMASKED(LOG_CPURY, "Setting CPURY = %d (PAS)\n", m_ready_out);
}
else
{
@@ -1987,7 +1989,7 @@ SETOFFSET_MEMBER( amigo_device::set_address )
m_dram_accessed = false;
m_amstate = IDLE;
m_ready_out = m_srdy;
- if (TRACE_CPURY) logerror("Setting CPURY = %d (LAS)\n", m_ready_out);
+ LOGMASKED(LOG_CPURY, "Setting CPURY = %d (LAS)\n", m_ready_out);
}
}
@@ -2066,7 +2068,7 @@ void amigo_device::mapper_load()
if ((m_sram_address & 0x03)==0)
{
- if (TRACE_MAP) logerror("Loaded basereg %02d = %08x\n", m_basereg, m_mapvalue);
+ LOGMASKED(LOG_MAP, "Loaded basereg %02d = %08x\n", m_basereg, m_mapvalue);
m_base_register[m_basereg++] = m_mapvalue;
}
if (m_basereg == 16)
@@ -2089,7 +2091,7 @@ void amigo_device::mapper_save()
else
{
m_mapvalue = m_base_register[m_basereg];
- if (TRACE_MAP) logerror("Saving basereg %02d = %08x\n", m_basereg, m_mapvalue);
+ LOGMASKED(LOG_MAP, "Saving basereg %02d = %08x\n", m_basereg, m_mapvalue);
m_basereg++;
}
}
@@ -2131,13 +2133,12 @@ void amigo_device::mapper_access_debug(int data)
WRITE_LINE_MEMBER( amigo_device::holda_in )
{
- if (TRACE_MAP) logerror("HOLD acknowledged = %d\n", state);
+ LOGMASKED(LOG_MAP, "HOLD acknowledged = %d\n", state);
m_hold_acknowledged = (state==ASSERT_LINE);
}
void amigo_device::device_start()
{
- logerror("Starting\n");
m_mainboard = downcast<mainboard8_device*>(owner());
save_item(NAME(m_memen));
@@ -2210,67 +2211,28 @@ void amigo_device::device_reset()
| 8 | 7 | 6 | 5 | 8 = ADB3; 7 = ADB2; 6 = nc; 5 = HSK*
+---+---+---+---+
- TODO: This is just a preliminary implementation to satisfy the operating
- system. When completed we can hopefully emulate a Hexbus floppy and
- use it in Extended Basic II which refuses to work with the PEB cards.
- The Hexbus should then be designed as a slot device.
-
****************************************************************************/
-/* Status register bits */
-enum
-{
- HSKWT = 0x80,
- HSKRD = 0x40,
- BAVIAS = 0x20,
- BAVAIS = 0x10,
- SBAV = 0x08,
- WBUSY = 0x04,
- RBUSY = 0x02,
- SHSK = 0x01
-};
-
-/* Control register bits */
-enum
-{
- WIEN = 0x80,
- RIEN = 0x40,
- BAVIAEN = 0x20,
- BAVAIEN = 0x10,
- BAVC = 0x08,
- WEN = 0x04,
- REN = 0x02,
- CR7 = 0x01
-};
-
-/* Line */
-enum
-{
- LINE_HSK = 0x10,
- LINE_BAV = 0x04,
- LINE_BIT32 = 0xc0,
- LINE_BIT10 = 0x03
-};
-
oso_device::oso_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
bus::hexbus::hexbus_chained_device(mconfig, TI99_OSO, tag, owner, clock),
m_int(*this),
m_data(0),
m_status(0xff),
m_control(0),
- m_xmit(0), m_lasthxvalue(0x01),
- m_bav(false), m_sbav(false), m_sbavold(false), m_bavhold(false),
- m_hsk(false), m_shsk(false), m_shskold(false), m_hskhold(false),
+ m_xmit(0),
+ m_bav(false), m_sbav(false), m_sbavold(false), m_bavold(false),
+ m_hsk(false), m_hsklocal(false), m_shsk(false), m_hskold(false),
m_wq1(false), m_wq1old(false), m_wq2(false), m_wq2old(false),
- m_wnp(false), m_wbusyold(false), m_sendbyte(false),
+ m_wnp(false), m_wbusy(false), m_wbusyold(false), m_sendbyte(false),
m_wrset(false), m_counting(false), m_clkcount(0),
m_rq1(false), m_rq2(false), m_rq2old(false),
m_rnib(false), m_rnibcold(false),
m_rdset(false), m_rdsetold(false),
m_msns(false), m_lsns(false),
- m_rhsus(false)
+ m_rhsus(false), m_rbusy(false),
+ m_phi3(false),
+ m_oldvalue(0xff)
{
- (void)m_shskold;
m_hexbus_inbound = nullptr;
m_hexbus_outbound = nullptr;
}
@@ -2283,8 +2245,8 @@ READ8_MEMBER( oso_device::read )
{
case 0:
// read 5FF8: read data register
- if (TRACE_OSO) logerror("Read data register = %02x\n", value);
value = m_data;
+ LOGMASKED(LOG_OSO, "Read data register = %02x\n", value);
// Release the handshake
m_rhsus = false;
break;
@@ -2292,7 +2254,7 @@ READ8_MEMBER( oso_device::read )
// read 5FFA: read status register
value = m_status;
clear_int_status();
- if (TRACE_OSO) logerror("Read status %02x (HSKWT=%d,HSKRD=%d,BAVIAS=%d,BAVAIS=%d,SBAV=%d,WBUSY=%d,RBUSY=%d,SHSK=%d)\n", value,
+ LOGMASKED(LOG_OSO, "Read status %02x (HSKWT=%d,HSKRD=%d,BAVIAS=%d,BAVAIS=%d,SBAV=%d,WBUSY=%d,RBUSY=%d,SHSK=%d)\n", value,
(value&HSKWT)? 1:0, (value&HSKRD)? 1:0, (value&BAVIAS)? 1:0,
(value&BAVAIS)? 1:0, (value&SBAV)? 1:0, (value&WBUSY)? 1:0,
(value&RBUSY)? 1:0,(value&SHSK)? 1:0);
@@ -2300,12 +2262,12 @@ READ8_MEMBER( oso_device::read )
case 2:
// read 5FFC: read control register
value = m_control;
- if (TRACE_OSO) logerror("Read control register = %02x\n", value);
+ LOGMASKED(LOG_OSO, "Read control register = %02x\n", value);
break;
case 3:
// read 5FFE: read transmit register
value = m_xmit;
- if (TRACE_OSO) logerror("Read transmit register = %02x\n", value);
+ LOGMASKED(LOG_OSO, "Read transmit register = %02x\n", value);
break;
}
return value;
@@ -2318,7 +2280,7 @@ WRITE8_MEMBER( oso_device::write )
{
case 0:
// write 5FF8: write transmit register
- if (TRACE_OSO) logerror("Write transmit register %02x\n", data);
+ LOGMASKED(LOG_OSO, "Write transmit register %02x\n", data);
// trigger some actions in the write subsystem
m_sendbyte = true;
@@ -2332,10 +2294,11 @@ WRITE8_MEMBER( oso_device::write )
break;
case 1:
// write 5FFA: write control register
- if (TRACE_OSO) logerror("Write control register %02x (WIEN=%d, RIEN=%d, BAVIAEN=%d, BAVAIEN=%d, BAVC=%d, WEN=%d, REN=%d)\n",
+ LOGMASKED(LOG_OSO, "Write control register %02x (WIEN=%d, RIEN=%d, BAVIAEN=%d, BAVAIEN=%d, BAVC=%d, WEN=%d, REN=%d)\n",
data, (data & WIEN)? 1:0, (data & RIEN)? 1:0, (data&BAVIAEN)? 1:0, (data&BAVAIEN)? 1:0,
(data & BAVC)? 1:0, (data & WEN)? 1:0, (data & REN)? 1:0);
m_control = data;
+ m_bav = control_bit(BAVC);
// Reset some flipflops in the write/read timing section
if (!control_bit(WEN))
@@ -2346,10 +2309,11 @@ WRITE8_MEMBER( oso_device::write )
{
m_rq1 = m_rq2 = m_rdset = false;
}
+ update_hexbus();
break;
default:
// write 5FFC, 5FFE: undefined
- if (TRACE_OSO) logerror("Invalid write on %04x: %02x\n", (offset<<1) | 0x5ff0, data);
+ LOGMASKED(LOG_OSO, "Invalid write on %04x: %02x\n", (offset<<1) | 0x5ff0, data);
break;
}
}
@@ -2360,35 +2324,28 @@ void oso_device::clear_int_status()
m_int(CLEAR_LINE);
}
-void oso_device::hexbus_value_changed(uint8_t data)
-{
- if (TRACE_OSO) logerror("Hexbus value changed to %02x\n", data);
-
- m_bav = ((data & LINE_BAV)==0) | control_bit(BAVC);
-
- m_hsk = (data & LINE_HSK)==0;
- int nibble = ((data & LINE_BIT32)>>4) | (data & LINE_BIT10);
- if (m_msns)
- m_data = (m_data & 0x0f) | (nibble<<4);
- if (m_lsns)
- m_data = (m_data & 0xf0) | nibble;
-}
-
/*
Phi3 incoming clock pulse
*/
WRITE_LINE_MEMBER( oso_device::clock_in )
{
+ m_phi3 = state;
if (state==ASSERT_LINE)
{
// Control lines SHSK, SBAV
// When BAV/HSK is 0/1 for two rising edges of Phi3*, SBAV/SHSK goes to
// 0/1 at the following falling edge of Phi3*.
// Page 5
- m_sbav = m_bavhold && m_bav; // could mean "stable BAV"
- m_bavhold = m_bav;
- m_shsk = m_hskhold && m_hsk;
- m_hskhold = m_hsk;
+
+ // In reality, the HSK and BAV signals are checked for their minimum
+ // width (by waiting for two cycles of constant level), but due to
+ // problems with synchronous execution between different parts in the
+ // emulation, we accept the level change immediately.
+
+ m_sbav = m_bav; // could mean "stable BAV"
+ // if (control_bit(WEN)) logerror("hskhold=%d, hsk=%d\n", m_hskhold? 1:0, m_hsk? 1:0);
+
+ m_shsk = m_hsk;
set_status(SHSK, m_shsk);
set_status(SBAV, m_sbav);
@@ -2412,7 +2369,9 @@ WRITE_LINE_MEMBER( oso_device::clock_in )
if (control_bit(WEN)) // Nothing happens without WEN
{
- if (TRACE_OSO) if (!m_wrset && m_sendbyte) logerror("Starting write process\n");
+ if (!m_wrset && m_sendbyte)
+ LOGMASKED(LOG_OSO, "Starting write process\n");
+
// Page 3: Write timing
// Note: First pass counts to 30, second to 31
bool cnt30 = ((m_clkcount & 0x1e) == 30);
@@ -2420,7 +2379,7 @@ WRITE_LINE_MEMBER( oso_device::clock_in )
|| (cnt30 && !m_wq2 && m_wq1) || (m_shsk && m_wq2 && m_wq1);
bool jwq1 = cont && m_wq2;
- bool kwq1 = !((cont && !m_wq2) || (!cont && m_wq2 && m_wnp));
+ bool kwq1 = !(cont && !m_wq2) && !(!cont && m_wq2 && m_wnp);
bool jwq2 = cont;
bool kwq2 = !(m_wq1 && !cont);
@@ -2431,17 +2390,26 @@ WRITE_LINE_MEMBER( oso_device::clock_in )
if (m_wq1 == true)
m_sendbyte = false;
- // logerror("sendbyte=%d, wq1=%d, wq2=%d, jwq1=%d, kwq1=%d, jwq2=%d, kwq2=%d, shsk=%d\n", m_sendbyte, m_wq1, m_wq2, jwq1, kwq1, jwq2, kwq2, m_shsk);
+ // logerror("sendbyte=%d, wq1=%d, wq2=%d, jwq1=%d, kwq1=%d, jwq2=%d, kwq2=%d\n", m_sendbyte, m_wq1, m_wq2, jwq1, kwq1, jwq2, kwq2);
+ // logerror("sendbyte=%d, wq1=%d, wq2=%d, m_shsk=%d\n", m_sendbyte, m_wq1, m_wq2, m_shsk);
// WBUSY is asserted on byte load, during phase 1, and phase 2.
- bool wbusy = m_sendbyte || m_wq1 || m_wq2;
+ m_wbusy = m_sendbyte || m_wq1 || m_wq2;
// Set status bits and raise interrupt (p. 4)
- set_status(WBUSY, wbusy);
+ set_status(WBUSY, m_wbusy);
// Raising edge of wbusy*
- if (m_wbusyold == true && wbusy == false)
+ // This is true when the two nibbles of the byte have been written and acknowledged
+ // by the receiver which has released HSK*
+ if (m_wbusyold == true && m_wbusy == false)
+ {
+ LOGMASKED(LOG_HEXBUS, "Setting HSKWT to true\n");
set_status(HSKWT, true);
- m_wbusyold = wbusy;
+ // Problem: By turning off the WBUSY signal, the transmit register goes inactive
+ // so the peripheral setting dominates again. However, the peripheral sender will not
+ // send its value again.
+ }
+ m_wbusyold = m_wbusy;
// Operate flipflops
// Write phases
@@ -2487,27 +2455,26 @@ WRITE_LINE_MEMBER( oso_device::clock_in )
if (control_bit(REN))
{
- bool rbusy = m_rq1 || m_rq2;
- set_status(RBUSY, rbusy);
-
- // Flipflop resets
- if (!rbusy) m_rnib = false;
- if (m_rq2) m_rdset = false;
-
- bool rdsetin = !control_bit(WBUSY) && m_sbav && m_shsk;
+ bool rdsetin = !status_bit(WBUSY) && m_sbav && m_shsk;
bool next = (m_rdset && !m_rq2) || (m_shsk && m_rq2);
bool drq1 = (next && m_rq2) || (m_rq2 && m_rq1 && !m_rnib);
bool jrq2 = next && !m_rq1;
- bool krq2 = m_rq1 && !m_rnib;
- m_msns = m_rnib && !m_rq1 && m_rq2;
- m_lsns = !m_rnib && !m_rq1 && m_rq2;
+ bool krq2 = !m_rq1 || m_rnib;
bool rnibc = m_rq1;
+ //logerror("n=%d,d1=%d,j2=%d,k2=%d,rn=%d\n", next, drq1, jrq2, krq2, m_rnib);
// Next state
- if (!m_rdsetold && rdsetin) m_rdset = true; // raising edge
+ if (!m_rdsetold && rdsetin)
+ {
+ m_rdset = true; // raising edge
+ }
m_rdsetold = rdsetin;
+ // logerror("rdset=%d, rdsetin=%d\n", m_rdset, rdsetin);
+
+ // Set the RQ1 flipflop
m_rq1 = drq1;
+ // Set the RQ2 flipflop
if (jrq2)
{
if (!krq2) m_rq2 = !m_rq2;
@@ -2516,12 +2483,47 @@ WRITE_LINE_MEMBER( oso_device::clock_in )
else
if (!krq2) m_rq2 = false;
- if (m_rnibcold == false && rnibc == true) m_rnib = !m_rnib; // raising edge
+ if (m_rq2) m_rdset = false;
+
+ // Set the rnib flipflop. This is in sequence to the RQ1 flipflop.
+ rnibc = m_rq1;
+ if (m_rnibcold == false && rnibc == true) // raising edge
+ m_rnib = !m_rnib;
+
m_rnibcold = rnibc;
+ // Debugging only
+ // next = (m_rdset && !m_rq2) || (m_shsk && m_rq2);
+ // drq1 = (next && m_rq2) || (m_rq2 && m_rq1 && !m_rnib);
+ // jrq2 = next && !m_rq1;
+ // krq2 = !m_rq1 || m_rnib;
+ // logerror("r=%d,n=%d,rn=%d,d1=%d,j2=%d,k2=%d,q1=%d,q2=%d\n", m_rdset, next, m_rnib, drq1, jrq2, krq2, m_rq1, m_rq2);
+
+ // Set RBUSY
+ bool rbusy = m_rq1 || m_rq2;
+
+ if (rbusy != m_rbusy)
+ LOGMASKED(LOG_HEXBUS, "RBUSY=%d\n",rbusy);
+
+ m_rbusy = rbusy;
+ set_status(RBUSY, rbusy);
+
+ // Flipflop resets
+ if (!rbusy) m_rnib = false;
+
+ bool msns = m_rnib && !m_rq1 && m_rq2;
+ bool lsns = !m_rnib && !m_rq1 && m_rq2;
+
+ // if (msns != m_msns) LOGMASKED(LOG_HEXBUS, "MSNS=%d\n", msns);
+ // if (lsns != m_lsns) LOGMASKED(LOG_HEXBUS, "LSNS=%d\n", lsns);
+
+ m_lsns = lsns;
+ m_msns = msns;
+
// Raising edge of RQ2*
if (m_rq2old == true && m_rq2 == false)
{
+ LOGMASKED(LOG_HEXBUS, "Byte available for reading\n");
set_status(HSKRD, true);
m_rhsus = true; // byte is available for reading
}
@@ -2534,11 +2536,14 @@ WRITE_LINE_MEMBER( oso_device::clock_in )
// Handshake control
// Set HSK (Page 6, RHSUS*)
- bool hskwrite = !m_wq1 && m_wq2;
+ // This is very likely an error in the schematics. It does not make
+ // sense, and simulations show that the behaviour would be wrong.
+ // bool hskwrite = !m_wq1 && m_wq2;
+ bool hskwrite = (m_wq1 != m_wq2);
// We can simplify this to a single flag because the CPU read operation
// is atomic here (starts and immediately terminates)
- m_hsk = hskwrite || m_rhsus;
+ m_hsklocal = hskwrite || m_rhsus;
update_hexbus();
}
// Actions that occur for Phi3=0
@@ -2575,26 +2580,110 @@ WRITE_LINE_MEMBER( oso_device::clock_in )
}
}
+/*
+ Change the Hexbus line levels and propagate them towards the peripherals.
+*/
void oso_device::update_hexbus()
{
- uint8_t value = 0x00;
- uint8_t nibble = m_xmit;
+ bool changed = false;
+ if (m_hsklocal != m_hskold)
+ {
+ LOGMASKED(LOG_HEXBUS, "%s HSK*\n", m_hsklocal? "Pulling down" : "Releasing");
+ m_hskold = m_hsklocal;
+ changed = true;
+ }
+
+ if (m_bav != m_bavold)
+ {
+ LOGMASKED(LOG_HEXBUS, "%s BAV*\n", m_bav? "Pulling down" : "Releasing");
+ m_bavold = m_bav;
+ changed = true;
+ }
+
+ if (!changed) return;
+
+ // If wbusy==false, set the data output to 1111; since the Hexbus is
+ // a pull-down line bus, this means to inactivate the output
+ uint8_t nibble = m_wbusy? m_xmit : 0xff;
if (m_wnp) nibble >>= 4;
- value = ((m_xmit & 0x0c)<<4) | (m_xmit & 0x03);
- if (!m_hsk) value |= 0x10;
- if (!control_bit(BAVC)) value |= 0x04;
- if (value != m_lasthxvalue)
+ uint8_t value = to_line_state(nibble, control_bit(BAVC), m_hsklocal);
+
+ // if (m_oldvalue != value)
+ // LOGMASKED(LOG_OSO, "Set hexbus = %02x (BAV*=%d, HSK*=%d, data=%01x)\n", value, (value & 0x04)? 1:0, (value & 0x10)? 1:0, ((value>>4)&0x0c) | (value&0x03));
+
+ // As for Oso, we can be sure that hexbus_write does not trigger further
+ // activities from the peripherals that cause a call to hexbus_value_changed.
+ hexbus_write(value);
+
+ // Check how the bus has changed. This depends on the states of all
+ // connected peripherals
+ uint8_t value1 = hexbus_read();
+ // if (value1 != value) LOGMASKED(LOG_OSO, "actually: %02x (BAV*=%d, HSK*=%d, data=%01x)\n", value1, (value1 & 0x04)? 1:0, (value1 & 0x10)? 1:0, ((value1>>4)&0x0c) | (value1&0x03));
+
+ // Update the state of BAV and HSK
+ m_bav = ((value1 & bus::hexbus::HEXBUS_LINE_BAV)==0);
+ m_hsk = ((value1 & bus::hexbus::HEXBUS_LINE_HSK)==0);
+
+ // Sometimes, Oso does not have a chance to advance its state after the
+ // last byte was read. In that case, a change of rdsetin would not be
+ // sensed. We reset the flag right here and so pretend that the tick
+ // has happened.
+ if (m_hsk==false) m_rdsetold = false;
+
+ m_oldvalue = value1;
+}
+
+/*
+ Called when the value on the Hexbus has changed.
+*/
+void oso_device::hexbus_value_changed(uint8_t data)
+{
+// LOGMASKED(LOG_OSO, "Hexbus value changed to %02x\n", data);
+ bool bav = (data & bus::hexbus::HEXBUS_LINE_BAV)==0;
+ bool hsk = (data & bus::hexbus::HEXBUS_LINE_HSK)==0;
+
+ if ((bav != m_bav) || (hsk != m_hsk))
+ {
+ m_bav = bav | control_bit(BAVC);
+ m_hsk = hsk;
+
+ LOGMASKED(LOG_HEXBUS, "BAV*=%d, HSK*=%d\n", m_bav? 0:1, m_hsk? 0:1);
+ int nibble = ((data & bus::hexbus::HEXBUS_LINE_BIT32)>>4) | (data & bus::hexbus::HEXBUS_LINE_BIT10);
+
+ // The real devices are driven at a similar clock rate like the 99/8.
+ // The designers assumed that there is a clock tick of Oso between
+ // every clock tick of the peripheral device. This is not true for
+ // the emulation in MAME, however. For that reason, we trigger "fake"
+ // clock ticks on every change of the hexbus.
+ for (int fake=0; fake < 4; fake++)
+ {
+ if (m_msns)
+ {
+ m_data = (m_data & 0x0f) | (nibble<<4);
+ LOGMASKED(LOG_HEXBUS, "Data register = %02x\n", m_data);
+ }
+ if (m_lsns)
+ {
+ m_data = (m_data & 0xf0) | nibble;
+ LOGMASKED(LOG_HEXBUS, "Data register = %02x\n", m_data);
+ }
+
+ LOGMASKED(LOG_HEXBUS, "Fake tick %d\n", fake);
+ bool phi3 = m_phi3; // mind that clock_in swaps the state of m_phi3
+ clock_in(!phi3);
+ clock_in(phi3);
+ LOGMASKED(LOG_HEXBUS, "Fake tick %d end\n", fake);
+ }
+ }
+ else
{
- if (TRACE_OSO) logerror("Set hexbus = %02x (BAV*=%d, HSK*=%d, data=%01x)\n", value, (value & 0x04)? 1:0, (value & 0x10)? 1:0, ((value>>4)&0x0c) | (value&0x03));
- hexbus_write(value);
+ LOGMASKED(LOG_HEXBUS, "No change for BAV* and HSK*\n");
}
- m_lasthxvalue = value;
}
void oso_device::device_start()
{
- logerror("Starting\n");
m_status = m_xmit = m_control = m_data = 0;
m_int.resolve_safe();
diff --git a/src/devices/bus/ti99/internal/998board.h b/src/devices/bus/ti99/internal/998board.h
index 526fad8bf44..e8df327cae1 100644
--- a/src/devices/bus/ti99/internal/998board.h
+++ b/src/devices/bus/ti99/internal/998board.h
@@ -422,6 +422,33 @@ private:
/*
Custom chip: OSO
*/
+
+/* Status register bits */
+typedef enum
+{
+ HSKWT = 0x80,
+ HSKRD = 0x40,
+ BAVIAS = 0x20,
+ BAVAIS = 0x10,
+ SBAV = 0x08,
+ WBUSY = 0x04,
+ RBUSY = 0x02,
+ SHSK = 0x01
+} oso_status;
+
+/* Control register bits */
+typedef enum
+{
+ WIEN = 0x80,
+ RIEN = 0x40,
+ BAVIAEN = 0x20,
+ BAVAIEN = 0x10,
+ BAVC = 0x08,
+ WEN = 0x04,
+ REN = 0x02,
+ CR7 = 0x01
+} oso_control;
+
class oso_device : public bus::hexbus::hexbus_chained_device
{
public:
@@ -429,9 +456,6 @@ public:
DECLARE_READ8_MEMBER( read );
DECLARE_WRITE8_MEMBER( write );
void device_start() override;
- // Don't add a hexbus connector; we use the one from the driver instance
- virtual void device_add_mconfig(machine_config &config) override { };
-
void hexbus_value_changed(uint8_t data) override;
WRITE_LINE_MEMBER( clock_in );
@@ -440,8 +464,8 @@ public:
devcb_write_line m_int;
private:
- bool control_bit(int bit) { return (m_control & bit)!=0; }
- bool status_bit(int bit) { return (m_status & bit)!=0; }
+ bool control_bit(oso_control bit) { return (m_control & bit)!=0; }
+ bool status_bit(oso_status bit) { return (m_status & bit)!=0; }
void clear_int_status();
void set_status(int bit, bool set) { m_status = (set)? (m_status | bit) : (m_status & ~bit); }
void update_hexbus();
@@ -452,18 +476,15 @@ private:
uint8_t m_control;
uint8_t m_xmit;
- // Last hexbus value; when the new value is different, send it via the hexbus
- uint8_t m_lasthxvalue;
-
bool m_bav; // Bus available; when true, a communication is about to happen
bool m_sbav; // Stable BAV; the BAV signal is true for two clock cycles
bool m_sbavold; // Old SBAV state
- bool m_bavhold; // For computing the SBAV signal
+ bool m_bavold;
bool m_hsk; // Handshake line; when true, a bus member needs more time to process the message
+ bool m_hsklocal; // Local level of HSK
bool m_shsk; // Stable HSK
- bool m_shskold; // see above
- bool m_hskhold; // see above
+ bool m_hskold;
// Page 3 in OSO schematics: Write timing
bool m_wq1; // Flipflop 1
@@ -471,6 +492,7 @@ private:
bool m_wq2; // Flipflop 2
bool m_wq2old; // Previous state
bool m_wnp; // Write nibble selection; true means upper 4 bits
+ bool m_wbusy; // When true, direct the transmit register towards the output
bool m_wbusyold; // Old state of the WBUSY line
bool m_sendbyte; // Byte has been loaded into the XMIT register
bool m_wrset; // Start sending
@@ -490,6 +512,25 @@ private:
// Page 6 (RHSUS*)
bool m_rhsus; // Needed to assert the HSK line until the CPU has read the byte
+
+ bool m_rbusy;
+
+ bool m_phi3;
+
+ // Debugging help
+ uint8_t m_oldvalue;
+/*
+ // This is a buffer to enqueue changes on the Hexbus
+ // This is not part of the real implementation, but in the emulation
+ // there is no guarantee that two subsequent bus changes will be sensed
+ // on the other side
+
+ void enqueue(uint8_t val);
+ uint8_t dequeue();
+
+ uint8_t m_queue[8];
+ int m_qhead;
+ int m_qtail; */
};
class mainboard8_device : public device_t
diff --git a/src/devices/cpu/tms9900/tms9995.cpp b/src/devices/cpu/tms9900/tms9995.cpp
index ce854d82c04..7a9382f571e 100644
--- a/src/devices/cpu/tms9900/tms9995.cpp
+++ b/src/devices/cpu/tms9900/tms9995.cpp
@@ -121,59 +121,33 @@ enum
/*****************************************************************
Debugging
- Set to 0 (disable) or 1 (enable)
+ Add the desired LOG aspect to the VERBOSE line
******************************************************************/
-// Log addresses of executed opcodes
-#define TRACE_EXEC 0
-
-// Log cycles
-#define TRACE_CYCLES 0
-
-// Log configuration
-#define TRACE_CONFIG 1
-
-// Log emulation details
-#define TRACE_EMU 0
-
-// Log wait/hold states
-#define TRACE_WAITHOLD 0
-
-// Log microinstruction processing
-#define TRACE_MICRO 0
-
-// Log interrupts
-#define TRACE_INT 0
-
-// Log interrupts (detailed phases)
-#define TRACE_INTD 0
-
-// Log clock pulses
-#define TRACE_CLOCK 0
-
-// Log READY line input
-#define TRACE_READY 0
-
-// Log memory access
-#define TRACE_MEM 0
-
-// Log address bus operation
-#define TRACE_ADDRESSBUS 0
-
-// Log CRU operations
-#define TRACE_CRU 0
-
-// Log status register
-#define TRACE_STATUS 0
-
-// Log operation
-#define TRACE_OP 0
-
-// Log decrementer operation
-#define TRACE_DEC 0
-
-// Log with max detail
-#define TRACE_DETAIL 0
+#define LOG_OP (1U<<1) // Current instruction
+#define LOG_EXEC (1U<<2) // Address of current instruction
+#define LOG_CONFIG (1U<<3) // Configuration
+#define LOG_CYCLES (1U<<4) // Cycles
+#define LOG_WARN (1U<<5) // Illegal operation or other condition
+#define LOG_MEM (1U<<6) // Memory access
+#define LOG_CONTEXT (1U<<7) // Context switch
+#define LOG_INT (1U<<8) // Interrupts
+#define LOG_READY (1U<<9) // READY line input
+#define LOG_CLOCK (1U<<10) // Clock pulses
+#define LOG_ADDRESSBUS (1U<<11) // Address bus operation
+#define LOG_STATUS (1U<<12) // Status register
+#define LOG_CRU (1U<<13) // CRU operations
+#define LOG_DEC (1U<<14) // Decrementer
+#define LOG_WAITHOLD (1U<<15) // Wait/hold states
+#define LOG_EMU (1U<<16) // Emulation details
+#define LOG_MICRO (1U<<17) // Microinstruction processing
+#define LOG_INTD (1U<<18) // Interrupts (detailed phases)
+#define LOG_DETAIL (1U<<19) // Increased detail
+
+// Minimum log should be config and warnings
+#define VERBOSE ( LOG_CONFIG | LOG_WARN )
+
+#include "logmacro.h"
/****************************************************************************
Constructor
@@ -257,7 +231,7 @@ void tms9995_device::device_start()
// Set up the lookup table for command decoding
build_command_lookup_table();
- if (TRACE_CONFIG) logerror("%s: Variant = %s, Overflow int = %s\n", tag(), m_mp9537? "MP9537 (no on-chip RAM)" : "with on-chip RAM", m_check_overflow? "check" : "no check");
+ LOGMASKED(LOG_CONFIG, "Variant = %s, Overflow int = %s\n", m_mp9537? "MP9537 (no on-chip RAM)" : "standard (with on-chip RAM)", m_check_overflow? "check" : "no check");
// Register persistable state variables
// save_item(NAME(m_state_any)); // only for debugger output
@@ -1172,7 +1146,7 @@ void tms9995_device::build_command_lookup_table()
{
inst = &s_command[i];
table = m_command_lookup_table.get();
- if (TRACE_EMU) logerror("=== opcode=%04x, len=%d\n", inst->opcode, format_mask_len[inst->format]);
+ LOGMASKED(LOG_EMU, "=== opcode=%04x, len=%d\n", inst->opcode, format_mask_len[inst->format]);
bitcount = 4;
opcode = inst->opcode;
cmdindex = (opcode>>12) & 0x000f;
@@ -1182,7 +1156,7 @@ void tms9995_device::build_command_lookup_table()
// Descend
if (table[cmdindex].next_digit == nullptr)
{
- if (TRACE_EMU) logerror("create new table at bitcount=%d for index=%d\n", bitcount, cmdindex);
+ LOGMASKED(LOG_EMU, "create new table at bitcount=%d for index=%d\n", bitcount, cmdindex);
table[cmdindex].next_digit = std::make_unique<lookup_entry[]>(16);
for (int j=0; j < 16; j++)
{
@@ -1192,7 +1166,7 @@ void tms9995_device::build_command_lookup_table()
}
else
{
- if (TRACE_EMU) logerror("found a table at bitcount=%d\n", bitcount);
+ LOGMASKED(LOG_EMU, "found a table at bitcount=%d\n", bitcount);
}
table = table[cmdindex].next_digit.get();
@@ -1200,17 +1174,17 @@ void tms9995_device::build_command_lookup_table()
bitcount = bitcount+4;
opcode <<= 4;
cmdindex = (opcode>>12) & 0x000f;
- if (TRACE_EMU) logerror("next index=%x\n", cmdindex);
+ LOGMASKED(LOG_EMU, "next index=%x\n", cmdindex);
}
- if (TRACE_EMU) logerror("bitcount=%d\n", bitcount);
+ LOGMASKED(LOG_EMU, "bitcount=%d\n", bitcount);
// We are at the target level
// Need to fill in the same entry for all values in the bitcount
// (if a command needs 10 bits we have to copy it four
// times for all combinations with 12 bits)
for (int j=0; j < (1<<(bitcount-format_mask_len[inst->format])); j++)
{
- if (TRACE_EMU) logerror("opcode=%04x at position %d\n", inst->opcode, cmdindex+j);
+ LOGMASKED(LOG_EMU, "opcode=%04x at position %d\n", inst->opcode, cmdindex+j);
table[cmdindex+j].index = i;
}
@@ -1234,14 +1208,14 @@ void tms9995_device::execute_run()
{
if (m_reset) service_interrupt();
- if (TRACE_EMU) logerror("calling execute_run for %d cycles\n", m_icount);
+ LOGMASKED(LOG_EMU, "calling execute_run for %d cycles\n", m_icount);
do
{
// Normal operation
if (m_check_ready && m_ready == false)
{
// We are in a wait state
- if (TRACE_WAITHOLD) logerror("wait state\n");
+ LOGMASKED(LOG_WAITHOLD, "wait state\n");
// The clock output should be used to change the state of an outer
// device which operates the READY line
pulse_clock(1);
@@ -1251,7 +1225,7 @@ void tms9995_device::execute_run()
if (m_check_hold && m_hold_requested)
{
set_hold_state(true);
- if (TRACE_WAITHOLD) logerror("HOLD state\n");
+ LOGMASKED(LOG_WAITHOLD, "HOLD state\n");
pulse_clock(1);
}
else
@@ -1260,7 +1234,7 @@ void tms9995_device::execute_run()
m_check_ready = false;
- if (TRACE_MICRO) logerror("main loop, operation %s, MPC = %d\n", opname[m_command], MPC);
+ LOGMASKED(LOG_MICRO, "main loop, operation %s, MPC = %d\n", opname[m_command], MPC);
uint8_t* program = (uint8_t*)s_command[m_index].prog;
(this->*s_microoperation[program[MPC]])();
@@ -1276,7 +1250,7 @@ void tms9995_device::execute_run()
}
} while (m_icount>0 && !m_reset);
- if (TRACE_EMU) logerror("cycles expired; will return soon.\n");
+ LOGMASKED(LOG_EMU, "cycles expired; will return soon.\n");
}
/**************************************************************************/
@@ -1303,28 +1277,28 @@ void tms9995_device::execute_set_input(int irqline, int state)
if (irqline == INPUT_LINE_NMI)
{
m_nmi_active = (state==ASSERT_LINE);
- if (TRACE_INT) logerror("NMI interrupt line state=%d\n", state);
+ LOGMASKED(LOG_INT, "NMI interrupt line state=%d\n", state);
}
else
{
if (irqline == INT_9995_INT1)
{
m_int1_active = m_flag[2] = (state==ASSERT_LINE);
- if (TRACE_INT) logerror("Line INT1 state=%d\n", state);
+ LOGMASKED(LOG_INT, "Line INT1 state=%d\n", state);
}
else
{
if (irqline == INT_9995_INT4)
{
- if (TRACE_INT) logerror("Line INT4/EC state=%d\n", state);
+ LOGMASKED(LOG_INT, "Line INT4/EC state=%d\n", state);
if (m_flag[0]==false)
{
- if (TRACE_INT) logerror("set as interrupt\n");
+ LOGMASKED(LOG_INT, "set as interrupt\n");
m_int4_active = m_flag[4] = (state==ASSERT_LINE);
}
else
{
- if (TRACE_INT) logerror("set as event count\n");
+ LOGMASKED(LOG_INT, "set as event count\n");
trigger_decrementer();
}
}
@@ -1363,11 +1337,12 @@ void tms9995_device::pulse_clock(int count)
m_ready = m_ready_bufd && !m_request_auto_wait_state; // get the latched READY state
if (!m_clock_out_line.isnull()) m_clock_out_line(CLEAR_LINE);
m_icount--; // This is the only location where we count down the cycles.
- if (TRACE_CLOCK)
- {
- if (m_check_ready) logerror("pulse_clock, READY=%d, auto_wait=%d\n", m_ready_bufd? 1:0, m_auto_wait? 1:0);
- else logerror("pulse_clock\n");
- }
+
+ if (m_check_ready)
+ LOGMASKED(LOG_CLOCK, "pulse_clock, READY=%d, auto_wait=%d\n", m_ready_bufd? 1:0, m_auto_wait? 1:0);
+ else
+ LOGMASKED(LOG_CLOCK, "pulse_clock\n");
+
m_request_auto_wait_state = false;
if (m_flag[0] == false && m_flag[1] == true)
{
@@ -1385,7 +1360,7 @@ void tms9995_device::pulse_clock(int count)
WRITE_LINE_MEMBER( tms9995_device::hold_line )
{
m_hold_requested = (state==ASSERT_LINE);
- if (TRACE_WAITHOLD) logerror("set HOLD = %d\n", state);
+ LOGMASKED(LOG_WAITHOLD, "set HOLD = %d\n", state);
if (!m_hold_requested)
{
if (!m_holda_line.isnull()) m_holda_line(CLEAR_LINE);
@@ -1398,11 +1373,19 @@ WRITE_LINE_MEMBER( tms9995_device::hold_line )
*/
WRITE_LINE_MEMBER( tms9995_device::ready_line )
{
- if (m_reset && (m_ready_bufd != state)) logerror("Ignoring READY=%d change due to pending RESET\n", state);
- else
+ bool newready = (state==ASSERT_LINE);
+
+ if (newready != m_ready_bufd)
{
- m_ready_bufd = (state==ASSERT_LINE);
- if (TRACE_READY) logerror("set READY = %d\n", m_ready_bufd? 1 : 0);
+ if (m_reset)
+ {
+ LOGMASKED(LOG_WARN, "Ignoring READY=%d change due to pending RESET\n", state);
+ }
+ else
+ {
+ m_ready_bufd = newready;
+ LOGMASKED(LOG_READY, "set READY = %d\n", m_ready_bufd? 1 : 0);
+ }
}
}
@@ -1444,7 +1427,7 @@ void tms9995_device::decode(uint16_t inst)
while (!complete)
{
ix = (opcode >> 12) & 0x000f;
- if (TRACE_EMU) logerror("Check next hex digit of instruction %x\n", ix);
+ LOGMASKED(LOG_EMU, "Check next hex digit of instruction %x\n", ix);
if (table[ix].next_digit != nullptr)
{
table = table[ix].next_digit.get();
@@ -1457,7 +1440,7 @@ void tms9995_device::decode(uint16_t inst)
if (program_index == NOPRG)
{
// not found
- logerror("Undefined opcode %04x at logical address %04x, will trigger MID\n", inst, PC);
+ LOGMASKED(LOG_WARN, "Undefined opcode %04x at logical address %04x, will trigger MID\n", inst, PC);
m_pre_IR = 0;
m_pre_command = MID;
}
@@ -1469,7 +1452,7 @@ void tms9995_device::decode(uint16_t inst)
m_pre_command = decoded.id;
m_pre_index = program_index;
m_pre_byteop = ((decoded.format == 1) && ((inst & 0x1000)!=0));
- if (TRACE_EMU) logerror("Command decoded as id %d, %s, base opcode %04x\n", decoded.id, opname[decoded.id], decoded.opcode);
+ LOGMASKED(LOG_EMU, "Command decoded as id %d, %s, base opcode %04x\n", decoded.id, opname[decoded.id], decoded.opcode);
m_pass = 1;
}
}
@@ -1489,7 +1472,7 @@ void tms9995_device::int_prefetch_and_decode()
// Check interrupt lines
if (m_nmi_active)
{
- if (TRACE_INT) logerror("Checking interrupts ... NMI active\n");
+ LOGMASKED(LOG_INT, "Checking interrupts ... NMI active\n");
m_int_pending |= PENDING_NMI;
m_idle_state = false;
PC = (PC + 2) & 0xfffe; // we have not prefetched the next instruction
@@ -1512,19 +1495,19 @@ void tms9995_device::int_prefetch_and_decode()
if (m_idle_state)
{
m_idle_state = false;
- if (TRACE_INT) logerror("Interrupt occurred, terminate IDLE state\n");
+ LOGMASKED(LOG_INT, "Interrupt occurred, terminate IDLE state\n");
}
PC = PC + 2; // PC must be advanced (see flow chart), but no prefetch
- if (TRACE_INT) logerror("Interrupts pending; no prefetch; advance PC to %04x\n", PC);
+ LOGMASKED(LOG_INT, "Interrupts pending; no prefetch; advance PC to %04x\n", PC);
return;
}
else
{
- if (TRACE_INT) logerror("Checking interrupts ... none pending\n");
+ LOGMASKED(LOG_INT, "Checking interrupts ... none pending\n");
// No pending interrupts
if (m_idle_state)
{
- if (TRACE_WAITHOLD) logerror("IDLE state\n");
+ LOGMASKED(LOG_WAITHOLD, "IDLE state\n");
// We are IDLE, stay in the loop and do not advance the PC
m_pass = 2;
pulse_clock(1);
@@ -1554,7 +1537,7 @@ void tms9995_device::prefetch_and_decode()
m_value_copy = m_current_value;
if (!m_iaq_line.isnull()) m_iaq_line(ASSERT_LINE);
m_address = PC;
- if (TRACE_OP) logerror("**** Prefetching new instruction at %04x ****\n", PC);
+ LOGMASKED(LOG_DETAIL, "**** Prefetching new instruction at %04x ****\n", PC);
}
word_read(); // changes m_mem_phase
@@ -1567,7 +1550,7 @@ void tms9995_device::prefetch_and_decode()
m_current_value = m_value_copy; // restore m_current_value
PC = (PC + 2) & 0xfffe; // advance PC
if (!m_iaq_line.isnull()) m_iaq_line(CLEAR_LINE);
- if (TRACE_OP) logerror("++++ Prefetch done ++++\n");
+ LOGMASKED(LOG_DETAIL, "++++ Prefetch done ++++\n");
}
}
@@ -1598,13 +1581,14 @@ void tms9995_device::next_command()
// This is a preset for opcodes which do not need an opcode address derivation
m_address = WP + ((IR & 0x000f)<<1);
MPC = -1;
- if (TRACE_OP) logerror("===== Next operation %04x (%s) at %04x =====\n", IR, opname[m_command], PC-2);
+ LOGMASKED(LOG_OP, "===== %04x: Op=%04x (%s)\n", PC-2, IR, opname[m_command]);
+
+ // Mark logged address as interrupt service
+ if (m_log_interrupt)
+ LOGMASKED(LOG_EXEC, "i%04x\n", PC-2);
+ else
+ LOGMASKED(LOG_EXEC, "%04x\n", PC-2);
- if (TRACE_EXEC)
- {
- if (m_log_interrupt) logerror("i%04x\n", PC-2);
- else logerror("%04x\n", PC-2);
- }
PC_debug = PC - 2;
debugger_instruction_hook(PC_debug);
m_first_cycle = m_icount;
@@ -1617,7 +1601,7 @@ void tms9995_device::next_command()
void tms9995_device::command_completed()
{
// Pseudo state at the end of the current instruction cycle sequence
- if (TRACE_CYCLES)
+ if (LOG_CYCLES & VERBOSE)
{
logerror("+++++ Instruction %04x (%s) completed", IR, opname[m_command]);
int cycles = m_first_cycle - m_icount;
@@ -1679,7 +1663,7 @@ void tms9995_device::service_interrupt()
vectorpos = 0x0008;
m_intmask = 0x0001;
PC = (PC + 2) & 0xfffe;
- if (TRACE_INT) logerror("***** MID pending\n");
+ LOGMASKED(LOG_INT, "***** MID pending\n");
m_mid_active = false;
}
else
@@ -1689,7 +1673,7 @@ void tms9995_device::service_interrupt()
vectorpos = 0xfffc;
m_int_pending &= ~PENDING_NMI;
m_intmask = 0;
- if (TRACE_INT) logerror("***** NMI pending\n");
+ LOGMASKED(LOG_INT, "***** NMI pending\n");
}
else
{
@@ -1699,7 +1683,7 @@ void tms9995_device::service_interrupt()
m_int_pending &= ~PENDING_LEVEL1;
m_flag[2] = false;
m_intmask = 0;
- if (TRACE_INT) logerror("***** INT1 pending\n");
+ LOGMASKED(LOG_INT, "***** INT1 pending\n");
}
else
{
@@ -1708,7 +1692,7 @@ void tms9995_device::service_interrupt()
vectorpos = 0x0008;
m_int_pending &= ~PENDING_OVERFLOW;
m_intmask = 0x0001;
- if (TRACE_INT) logerror("***** OVERFL pending\n");
+ LOGMASKED(LOG_INT, "***** OVERFL pending\n");
}
else
{
@@ -1719,7 +1703,7 @@ void tms9995_device::service_interrupt()
m_int_pending &= ~PENDING_DECR;
m_flag[3] = false;
m_int_decrementer = false;
- if (TRACE_DEC) logerror("***** DECR pending\n");
+ LOGMASKED(LOG_DEC, "***** DECR pending\n");
}
else
{
@@ -1727,7 +1711,7 @@ void tms9995_device::service_interrupt()
m_intmask = 0x0003;
m_int_pending &= ~PENDING_LEVEL4;
m_flag[4] = false;
- if (TRACE_INT) logerror("***** INT4 pending\n");
+ LOGMASKED(LOG_INT, "***** INT4 pending\n");
}
}
}
@@ -1735,7 +1719,7 @@ void tms9995_device::service_interrupt()
}
}
- if (TRACE_INT) logerror("********* triggered an interrupt with vector %04x/%04x\n", vectorpos, vectorpos+2);
+ LOGMASKED(LOG_INT, "********* triggered an interrupt with vector %04x/%04x\n", vectorpos, vectorpos+2);
// just for debugging purposes
if (!m_reset) m_log_interrupt = true;
@@ -1787,7 +1771,7 @@ void tms9995_device::mem_read()
if ((m_address & 0xfffe)==0xfffa && !m_mp9537)
{
- if (TRACE_DEC) logerror("read decrementer\n");
+ LOGMASKED(LOG_DEC, "read decrementer\n");
// Decrementer mapped into the address space
m_current_value = m_decrementer_value;
if (m_byteop)
@@ -1806,7 +1790,7 @@ void tms9995_device::mem_read()
// byte operations (e.g. when retrieving the index register)
if (m_word_access || !m_byteop) m_address &= 0xfffe;
- if (TRACE_MEM) logerror("read onchip memory (single pass, address %04x)\n", m_address);
+ LOGMASKED(LOG_MEM, "read onchip memory (single pass, address %04x)\n", m_address);
// Ignore the READY state
m_check_ready = false;
@@ -1841,7 +1825,7 @@ void tms9995_device::mem_read()
else m_pass = 2;
m_check_hold = false;
- if (TRACE_ADDRESSBUS) logerror("set address bus %04x\n", m_address & ~1);
+ LOGMASKED(LOG_ADDRESSBUS, "set address bus %04x\n", m_address & ~1);
m_prgspace->set_address(address);
m_request_auto_wait_state = m_auto_wait;
pulse_clock(1);
@@ -1850,12 +1834,12 @@ void tms9995_device::mem_read()
// Sample the value on the data bus (high byte)
if (m_word_access || !m_byteop) address &= 0xfffe;
value = m_prgspace->read_byte(address);
- if (TRACE_MEM) logerror("memory read byte %04x -> %02x\n", m_address & ~1, value);
+ LOGMASKED(LOG_MEM, "memory read byte %04x -> %02x\n", m_address & ~1, value);
m_current_value = (value << 8) & 0xff00;
break;
case 3:
// Set address + 1 (unless byte command)
- if (TRACE_ADDRESSBUS) logerror("set address bus %04x\n", m_address | 1);
+ LOGMASKED(LOG_ADDRESSBUS, "set address bus %04x\n", m_address | 1);
m_prgspace->set_address(m_address | 1);
m_request_auto_wait_state = m_auto_wait;
pulse_clock(1);
@@ -1864,7 +1848,7 @@ void tms9995_device::mem_read()
// Read low byte
value = m_prgspace->read_byte(m_address | 1);
m_current_value |= value;
- if (TRACE_MEM) logerror("memory read byte %04x -> %02x, complete word = %04x\n", m_address | 1, value, m_current_value);
+ LOGMASKED(LOG_MEM, "memory read byte %04x -> %02x, complete word = %04x\n", m_address | 1, value, m_current_value);
m_check_hold = true;
break;
}
@@ -1932,7 +1916,7 @@ void tms9995_device::mem_write()
{
m_starting_count_storage_register = m_decrementer_value = m_current_value;
}
- if (TRACE_DEC) logerror("Setting decrementer to %04x, PC=%04x\n", m_current_value, PC);
+ LOGMASKED(LOG_DEC, "Setting decrementer to %04x, PC=%04x\n", m_current_value, PC);
pulse_clock(1);
return;
}
@@ -1944,7 +1928,7 @@ void tms9995_device::mem_write()
// byte operations (e.g. when retrieving the index register)
if (m_word_access || !m_byteop) m_address &= 0xfffe;
- if (TRACE_MEM) logerror("write to onchip memory (single pass, address %04x, value=%04x)\n", m_address, m_current_value);
+ LOGMASKED(LOG_MEM, "write to onchip memory (single pass, address %04x, value=%04x)\n", m_address, m_current_value);
m_check_ready = false;
m_onchip_memory[m_address & 0x00ff] = (m_current_value >> 8) & 0xff;
if (m_word_access || !m_byteop)
@@ -1973,9 +1957,9 @@ void tms9995_device::mem_write()
else m_pass = 2;
m_check_hold = false;
- if (TRACE_ADDRESSBUS) logerror("set address bus %04x\n", address);
+ LOGMASKED(LOG_ADDRESSBUS, "set address bus %04x\n", address);
m_prgspace->set_address(address);
- if (TRACE_MEM) logerror("memory write byte %04x <- %02x\n", address, (m_current_value >> 8)&0xff);
+ LOGMASKED(LOG_MEM, "memory write byte %04x <- %02x\n", address, (m_current_value >> 8)&0xff);
m_prgspace->write_byte(address, (m_current_value >> 8)&0xff);
m_request_auto_wait_state = m_auto_wait;
pulse_clock(1);
@@ -1986,9 +1970,9 @@ void tms9995_device::mem_write()
break;
case 3:
// Set address + 1 (unless byte command)
- if (TRACE_ADDRESSBUS) logerror("set address bus %04x\n", m_address | 1);
+ LOGMASKED(LOG_ADDRESSBUS, "set address bus %04x\n", m_address | 1);
m_prgspace->set_address(m_address | 1);
- if (TRACE_MEM) logerror("memory write byte %04x <- %02x\n", m_address | 1, m_current_value & 0xff);
+ LOGMASKED(LOG_MEM, "memory write byte %04x <- %02x\n", m_address | 1, m_current_value & 0xff);
m_prgspace->write_byte(m_address | 1, m_current_value & 0xff);
m_request_auto_wait_state = m_auto_wait;
pulse_clock(1);
@@ -2029,7 +2013,7 @@ void tms9995_device::return_with_address()
m_index = m_caller_index;
MPC = m_caller_MPC; // will be increased on return
m_address = m_current_value + m_address_add;
- if (TRACE_DETAIL) logerror("+++ return from operand address derivation +++\n");
+ LOGMASKED(LOG_DETAIL, "+++ return from operand address derivation +++\n");
// no clock pulse
}
@@ -2043,7 +2027,7 @@ void tms9995_device::return_with_address_copy()
m_index = m_caller_index;
MPC = m_caller_MPC; // will be increased on return
m_address = m_address_saved;
- if (TRACE_DETAIL) logerror("+++ return from operand address derivation (auto inc) +++\n");
+ LOGMASKED(LOG_DETAIL, "+++ return from operand address derivation (auto inc) +++\n");
// no clock pulse
}
@@ -2084,7 +2068,7 @@ void tms9995_device::return_with_address_copy()
void tms9995_device::cru_output_operation()
{
- if (TRACE_CRU) logerror("CRU output operation, address %04x, value %d\n", m_cru_address, m_cru_value & 0x01);
+ LOGMASKED(LOG_CRU, "CRU output operation, address %04x, value %d\n", m_cru_address, m_cru_value & 0x01);
if (m_cru_address == 0x1fda)
{
@@ -2099,7 +2083,7 @@ void tms9995_device::cru_output_operation()
{
m_check_ready = false;
// FLAG2, FLAG3, and FLAG4 are read-only
- if (TRACE_CRU) logerror("set CRU address %04x to %d\n", m_cru_address, m_cru_value&1);
+ LOGMASKED(LOG_CRU, "set CRU address %04x to %d\n", m_cru_address, m_cru_value&1);
if ((m_cru_address != 0x1ee4) && (m_cru_address != 0x1ee6) && (m_cru_address != 0x1ee8))
m_flag[(m_cru_address>>1)&0x000f] = (m_cru_value & 0x01);
}
@@ -2156,7 +2140,7 @@ void tms9995_device::cru_input_operation()
// ........ ........ X....... ........
//
crubyte = m_cru->read_byte((m_cru_address >> 4)& CRUREADMASK);
- if (TRACE_DETAIL) logerror("Need to get next 8 bits (addresses %04x-%04x): %02x\n", (m_cru_address&0xfff0)+14, m_cru_address&0xfff0, crubyte);
+ LOGMASKED(LOG_DETAIL, "Need to get next 8 bits (addresses %04x-%04x): %02x\n", (m_cru_address&0xfff0)+14, m_cru_address&0xfff0, crubyte);
m_cru_read = crubyte << 15;
m_cru_bits_left = 8;
@@ -2168,7 +2152,7 @@ void tms9995_device::cru_input_operation()
m_cru_first_read = false;
m_pass = m_count;
}
- if (TRACE_DETAIL) logerror("adjusted value for shift: %06x\n", m_cru_read);
+ LOGMASKED(LOG_DETAIL, "adjusted value for shift: %06x\n", m_cru_read);
}
crubit = (m_cru_read & 0x8000);
@@ -2194,7 +2178,7 @@ void tms9995_device::cru_input_operation()
}
}
- if (TRACE_CRU) logerror("CRU input operation, address %04x, value %d\n", m_cru_address, (crubit & 0x8000)>>15);
+ LOGMASKED(LOG_CRU, "CRU input operation, address %04x, value %d\n", m_cru_address, (crubit & 0x8000)>>15);
m_cru_value |= crubit;
@@ -2224,11 +2208,11 @@ void tms9995_device::trigger_decrementer()
m_decrementer_value--;
if (m_decrementer_value==0)
{
- if (TRACE_DEC) logerror("decrementer reached 0\n");
+ LOGMASKED(LOG_DEC, "decrementer reached 0\n");
m_decrementer_value = m_starting_count_storage_register;
if (m_flag[1]==true)
{
- if (TRACE_DEC) logerror("decrementer flags interrupt\n");
+ LOGMASKED(LOG_DEC, "decrementer flags interrupt\n");
m_flag[3] = true;
m_int_decrementer = true;
}
@@ -2277,12 +2261,12 @@ void tms9995_device::operand_address_subprogram()
{
if (m_regnumber != 0)
{
- if (TRACE_DETAIL) logerror("indexed addressing\n");
+ LOGMASKED(LOG_DETAIL, "indexed addressing\n");
MPC = 16; // indexed
}
else
{
- if (TRACE_DETAIL) logerror("symbolic addressing\n");
+ LOGMASKED(LOG_DETAIL, "symbolic addressing\n");
m_address = PC;
PC = (PC + 2) & 0xfffe;
}
@@ -2292,7 +2276,7 @@ void tms9995_device::operand_address_subprogram()
m_mem_phase = 1;
m_address_add = 0;
MPC--; // will be increased in the mail loop
- if (TRACE_DETAIL) logerror("*** Operand address derivation; address=%04x; index=%d\n", m_address, MPC+1);
+ LOGMASKED(LOG_DETAIL, "*** Operand address derivation; address=%04x; index=%d\n", m_address, MPC+1);
}
/*
@@ -2434,7 +2418,7 @@ void tms9995_device::alu_add_s_sxc()
{
set_status_parity((uint8_t)(dest_new>>8));
}
- if (TRACE_STATUS) logerror("ST = %04x (val=%04x)\n", ST, m_current_value);
+ LOGMASKED(LOG_STATUS, "ST = %04x (val=%04x)\n", ST, m_current_value);
// No clock pulse (will be done by prefetch)
}
@@ -2481,7 +2465,7 @@ void tms9995_device::alu_blwp()
case 4:
PC = m_current_value & 0xfffe;
n = 0;
- if (TRACE_OP) logerror("Context switch complete; WP=%04x, PC=%04x, ST=%04x\n", WP, PC, ST);
+ LOGMASKED(LOG_CONTEXT, "Context switch (blwp): WP=%04x, PC=%04x, ST=%04x\n", WP, PC, ST);
break;
}
m_inst_state++;
@@ -2502,7 +2486,7 @@ void tms9995_device::alu_c()
set_status_parity((uint8_t)(m_source_value>>8));
}
compare_and_set_lae(m_source_value, m_current_value);
- if (TRACE_STATUS) logerror("ST = %04x (val1=%04x, val2=%04x)\n", ST, m_source_value, m_current_value);
+ LOGMASKED(LOG_STATUS, "ST = %04x (val1=%04x, val2=%04x)\n", ST, m_source_value, m_current_value);
}
/*
@@ -2513,12 +2497,12 @@ void tms9995_device::alu_ci()
// We have the register value in m_source_value, the register address in m_address_saved
// and the immediate value in m_current_value
compare_and_set_lae(m_source_value, m_current_value);
- if (TRACE_STATUS) logerror("ST = %04x (val1=%04x, val2=%04x)\n", ST, m_source_value, m_current_value);
+ LOGMASKED(LOG_STATUS, "ST = %04x (val1=%04x, val2=%04x)\n", ST, m_source_value, m_current_value);
}
void tms9995_device::alu_clr_seto()
{
- if (TRACE_OP) logerror("clr/seto: Setting values for address %04x\n", m_address);
+ LOGMASKED(LOG_DETAIL, "clr/seto: Setting values for address %04x\n", m_address);
switch (m_command)
{
case CLR:
@@ -2727,14 +2711,14 @@ void tms9995_device::alu_external()
if (m_command == IDLE)
{
- if (TRACE_OP) logerror("Entering IDLE state\n");
+ LOGMASKED(LOG_OP, "Entering IDLE state\n");
m_idle_state = true;
}
if (m_command == RSET)
{
ST &= 0xfff0;
- if (TRACE_OP) logerror("RSET, new ST = %04x\n", ST);
+ LOGMASKED(LOG_OP, "RSET, new ST = %04x\n", ST);
}
if (!m_external_operation.isnull())
@@ -2776,7 +2760,7 @@ void tms9995_device::alu_f3()
compare_and_set_lae(m_current_value, 0);
}
}
- if (TRACE_STATUS) logerror("ST = %04x\n", ST);
+ LOGMASKED(LOG_STATUS, "ST = %04x\n", ST);
break;
}
m_inst_state++;
@@ -2812,7 +2796,7 @@ void tms9995_device::alu_imm_arithm()
m_current_value = (uint16_t)(dest_new & 0xffff);
compare_and_set_lae(m_current_value, 0);
m_address = m_address_saved;
- if (TRACE_STATUS) logerror("ST = %04x (val=%04x)\n", ST, m_current_value);
+ LOGMASKED(LOG_STATUS, "ST = %04x (val=%04x)\n", ST, m_current_value);
}
/*
@@ -2868,11 +2852,11 @@ void tms9995_device::alu_jump()
if (!cond)
{
- if (TRACE_OP) logerror("Jump condition false\n");
+ LOGMASKED(LOG_DETAIL, "Jump condition false\n");
}
else
{
- if (TRACE_OP) logerror("Jump condition true\n");
+ LOGMASKED(LOG_DETAIL, "Jump condition true\n");
PC = (PC + (displacement<<1)) & 0xfffe;
}
}
@@ -2892,7 +2876,7 @@ void tms9995_device::alu_ldcr()
case 1:
// We have read the byte or word into m_current_value.
compare_and_set_lae(m_current_value, 0);
- if (TRACE_STATUS) logerror("ST = %04x (val=%04x)\n", ST, m_current_value);
+ LOGMASKED(LOG_STATUS, "ST = %04x (val=%04x)\n", ST, m_current_value);
// Parity is computed from the complete byte, even when less than
// 8 bits are transferred (see [1]).
@@ -2924,7 +2908,7 @@ void tms9995_device::alu_li()
// The immediate value is still in m_current_value
m_address = m_address_saved;
compare_and_set_lae(m_current_value, 0);
- if (TRACE_STATUS) logerror("ST = %04x (val=%04x)\n", ST, m_current_value);
+ LOGMASKED(LOG_STATUS, "ST = %04x (val=%04x)\n", ST, m_current_value);
}
void tms9995_device::alu_limi_lwpi()
@@ -2933,13 +2917,13 @@ void tms9995_device::alu_limi_lwpi()
if (m_command == LIMI)
{
ST = (ST & 0xfff0) | (m_current_value & 0x000f);
- if (TRACE_OP) logerror("LIMI sets ST = %04x\n", ST);
+ LOGMASKED(LOG_DETAIL, "LIMI sets ST = %04x\n", ST);
pulse_clock(1); // needs one more than LWPI
}
else
{
WP = m_current_value & 0xfffe;
- if (TRACE_OP) logerror("LWPI sets new WP = %04x\n", WP);
+ LOGMASKED(LOG_DETAIL, "LWPI sets new WP = %04x\n", WP);
}
}
@@ -2952,13 +2936,13 @@ void tms9995_device::alu_lst_lwp()
if (m_command==LST)
{
ST = m_current_value;
- if (TRACE_OP) logerror("new ST = %04x\n", ST);
+ LOGMASKED(LOG_DETAIL, "new ST = %04x\n", ST);
pulse_clock(1);
}
else
{
WP = m_current_value & 0xfffe;
- if (TRACE_OP) logerror("new WP = %04x\n", WP);
+ LOGMASKED(LOG_DETAIL, "new WP = %04x\n", WP);
}
}
@@ -2976,7 +2960,7 @@ void tms9995_device::alu_mov()
set_status_parity((uint8_t)(m_current_value>>8));
}
compare_and_set_lae(m_current_value, 0);
- if (TRACE_STATUS) logerror("ST = %04x (val=%04x)\n", ST, m_current_value);
+ LOGMASKED(LOG_STATUS, "ST = %04x (val=%04x)\n", ST, m_current_value);
// No clock pulse, as next instruction is prefetch
}
@@ -3069,7 +3053,7 @@ void tms9995_device::alu_rtwp()
// Just for debugging purposes
m_log_interrupt = false;
- if (TRACE_OP) logerror("RTWP restored old context (WP=%04x, PC=%04x, ST=%04x)\n", WP, PC, ST);
+ LOGMASKED(LOG_CONTEXT, "Context switch (rtwp): WP=%04x, PC=%04x, ST=%04x\n", WP, PC, ST);
break;
}
m_inst_state++;
@@ -3122,7 +3106,7 @@ void tms9995_device::alu_shift()
}
else
{
- if (TRACE_DETAIL) logerror("Shift operation gets count from R0\n");
+ LOGMASKED(LOG_DETAIL, "Shift operation gets count from R0\n");
}
pulse_clock(1);
pulse_clock(1);
@@ -3167,7 +3151,7 @@ void tms9995_device::alu_shift()
set_status_bit(ST_OV, overflow);
compare_and_set_lae(m_current_value, 0);
m_address = m_address_saved; // Register address
- if (TRACE_STATUS) logerror("ST = %04x (val=%04x)\n", ST, m_current_value);
+ LOGMASKED(LOG_STATUS, "ST = %04x (val=%04x)\n", ST, m_current_value);
break;
}
m_inst_state++;
@@ -3263,7 +3247,7 @@ void tms9995_device::alu_single_arithm()
m_current_value = dest_new & 0xffff;
compare_and_set_lae(m_current_value, 0);
- if (TRACE_STATUS) logerror("ST = %04x (val=%04x)\n", ST, m_current_value);
+ LOGMASKED(LOG_STATUS, "ST = %04x (val=%04x)\n", ST, m_current_value);
// No clock pulse, as next instruction is prefetch
}
@@ -3301,7 +3285,7 @@ void tms9995_device::alu_stcr()
m_current_value <<= 8;
}
else n += 8;
- if (TRACE_STATUS) logerror("ST = %04x (val=%04x)\n", ST, m_current_value);
+ LOGMASKED(LOG_STATUS, "ST = %04x (val=%04x)\n", ST, m_current_value);
break;
}
m_inst_state++;
@@ -3341,7 +3325,7 @@ void tms9995_device::alu_tb()
break;
case 2:
set_status_bit(ST_EQ, m_cru_value!=0);
- if (TRACE_STATUS) logerror("ST = %04x\n", ST);
+ LOGMASKED(LOG_STATUS, "ST = %04x\n", ST);
break;
}
m_inst_state++;
@@ -3406,6 +3390,7 @@ void tms9995_device::alu_xop()
case 6:
PC = m_current_value & 0xfffe;
set_status_bit(ST_X, true);
+ LOGMASKED(LOG_CONTEXT, "Context switch (xop): WP=%04x, PC=%04x, ST=%04x\n", WP, PC, ST);
break;
}
m_inst_state++;
@@ -3424,7 +3409,7 @@ void tms9995_device::alu_int()
case 0:
PC = (PC - 2) & 0xfffe;
m_address_saved = m_address;
- if (TRACE_INTD) logerror("interrupt service (0): Prepare to read vector\n");
+ LOGMASKED(LOG_INTD, "interrupt service (0): Prepare to read vector\n");
break;
case 1:
pulse = 2; // two cycles (with the one at the end)
@@ -3432,30 +3417,30 @@ void tms9995_device::alu_int()
WP = m_current_value & 0xfffe; // new WP
m_current_value = ST;
m_address = (WP + 30)&0xfffe;
- if (TRACE_INTD) logerror("interrupt service (1): Read new WP = %04x, save ST to %04x\n", WP, m_address);
+ LOGMASKED(LOG_INTD, "interrupt service (1): Read new WP = %04x, save ST to %04x\n", WP, m_address);
break;
case 2:
m_address = (WP + 28)&0xfffe;
m_current_value = PC;
- if (TRACE_INTD) logerror("interrupt service (2): Save PC to %04x\n", m_address);
+ LOGMASKED(LOG_INTD, "interrupt service (2): Save PC to %04x\n", m_address);
break;
case 3:
m_address = (WP + 26)&0xfffe;
m_current_value = m_source_value; // old WP
- if (TRACE_INTD) logerror("interrupt service (3): Save WP to %04x\n", m_address);
+ LOGMASKED(LOG_INTD, "interrupt service (3): Save WP to %04x\n", m_address);
break;
case 4:
m_address = (m_address_saved + 2) & 0xfffe;
- if (TRACE_INTD) logerror("interrupt service (4): Read PC from %04x\n", m_address);
+ LOGMASKED(LOG_INTD, "interrupt service (4): Read PC from %04x\n", m_address);
break;
case 5:
PC = m_current_value & 0xfffe;
ST = (ST & 0xfe00) | m_intmask;
- if (TRACE_INTD) logerror("interrupt service (5): Context switch complete; WP=%04x, PC=%04x, ST=%04x\n", WP, PC, ST);
+ LOGMASKED(LOG_CONTEXT, "Context switch (int): WP=%04x, PC=%04x, ST=%04x\n", WP, PC, ST);
if (((m_int_pending & PENDING_MID)!=0) && m_nmi_active)
{
- if (TRACE_INTD) logerror("interrupt service (6): NMI active after context switch\n");
+ LOGMASKED(LOG_INTD, "interrupt service (6): NMI active after context switch\n");
m_int_pending &= ~PENDING_MID;
m_address = 0xfffc;
m_intmask = 0;
@@ -3465,7 +3450,7 @@ void tms9995_device::alu_int()
{
if (m_from_reset)
{
- if (TRACE_INTD) logerror("interrupt service (6): RESET completed\n");
+ LOGMASKED(LOG_INTD, "interrupt service (6): RESET completed\n");
// We came from the RESET interrupt
m_from_reset = false;
ST &= 0x01ff;