mirror of
https://github.com/holub/mame
synced 2025-10-04 16:34:53 +03:00
ti99: Hexbus floppy system; logging updates
This commit is contained in:
parent
bdc4288fe1
commit
fda26ee7dd
@ -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
|
||||
|
||||
|
@ -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,9 +258,28 @@ 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);
|
||||
|
||||
m_current_bus_value = data;
|
||||
|
||||
// Propagate
|
||||
// Propagate this value first
|
||||
if (hexbuscont != nullptr)
|
||||
hexbuscont->write(dir, data);
|
||||
|
||||
uint8_t oldvalue = m_current_bus_value;
|
||||
m_current_bus_value = 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;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -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 TRACE_HEXBUS 0
|
||||
#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
|
||||
|
||||
DEFINE_DEVICE_TYPE_NS(HX5102, bus::hexbus, hx5102_device, "hx5102", "TI Hexbus Floppy")
|
||||
// Minimum log should be config and warnings
|
||||
#define VERBOSE ( LOG_GENERAL | LOG_WARN )
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
#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 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
|
||||
|
@ -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
|
||||
|
340
src/devices/bus/hexbus/tp0370.cpp
Normal file
340
src/devices/bus/hexbus/tp0370.cpp
Normal file
@ -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;
|
||||
}
|
||||
|
||||
} }
|
||||
|
85
src/devices/bus/hexbus/tp0370.h
Normal file
85
src/devices/bus/hexbus/tp0370.h
Normal file
@ -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
|
@ -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))
|
||||
{
|
||||
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);
|
||||
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
|
||||
{
|
||||
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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
#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
|
||||
|
||||
// Log cycles
|
||||
#define TRACE_CYCLES 0
|
||||
// Minimum log should be config and warnings
|
||||
#define VERBOSE ( LOG_CONFIG | LOG_WARN )
|
||||
|
||||
// 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
|
||||
#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;
|
||||
|
Loading…
Reference in New Issue
Block a user